LinuxThreads library.
[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(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
103     /* Check for termination of the main thread */
104     if (getppid() == 1) {
105       pthread_kill_all_threads(SIGKILL, 0);
106       _exit(0);
107     }
108     /* Check for dead children */
109     if (terminated_children) {
110       terminated_children = 0;
111       pthread_reap_children();
112     }
113     /* Read and execute request */
114     if (n == 1 && FD_ISSET(reqfd, &readfds)) {
115       n = __libc_read(reqfd, (char *)&request, sizeof(request));
116       ASSERT(n == sizeof(request));
117       switch(request.req_kind) {
118       case REQ_CREATE:
119         request.req_thread->p_retcode =
120           pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
121                                 request.req_args.create.attr,
122                                 request.req_args.create.fn,
123                                 request.req_args.create.arg,
124                                 &request.req_args.create.mask,
125                                 request.req_thread->p_pid);
126         restart(request.req_thread);
127         break;
128       case REQ_FREE:
129         pthread_handle_free(request.req_args.free.thread);
130         break;
131       case REQ_PROCESS_EXIT:
132         pthread_handle_exit(request.req_thread,
133                             request.req_args.exit.code);
134         break;
135       case REQ_MAIN_THREAD_EXIT:
136         main_thread_exiting = 1;
137         if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
138           restart(__pthread_main_thread);
139           return 0;
140         }
141         break;
142       }
143     }
144   }
145 }
146
147 /* Process creation */
148
149 static int pthread_start_thread(void *arg)
150 {
151   pthread_descr self = (pthread_descr) arg;
152   void * outcome;
153   /* Initialize special thread_self processing, if any.  */
154 #ifdef INIT_THREAD_SELF
155   INIT_THREAD_SELF(self);
156 #endif
157   /* Make sure our pid field is initialized, just in case we get there
158      before our father has initialized it. */
159   self->p_pid = __getpid();
160   /* Initial signal mask is that of the creating thread. (Otherwise,
161      we'd just inherit the mask of the thread manager.) */
162   sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL);
163   /* Set the scheduling policy and priority for the new thread, if needed */
164   if (self->p_start_args.schedpolicy >= 0)
165     __sched_setscheduler(self->p_pid, self->p_start_args.schedpolicy,
166                          &self->p_start_args.schedparam);
167   /* Run the thread code */
168   outcome = self->p_start_args.start_routine(self->p_start_args.arg);
169   /* Exit with the given return value */
170   pthread_exit(outcome);
171   return 0;
172 }
173
174 static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
175                                  void * (*start_routine)(void *), void *arg,
176                                  sigset_t * mask, int father_pid)
177 {
178   size_t sseg;
179   int pid;
180   pthread_descr new_thread;
181   pthread_t new_thread_id;
182   int i;
183
184   /* Find a free stack segment for the current stack */
185   for (sseg = 1; ; sseg++) {
186     if (sseg >= PTHREAD_THREADS_MAX) return EAGAIN;
187     if (__pthread_handles[sseg].h_descr != NULL) continue;
188     new_thread = thread_segment(sseg);
189     /* Allocate space for stack and thread descriptor. */
190     if (mmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
191              INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
192              MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, -1, 0)
193         != MAP_FAILED) break;
194     /* It seems part of this segment is already mapped. Try the next. */
195   }
196   /* Allocate new thread identifier */
197   pthread_threads_counter += PTHREAD_THREADS_MAX;
198   new_thread_id = sseg + pthread_threads_counter;
199   /* Initialize the thread descriptor */
200   new_thread->p_nextwaiting = NULL;
201   new_thread->p_tid = new_thread_id;
202   new_thread->p_priority = 0;
203   new_thread->p_spinlock = &(__pthread_handles[sseg].h_spinlock);
204   new_thread->p_signal = 0;
205   new_thread->p_signal_jmp = NULL;
206   new_thread->p_cancel_jmp = NULL;
207   new_thread->p_terminated = 0;
208   new_thread->p_detached = attr == NULL ? 0 : attr->detachstate;
209   new_thread->p_exited = 0;
210   new_thread->p_retval = NULL;
211   new_thread->p_joining = NULL;
212   new_thread->p_cleanup = NULL;
213   new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
214   new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
215   new_thread->p_canceled = 0;
216   new_thread->p_errnop = &new_thread->p_errno;
217   new_thread->p_errno = 0;
218   new_thread->p_h_errnop = &new_thread->p_h_errno;
219   new_thread->p_h_errno = 0;
220   for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
221     new_thread->p_specific[i] = NULL;
222   /* Initialize the thread handle */
223   __pthread_handles[sseg].h_spinlock = 0; /* should already be 0 */
224   __pthread_handles[sseg].h_descr = new_thread;
225   /* Determine scheduling parameters for the thread */
226   new_thread->p_start_args.schedpolicy = -1;
227   if (attr != NULL) {
228     switch(attr->inheritsched) {
229     case PTHREAD_EXPLICIT_SCHED:
230       new_thread->p_start_args.schedpolicy = attr->schedpolicy;
231       new_thread->p_start_args.schedparam = attr->schedparam;
232       break;
233     case PTHREAD_INHERIT_SCHED:
234       /* schedpolicy doesn't need to be set, only get priority */
235       __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
236       break;
237     }
238     new_thread->p_priority =
239       new_thread->p_start_args.schedparam.sched_priority;
240   }
241   /* Finish setting up arguments to pthread_start_thread */
242   new_thread->p_start_args.start_routine = start_routine;
243   new_thread->p_start_args.arg = arg;
244   new_thread->p_start_args.mask = *mask;
245   /* Do the cloning */
246   pid = __clone(pthread_start_thread, (void **) new_thread,
247                 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
248                 PTHREAD_SIG_RESTART,
249                 new_thread);
250   /* Check if cloning succeeded */
251   if (pid == -1) {
252     /* Free the stack */
253     munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
254            INITIAL_STACK_SIZE);
255     __pthread_handles[sseg].h_descr = NULL;
256     return errno;
257   }
258   /* Insert new thread in doubly linked list of active threads */
259   new_thread->p_prevlive = __pthread_main_thread;
260   new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
261   __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
262   __pthread_main_thread->p_nextlive = new_thread;
263   /* Set pid field of the new thread, in case we get there before the
264      child starts. */
265   new_thread->p_pid = pid;
266   /* We're all set */
267   *thread = new_thread_id;
268   return 0;
269 }
270
271 /* Free the resources of a thread. */
272
273 static void pthread_free(pthread_descr th)
274 {
275   pthread_handle handle;
276   ASSERT(th->p_exited);
277   /* Make the handle invalid */
278   handle =  thread_handle(th->p_tid);
279   acquire(&handle->h_spinlock);
280   handle->h_descr = NULL;
281   release(&handle->h_spinlock);
282   /* If initial thread, nothing to free */
283   if (th == &__pthread_initial_thread) return;
284   /* Free the stack and thread descriptor area */
285   munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
286 }
287
288 /* Handle threads that have exited */
289
290 static void pthread_exited(pid_t pid)
291 {
292   pthread_descr th;
293   int detached;
294   /* Find thread with that pid */
295   for (th = __pthread_main_thread->p_nextlive;
296        th != __pthread_main_thread;
297        th = th->p_nextlive) {
298     if (th->p_pid == pid) {
299       /* Remove thread from list of active threads */
300       th->p_nextlive->p_prevlive = th->p_prevlive;
301       th->p_prevlive->p_nextlive = th->p_nextlive;
302       /* Mark thread as exited, and if detached, free its resources */
303       acquire(th->p_spinlock);
304       th->p_exited = 1;
305       detached = th->p_detached;
306       release(th->p_spinlock);
307       if (detached) pthread_free(th);
308       break;
309     }
310   }
311   /* If all threads have exited and the main thread is pending on a
312      pthread_exit, wake up the main thread and terminate ourselves. */
313   if (main_thread_exiting &&
314       __pthread_main_thread->p_nextlive == __pthread_main_thread) {
315     restart(__pthread_main_thread);
316     _exit(0);
317   }
318 }
319
320 static void pthread_reap_children(void)
321 {
322   pid_t pid;
323   int status;
324
325   while ((pid = __libc_waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) {
326     pthread_exited(pid);
327     if (WIFSIGNALED(status)) {
328       /* If a thread died due to a signal, send the same signal to
329          all other threads, including the main thread. */
330       pthread_kill_all_threads(WTERMSIG(status), 1);
331       _exit(0);
332     }
333   }
334 }
335
336 /* Free the resources of a thread */
337
338 static void pthread_handle_free(pthread_descr th)
339 {
340   acquire(th->p_spinlock);
341   if (th->p_exited) {
342     release(th->p_spinlock);
343     pthread_free(th);
344   } else {
345     /* The Unix process of the thread is still running.
346        Mark the thread as detached so that the thread manager will
347        deallocate its resources when the Unix process exits. */
348     th->p_detached = 1;
349     release(th->p_spinlock);
350   }
351 }
352
353 /* Send a signal to all running threads */
354
355 static void pthread_kill_all_threads(int sig, int main_thread_also)
356 {
357   pthread_descr th;
358   for (th = __pthread_main_thread->p_nextlive;
359        th != __pthread_main_thread;
360        th = th->p_nextlive) {
361     kill(th->p_pid, sig);
362   }
363   if (main_thread_also) {
364     kill(__pthread_main_thread->p_pid, sig);
365   }
366 }
367
368 /* Process-wide exit() */
369
370 static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
371 {
372   pthread_descr th;
373   __pthread_exit_requested = 1;
374   __pthread_exit_code = exitcode;
375   /* Send the CANCEL signal to all running threads, including the main
376      thread, but excluding the thread from which the exit request originated
377      (that thread must complete the exit, e.g. calling atexit functions
378      and flushing stdio buffers). */
379   for (th = issuing_thread->p_nextlive;
380        th != issuing_thread;
381        th = th->p_nextlive) {
382     kill(th->p_pid, PTHREAD_SIG_CANCEL);
383   }
384   /* Now, wait for all these threads, so that they don't become zombies
385      and their times are properly added to the thread manager's times. */
386   for (th = issuing_thread->p_nextlive;
387        th != issuing_thread;
388        th = th->p_nextlive) {
389     waitpid(th->p_pid, NULL, __WCLONE);
390   }
391   restart(issuing_thread);
392   _exit(0);
393 }
394
395 /* Handler for PTHREAD_SIG_RESTART in thread manager thread */
396
397 void __pthread_manager_sighandler(int sig)
398 {
399   terminated_children = 1;
400 }