Delete libpthread-map.
[kopensolaris-gnu/glibc.git] / linuxthreads / manager.c
1 /* Linuxthreads - a simple clone()-based implementation of Posix        */
2 /* threads for Linux.                                                   */
3 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr)              */
4 /*                                                                      */
5 /* This program is free software; you can redistribute it and/or        */
6 /* modify it under the terms of the GNU Library General Public License  */
7 /* as published by the Free Software Foundation; either version 2       */
8 /* of the License, or (at your option) any later version.               */
9 /*                                                                      */
10 /* This program is distributed in the hope that it will be useful,      */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
13 /* GNU Library General Public License for more details.                 */
14
15 /* The "thread manager" thread: manages creation and termination of threads */
16
17 #include <errno.h>
18 #include <sched.h>
19 #include <stddef.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/select.h>         /* for select */
25 #include <sys/mman.h>           /* for mmap */
26 #include <sys/time.h>
27 #include <sys/wait.h>           /* for waitpid macros */
28 #include <linux/tasks.h>
29
30 #include "pthread.h"
31 #include "internals.h"
32 #include "spinlock.h"
33 #include "restart.h"
34
35 /* Array of active threads. Entry 0 is reserved for the initial thread. */
36
37 struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =
38 { { 0, &__pthread_initial_thread}, /* All NULLs */ };
39
40 /* Mapping from stack segment to thread descriptor. */
41 /* Stack segment numbers are also indices into the __pthread_handles array. */
42 /* Stack segment number 0 is reserved for the initial thread. */
43
44 static inline pthread_descr thread_segment(int seg)
45 {
46   return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE)
47          - 1;
48 }
49
50 /* Flag set in signal handler to record child termination */
51
52 static volatile int terminated_children = 0;
53
54 /* Flag set when the initial thread is blocked on pthread_exit waiting
55    for all other threads to terminate */
56
57 static int main_thread_exiting = 0;
58
59 /* Counter used to generate unique thread identifier.
60    Thread identifier is pthread_threads_counter + segment. */
61
62 static pthread_t pthread_threads_counter = 0;
63
64 /* Forward declarations */
65
66 static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
67                                  void * (*start_routine)(void *), void *arg,
68                                  sigset_t *mask, int father_pid);
69 static void pthread_handle_free(pthread_descr th);
70 static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode);
71 static void pthread_reap_children(void);
72 static void pthread_kill_all_threads(int sig, int main_thread_also);
73
74 /* The server thread managing requests for thread creation and termination */
75
76 int __pthread_manager(void *arg)
77 {
78   int reqfd = (int)arg;
79   sigset_t mask;
80   fd_set readfds;
81   struct timeval timeout;
82   int n;
83   struct pthread_request request;
84
85   /* If we have special thread_self processing, initialize it.  */
86 #ifdef INIT_THREAD_SELF
87   INIT_THREAD_SELF(&__pthread_manager_thread);
88 #endif
89   /* Set the error variable.  */
90   __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno;
91   __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno;
92   /* Block all signals except PTHREAD_SIG_RESTART */
93   sigfillset(&mask);
94   sigdelset(&mask, PTHREAD_SIG_RESTART);
95   sigprocmask(SIG_SETMASK, &mask, NULL);
96   /* Enter server loop */
97   while(1) {
98     FD_ZERO(&readfds);
99     FD_SET(reqfd, &readfds);
100     timeout.tv_sec = 2;
101     timeout.tv_usec = 0;
102     n = __select(reqfd + 1, &readfds, NULL, NULL, &timeout);
103
104     /* Check for termination of the main thread */
105     if (getppid() == 1) {
106       pthread_kill_all_threads(SIGKILL, 0);
107       _exit(0);
108     }
109     /* Check for dead children */
110     if (terminated_children) {
111       terminated_children = 0;
112       pthread_reap_children();
113     }
114     /* Read and execute request */
115     if (n == 1 && FD_ISSET(reqfd, &readfds)) {
116       n = __libc_read(reqfd, (char *)&request, sizeof(request));
117       ASSERT(n == sizeof(request));
118       switch(request.req_kind) {
119       case REQ_CREATE:
120         request.req_thread->p_retcode =
121           pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
122                                 request.req_args.create.attr,
123                                 request.req_args.create.fn,
124                                 request.req_args.create.arg,
125                                 &request.req_args.create.mask,
126                                 request.req_thread->p_pid);
127         restart(request.req_thread);
128         break;
129       case REQ_FREE:
130         pthread_handle_free(request.req_args.free.thread);
131         break;
132       case REQ_PROCESS_EXIT:
133         pthread_handle_exit(request.req_thread,
134                             request.req_args.exit.code);
135         break;
136       case REQ_MAIN_THREAD_EXIT:
137         main_thread_exiting = 1;
138         if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
139           restart(__pthread_main_thread);
140           return 0;
141         }
142         break;
143       }
144     }
145   }
146 }
147
148 /* Process creation */
149
150 static int pthread_start_thread(void *arg)
151 {
152   pthread_descr self = (pthread_descr) arg;
153   void * outcome;
154   /* Initialize special thread_self processing, if any.  */
155 #ifdef INIT_THREAD_SELF
156   INIT_THREAD_SELF(self);
157 #endif
158   /* Make sure our pid field is initialized, just in case we get there
159      before our father has initialized it. */
160   self->p_pid = __getpid();
161   /* Initial signal mask is that of the creating thread. (Otherwise,
162      we'd just inherit the mask of the thread manager.) */
163   sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL);
164   /* Set the scheduling policy and priority for the new thread, if needed */
165   if (self->p_start_args.schedpolicy >= 0)
166     __sched_setscheduler(self->p_pid, self->p_start_args.schedpolicy,
167                          &self->p_start_args.schedparam);
168   /* Run the thread code */
169   outcome = self->p_start_args.start_routine(self->p_start_args.arg);
170   /* Exit with the given return value */
171   pthread_exit(outcome);
172   return 0;
173 }
174
175 static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
176                                  void * (*start_routine)(void *), void *arg,
177                                  sigset_t * mask, int father_pid)
178 {
179   size_t sseg;
180   int pid;
181   pthread_descr new_thread;
182   pthread_t new_thread_id;
183   void *guardaddr = NULL;
184
185   /* Find a free stack segment for the current stack */
186   for (sseg = 1; ; sseg++)
187     {
188       if (sseg >= PTHREAD_THREADS_MAX)
189         return EAGAIN;
190       if (__pthread_handles[sseg].h_descr != NULL)
191         continue;
192
193       if (attr == NULL || !attr->stackaddr_set)
194         {
195           new_thread = thread_segment(sseg);
196           /* Allocate space for stack and thread descriptor. */
197           if (mmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
198                    INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
199                    MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN,
200                    -1, 0) != MAP_FAILED)
201             {
202               /* We manage to get a stack.  Now see whether we need a guard
203                  and allocate it if necessary.  */
204               if (attr == NULL || attr->guardsize != 0)
205                 {
206                   guardaddr = mmap ((caddr_t)((char *)(new_thread+1)
207                                               - STACK_SIZE),
208                                     attr ? attr->guardsize : __getpagesize (),
209                                     0, MAP_FIXED, -1, 0);
210                   if (guardaddr == MAP_FAILED)
211                     /* We don't make this an error.  */
212                     guardaddr = NULL;
213                 }
214               break;
215             }
216           /* It seems part of this segment is already mapped. Try the next. */
217         }
218       else
219         {
220           new_thread = (pthread_descr) attr->stackaddr - 1;
221           break;
222         }
223     }
224   /* Allocate new thread identifier */
225   pthread_threads_counter += PTHREAD_THREADS_MAX;
226   new_thread_id = sseg + pthread_threads_counter;
227   /* Initialize the thread descriptor */
228   new_thread->p_nextwaiting = NULL;
229   new_thread->p_tid = new_thread_id;
230   new_thread->p_priority = 0;
231   new_thread->p_spinlock = &(__pthread_handles[sseg].h_spinlock);
232   new_thread->p_signal = 0;
233   new_thread->p_signal_jmp = NULL;
234   new_thread->p_cancel_jmp = NULL;
235   new_thread->p_terminated = 0;
236   new_thread->p_detached = attr == NULL ? 0 : attr->detachstate;
237   new_thread->p_exited = 0;
238   new_thread->p_retval = NULL;
239   new_thread->p_joining = NULL;
240   new_thread->p_cleanup = NULL;
241   new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
242   new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
243   new_thread->p_canceled = 0;
244   new_thread->p_errnop = &new_thread->p_errno;
245   new_thread->p_errno = 0;
246   new_thread->p_h_errnop = &new_thread->p_h_errno;
247   new_thread->p_h_errno = 0;
248   new_thread->p_guardaddr = guardaddr;
249   new_thread->p_guardsize = (guardaddr == NULL
250                              ? 0
251                              : (attr == NULL
252                                 ? __getpagesize () : attr->guardsize));
253   new_thread->p_userstack = attr != NULL && attr->stackaddr_set;
254   memset (new_thread->p_specific, '\0',
255           PTHREAD_KEY_1STLEVEL_SIZE * sizeof (new_thread->p_specific[0]));
256   /* Initialize the thread handle */
257   __pthread_handles[sseg].h_spinlock = 0; /* should already be 0 */
258   __pthread_handles[sseg].h_descr = new_thread;
259   /* Determine scheduling parameters for the thread */
260   new_thread->p_start_args.schedpolicy = -1;
261   if (attr != NULL) {
262     switch(attr->inheritsched) {
263     case PTHREAD_EXPLICIT_SCHED:
264       new_thread->p_start_args.schedpolicy = attr->schedpolicy;
265       new_thread->p_start_args.schedparam = attr->schedparam;
266       break;
267     case PTHREAD_INHERIT_SCHED:
268       /* schedpolicy doesn't need to be set, only get priority */
269       __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
270       break;
271     }
272     new_thread->p_priority =
273       new_thread->p_start_args.schedparam.sched_priority;
274   }
275   /* Finish setting up arguments to pthread_start_thread */
276   new_thread->p_start_args.start_routine = start_routine;
277   new_thread->p_start_args.arg = arg;
278   new_thread->p_start_args.mask = *mask;
279   /* Do the cloning */
280   pid = __clone(pthread_start_thread, (void **) new_thread,
281                 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
282                 PTHREAD_SIG_RESTART,
283                 new_thread);
284   /* Check if cloning succeeded */
285   if (pid == -1) {
286     /* Free the stack if we allocated it */
287     if (attr == NULL || !attr->stackaddr_set)
288       {
289         munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
290                INITIAL_STACK_SIZE);
291         if (new_thread->p_guardsize != 0)
292           munmap(new_thread->p_guardaddr, new_thread->p_guardsize);
293       }
294     __pthread_handles[sseg].h_descr = NULL;
295     return errno;
296   }
297   /* Insert new thread in doubly linked list of active threads */
298   new_thread->p_prevlive = __pthread_main_thread;
299   new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
300   __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
301   __pthread_main_thread->p_nextlive = new_thread;
302   /* Set pid field of the new thread, in case we get there before the
303      child starts. */
304   new_thread->p_pid = pid;
305   /* We're all set */
306   *thread = new_thread_id;
307   return 0;
308 }
309
310
311 /* Try to free the resources of a thread when requested by pthread_join
312    or pthread_detach on a terminated thread. */
313
314 static void pthread_free(pthread_descr th)
315 {
316   pthread_handle handle;
317   pthread_descr t;
318
319   /* Check that the thread th is still there -- pthread_reap_children
320      might have deallocated it already */
321   t = __pthread_main_thread;
322   do {
323     if (t == th) break;
324     t = t->p_nextlive;
325   } while (t != __pthread_main_thread);
326   if (t != th) return;
327
328   ASSERT(th->p_exited);
329   /* Make the handle invalid */
330   handle =  thread_handle(th->p_tid);
331   acquire(&handle->h_spinlock);
332   handle->h_descr = NULL;
333   release(&handle->h_spinlock);
334   /* If initial thread, nothing to free */
335   if (th == &__pthread_initial_thread) return;
336   if (!th->p_userstack)
337     {
338       /* Free the stack and thread descriptor area */
339       if (th->p_guardsize != 0)
340         munmap(th->p_guardaddr, th->p_guardsize);
341       munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
342     }
343 }
344
345 /* Handle threads that have exited */
346
347 static void pthread_exited(pid_t pid)
348 {
349   pthread_descr th;
350   int detached;
351   /* Find thread with that pid */
352   for (th = __pthread_main_thread->p_nextlive;
353        th != __pthread_main_thread;
354        th = th->p_nextlive) {
355     if (th->p_pid == pid) {
356       /* Remove thread from list of active threads */
357       th->p_nextlive->p_prevlive = th->p_prevlive;
358       th->p_prevlive->p_nextlive = th->p_nextlive;
359       /* Mark thread as exited, and if detached, free its resources */
360       acquire(th->p_spinlock);
361       th->p_exited = 1;
362       detached = th->p_detached;
363       release(th->p_spinlock);
364       if (detached) pthread_free(th);
365       break;
366     }
367   }
368   /* If all threads have exited and the main thread is pending on a
369      pthread_exit, wake up the main thread and terminate ourselves. */
370   if (main_thread_exiting &&
371       __pthread_main_thread->p_nextlive == __pthread_main_thread) {
372     restart(__pthread_main_thread);
373     _exit(0);
374   }
375 }
376
377 static void pthread_reap_children(void)
378 {
379   pid_t pid;
380   int status;
381
382   while ((pid = __libc_waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) {
383     pthread_exited(pid);
384     if (WIFSIGNALED(status)) {
385       /* If a thread died due to a signal, send the same signal to
386          all other threads, including the main thread. */
387       pthread_kill_all_threads(WTERMSIG(status), 1);
388       _exit(0);
389     }
390   }
391 }
392
393 /* Free the resources of a thread */
394
395 static void pthread_handle_free(pthread_descr th)
396 {
397   acquire(th->p_spinlock);
398   if (th->p_exited) {
399     release(th->p_spinlock);
400     pthread_free(th);
401   } else {
402     /* The Unix process of the thread is still running.
403        Mark the thread as detached so that the thread manager will
404        deallocate its resources when the Unix process exits. */
405     th->p_detached = 1;
406     release(th->p_spinlock);
407   }
408 }
409
410 /* Send a signal to all running threads */
411
412 static void pthread_kill_all_threads(int sig, int main_thread_also)
413 {
414   pthread_descr th;
415   for (th = __pthread_main_thread->p_nextlive;
416        th != __pthread_main_thread;
417        th = th->p_nextlive) {
418     kill(th->p_pid, sig);
419   }
420   if (main_thread_also) {
421     kill(__pthread_main_thread->p_pid, sig);
422   }
423 }
424
425 /* Process-wide exit() */
426
427 static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
428 {
429   pthread_descr th;
430   __pthread_exit_requested = 1;
431   __pthread_exit_code = exitcode;
432   /* Send the CANCEL signal to all running threads, including the main
433      thread, but excluding the thread from which the exit request originated
434      (that thread must complete the exit, e.g. calling atexit functions
435      and flushing stdio buffers). */
436   for (th = issuing_thread->p_nextlive;
437        th != issuing_thread;
438        th = th->p_nextlive) {
439     kill(th->p_pid, PTHREAD_SIG_CANCEL);
440   }
441   /* Now, wait for all these threads, so that they don't become zombies
442      and their times are properly added to the thread manager's times. */
443   for (th = issuing_thread->p_nextlive;
444        th != issuing_thread;
445        th = th->p_nextlive) {
446     waitpid(th->p_pid, NULL, __WCLONE);
447   }
448   restart(issuing_thread);
449   _exit(0);
450 }
451
452 /* Handler for PTHREAD_SIG_RESTART in thread manager thread */
453
454 void __pthread_manager_sighandler(int sig)
455 {
456   terminated_children = 1;
457 }