thread safe longjmp functions.
[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 /* Free the resources of a thread. */
312
313 static void pthread_free(pthread_descr th)
314 {
315   pthread_handle handle;
316   ASSERT(th->p_exited);
317   /* Make the handle invalid */
318   handle =  thread_handle(th->p_tid);
319   acquire(&handle->h_spinlock);
320   handle->h_descr = NULL;
321   release(&handle->h_spinlock);
322   /* If initial thread, nothing to free */
323   if (th == &__pthread_initial_thread) return;
324   if (!th->p_userstack)
325     {
326       /* Free the stack and thread descriptor area */
327       munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
328       if (th->p_guardsize != 0)
329         munmap(th->p_guardaddr, th->p_guardsize);
330     }
331 }
332
333 /* Handle threads that have exited */
334
335 static void pthread_exited(pid_t pid)
336 {
337   pthread_descr th;
338   int detached;
339   /* Find thread with that pid */
340   for (th = __pthread_main_thread->p_nextlive;
341        th != __pthread_main_thread;
342        th = th->p_nextlive) {
343     if (th->p_pid == pid) {
344       /* Remove thread from list of active threads */
345       th->p_nextlive->p_prevlive = th->p_prevlive;
346       th->p_prevlive->p_nextlive = th->p_nextlive;
347       /* Mark thread as exited, and if detached, free its resources */
348       acquire(th->p_spinlock);
349       th->p_exited = 1;
350       detached = th->p_detached;
351       release(th->p_spinlock);
352       if (detached) pthread_free(th);
353       break;
354     }
355   }
356   /* If all threads have exited and the main thread is pending on a
357      pthread_exit, wake up the main thread and terminate ourselves. */
358   if (main_thread_exiting &&
359       __pthread_main_thread->p_nextlive == __pthread_main_thread) {
360     restart(__pthread_main_thread);
361     _exit(0);
362   }
363 }
364
365 static void pthread_reap_children(void)
366 {
367   pid_t pid;
368   int status;
369
370   while ((pid = __libc_waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) {
371     pthread_exited(pid);
372     if (WIFSIGNALED(status)) {
373       /* If a thread died due to a signal, send the same signal to
374          all other threads, including the main thread. */
375       pthread_kill_all_threads(WTERMSIG(status), 1);
376       _exit(0);
377     }
378   }
379 }
380
381 /* Free the resources of a thread */
382
383 static void pthread_handle_free(pthread_descr th)
384 {
385   acquire(th->p_spinlock);
386   if (th->p_exited) {
387     release(th->p_spinlock);
388     pthread_free(th);
389   } else {
390     /* The Unix process of the thread is still running.
391        Mark the thread as detached so that the thread manager will
392        deallocate its resources when the Unix process exits. */
393     th->p_detached = 1;
394     release(th->p_spinlock);
395   }
396 }
397
398 /* Send a signal to all running threads */
399
400 static void pthread_kill_all_threads(int sig, int main_thread_also)
401 {
402   pthread_descr th;
403   for (th = __pthread_main_thread->p_nextlive;
404        th != __pthread_main_thread;
405        th = th->p_nextlive) {
406     kill(th->p_pid, sig);
407   }
408   if (main_thread_also) {
409     kill(__pthread_main_thread->p_pid, sig);
410   }
411 }
412
413 /* Process-wide exit() */
414
415 static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
416 {
417   pthread_descr th;
418   __pthread_exit_requested = 1;
419   __pthread_exit_code = exitcode;
420   /* Send the CANCEL signal to all running threads, including the main
421      thread, but excluding the thread from which the exit request originated
422      (that thread must complete the exit, e.g. calling atexit functions
423      and flushing stdio buffers). */
424   for (th = issuing_thread->p_nextlive;
425        th != issuing_thread;
426        th = th->p_nextlive) {
427     kill(th->p_pid, PTHREAD_SIG_CANCEL);
428   }
429   /* Now, wait for all these threads, so that they don't become zombies
430      and their times are properly added to the thread manager's times. */
431   for (th = issuing_thread->p_nextlive;
432        th != issuing_thread;
433        th = th->p_nextlive) {
434     waitpid(th->p_pid, NULL, __WCLONE);
435   }
436   restart(issuing_thread);
437   _exit(0);
438 }
439
440 /* Handler for PTHREAD_SIG_RESTART in thread manager thread */
441
442 void __pthread_manager_sighandler(int sig)
443 {
444   terminated_children = 1;
445 }