Update.
[glibc.git] / linuxthreads / manager.c
blobd14a57ccd7b5821b619b6a6721c7c7b4df9cf980
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. */
15 /* The "thread manager" thread: manages creation and termination of threads */
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/poll.h> /* for poll */
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>
30 #include "pthread.h"
31 #include "internals.h"
32 #include "spinlock.h"
33 #include "restart.h"
34 #include "semaphore.h"
36 /* Array of active threads. Entry 0 is reserved for the initial thread. */
37 struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =
38 { { LOCK_INITIALIZER, &__pthread_initial_thread, 0}, /* All NULLs */ };
40 /* Indicate whether at least one thread has a user-defined stack (if 1),
41 or if all threads have stacks supplied by LinuxThreads (if 0). */
42 int __pthread_nonstandard_stacks = 0;
44 /* Number of active entries in __pthread_handles (used by gdb) */
45 volatile int __pthread_handles_num = 1;
47 /* Whether to use debugger additional actions for thread creation
48 (set to 1 by gdb) */
49 volatile int __pthread_threads_debug = 0;
51 /* Mapping from stack segment to thread descriptor. */
52 /* Stack segment numbers are also indices into the __pthread_handles array. */
53 /* Stack segment number 0 is reserved for the initial thread. */
55 static inline pthread_descr thread_segment(int seg)
57 return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE)
58 - 1;
61 /* Flag set in signal handler to record child termination */
63 static volatile int terminated_children = 0;
65 /* Flag set when the initial thread is blocked on pthread_exit waiting
66 for all other threads to terminate */
68 static int main_thread_exiting = 0;
70 /* Counter used to generate unique thread identifier.
71 Thread identifier is pthread_threads_counter + segment. */
73 static pthread_t pthread_threads_counter = 0;
75 /* Forward declarations */
77 static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
78 void * (*start_routine)(void *), void *arg,
79 sigset_t *mask, int father_pid);
80 static void pthread_handle_free(pthread_t th_id);
81 static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode);
82 static void pthread_reap_children(void);
83 static void pthread_kill_all_threads(int sig, int main_thread_also);
85 /* The server thread managing requests for thread creation and termination */
87 int __pthread_manager(void *arg)
89 int reqfd = (int)arg;
90 struct pollfd ufd;
91 sigset_t mask;
92 int n;
93 struct pthread_request request;
95 /* If we have special thread_self processing, initialize it. */
96 #ifdef INIT_THREAD_SELF
97 INIT_THREAD_SELF(&__pthread_manager_thread);
98 #endif
99 /* Set the error variable. */
100 __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno;
101 __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno;
102 /* Block all signals except PTHREAD_SIG_RESTART, PTHREAD_SIG_CANCEL
103 and SIGTRAP */
104 sigfillset(&mask);
105 sigdelset(&mask, PTHREAD_SIG_RESTART);
106 sigdelset(&mask, PTHREAD_SIG_CANCEL); /* for debugging new threads */
107 sigdelset(&mask, SIGTRAP); /* for debugging purposes */
108 sigprocmask(SIG_SETMASK, &mask, NULL);
109 /* Raise our priority to match that of main thread */
110 __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
111 /* Synchronize debugging of the thread manager */
112 n = __libc_read(reqfd, (char *)&request, sizeof(request));
113 ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG);
114 ufd.fd = reqfd;
115 ufd.events = POLLIN;
116 /* Enter server loop */
117 while(1) {
118 n = __poll(&ufd, 1, 2000);
120 /* Check for termination of the main thread */
121 if (getppid() == 1) {
122 pthread_kill_all_threads(SIGKILL, 0);
123 _exit(0);
125 /* Check for dead children */
126 if (terminated_children) {
127 terminated_children = 0;
128 pthread_reap_children();
130 /* Read and execute request */
131 if (n == 1 && (ufd.revents & POLLIN)) {
132 n = __libc_read(reqfd, (char *)&request, sizeof(request));
133 ASSERT(n == sizeof(request));
134 switch(request.req_kind) {
135 case REQ_CREATE:
136 request.req_thread->p_retcode =
137 pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
138 request.req_args.create.attr,
139 request.req_args.create.fn,
140 request.req_args.create.arg,
141 &request.req_args.create.mask,
142 request.req_thread->p_pid);
143 restart(request.req_thread);
144 break;
145 case REQ_FREE:
146 pthread_handle_free(request.req_args.free.thread_id);
147 break;
148 case REQ_PROCESS_EXIT:
149 pthread_handle_exit(request.req_thread,
150 request.req_args.exit.code);
151 break;
152 case REQ_MAIN_THREAD_EXIT:
153 main_thread_exiting = 1;
154 if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
155 restart(__pthread_main_thread);
156 return 0;
158 break;
159 case REQ_POST:
160 sem_post(request.req_args.post);
161 break;
162 case REQ_DEBUG:
163 /* Make gdb aware of new thread */
164 if (__pthread_threads_debug) raise(PTHREAD_SIG_CANCEL);
165 restart(request.req_thread);
166 break;
172 /* Process creation */
174 static int pthread_start_thread(void *arg)
176 pthread_descr self = (pthread_descr) arg;
177 struct pthread_request request;
178 void * outcome;
179 /* Initialize special thread_self processing, if any. */
180 #ifdef INIT_THREAD_SELF
181 INIT_THREAD_SELF(self);
182 #endif
183 /* Make sure our pid field is initialized, just in case we get there
184 before our father has initialized it. */
185 self->p_pid = __getpid();
186 /* Initial signal mask is that of the creating thread. (Otherwise,
187 we'd just inherit the mask of the thread manager.) */
188 sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL);
189 /* Set the scheduling policy and priority for the new thread, if needed */
190 if (self->p_start_args.schedpolicy >= 0)
191 __sched_setscheduler(self->p_pid, self->p_start_args.schedpolicy,
192 &self->p_start_args.schedparam);
193 /* Make gdb aware of new thread */
194 if (__pthread_threads_debug) {
195 request.req_thread = self;
196 request.req_kind = REQ_DEBUG;
197 __libc_write(__pthread_manager_request,
198 (char *) &request, sizeof(request));
199 suspend(self);
201 /* Run the thread code */
202 outcome = self->p_start_args.start_routine(self->p_start_args.arg);
203 /* Exit with the given return value */
204 pthread_exit(outcome);
205 return 0;
208 static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
209 void * (*start_routine)(void *), void *arg,
210 sigset_t * mask, int father_pid)
212 size_t sseg;
213 int pid;
214 pthread_descr new_thread;
215 char * new_thread_bottom;
216 pthread_t new_thread_id;
217 void *guardaddr = NULL;
218 size_t guardsize = 0;
220 /* First check whether we have to change the policy and if yes, whether
221 we can do this. Normally this should be done by examining the
222 return value of the __sched_setscheduler call in pthread_start_thread
223 but this is hard to implement. FIXME */
224 if (attr != NULL && attr->schedpolicy != SCHED_OTHER && geteuid () != 0)
225 return EPERM;
226 /* Find a free stack segment for the current stack */
227 for (sseg = 1; ; sseg++)
229 if (sseg >= PTHREAD_THREADS_MAX)
230 return EAGAIN;
231 if (__pthread_handles[sseg].h_descr != NULL)
232 continue;
234 if (attr == NULL || !attr->stackaddr_set)
236 new_thread = thread_segment(sseg);
237 new_thread_bottom = (char *) new_thread - STACK_SIZE;
238 /* Allocate space for stack and thread descriptor. */
239 if (mmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
240 INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
241 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN,
242 -1, 0) != MAP_FAILED)
244 /* We manage to get a stack. Now see whether we need a guard
245 and allocate it if necessary. */
246 if (attr == NULL || attr->guardsize != 0)
248 guardsize = attr ? attr->guardsize : __getpagesize ();
249 guardaddr = mmap ((caddr_t)((char *)(new_thread+1)
250 - STACK_SIZE),
251 guardsize, 0, MAP_FIXED, -1, 0);
252 if (guardaddr == MAP_FAILED)
254 /* We don't make this an error. */
255 guardaddr = NULL;
256 guardsize = 0;
259 break;
261 /* It seems part of this segment is already mapped. Try the next. */
263 else
265 new_thread = (pthread_descr) ((long) attr->stackaddr
266 & -sizeof(void *)) - 1;
267 new_thread_bottom = (char *) attr->stackaddr - attr->stacksize;
268 break;
271 /* Allocate new thread identifier */
272 pthread_threads_counter += PTHREAD_THREADS_MAX;
273 new_thread_id = sseg + pthread_threads_counter;
274 /* Initialize the thread descriptor */
275 new_thread->p_nextwaiting = NULL;
276 new_thread->p_tid = new_thread_id;
277 new_thread->p_priority = 0;
278 new_thread->p_lock = &(__pthread_handles[sseg].h_lock);
279 new_thread->p_signal = 0;
280 new_thread->p_signal_jmp = NULL;
281 new_thread->p_cancel_jmp = NULL;
282 new_thread->p_terminated = 0;
283 new_thread->p_detached = attr == NULL ? 0 : attr->detachstate;
284 new_thread->p_exited = 0;
285 new_thread->p_retval = NULL;
286 new_thread->p_joining = NULL;
287 new_thread->p_cleanup = NULL;
288 new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
289 new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
290 new_thread->p_canceled = 0;
291 new_thread->p_errnop = &new_thread->p_errno;
292 new_thread->p_errno = 0;
293 new_thread->p_h_errnop = &new_thread->p_h_errno;
294 new_thread->p_h_errno = 0;
295 new_thread->p_in_sighandler = NULL;
296 new_thread->p_sigwaiting = 0;
297 new_thread->p_guardaddr = guardaddr;
298 new_thread->p_guardsize = guardsize;
299 new_thread->p_userstack = attr != NULL && attr->stackaddr_set;
300 memset (new_thread->p_specific, '\0',
301 PTHREAD_KEY_1STLEVEL_SIZE * sizeof (new_thread->p_specific[0]));
302 /* Initialize the thread handle */
303 __pthread_init_lock(&__pthread_handles[sseg].h_lock);
304 __pthread_handles[sseg].h_descr = new_thread;
305 __pthread_handles[sseg].h_bottom = new_thread_bottom;
306 /* Determine scheduling parameters for the thread */
307 new_thread->p_start_args.schedpolicy = -1;
308 if (attr != NULL) {
309 switch(attr->inheritsched) {
310 case PTHREAD_EXPLICIT_SCHED:
311 new_thread->p_start_args.schedpolicy = attr->schedpolicy;
312 memcpy (&new_thread->p_start_args.schedparam, &attr->schedparam,
313 sizeof (struct sched_param));
314 break;
315 case PTHREAD_INHERIT_SCHED:
316 /* schedpolicy doesn't need to be set, only get priority */
317 __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
318 break;
320 new_thread->p_priority =
321 new_thread->p_start_args.schedparam.sched_priority;
323 /* Finish setting up arguments to pthread_start_thread */
324 new_thread->p_start_args.start_routine = start_routine;
325 new_thread->p_start_args.arg = arg;
326 new_thread->p_start_args.mask = *mask;
327 /* Raise priority of thread manager if needed */
328 __pthread_manager_adjust_prio(new_thread->p_priority);
329 /* Do the cloning */
330 pid = __clone(pthread_start_thread, (void **) new_thread,
331 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
332 PTHREAD_SIG_RESTART,
333 new_thread);
334 /* Check if cloning succeeded */
335 if (pid == -1) {
336 /* Free the stack if we allocated it */
337 if (attr == NULL || !attr->stackaddr_set)
339 munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
340 INITIAL_STACK_SIZE);
341 if (new_thread->p_guardsize != 0)
342 munmap(new_thread->p_guardaddr, new_thread->p_guardsize);
344 __pthread_handles[sseg].h_descr = NULL;
345 __pthread_handles[sseg].h_bottom = NULL;
346 __pthread_handles_num--;
347 return errno;
349 /* Insert new thread in doubly linked list of active threads */
350 new_thread->p_prevlive = __pthread_main_thread;
351 new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
352 __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
353 __pthread_main_thread->p_nextlive = new_thread;
354 /* Set pid field of the new thread, in case we get there before the
355 child starts. */
356 new_thread->p_pid = pid;
357 /* We're all set */
358 *thread = new_thread_id;
359 return 0;
363 /* Try to free the resources of a thread when requested by pthread_join
364 or pthread_detach on a terminated thread. */
366 static void pthread_free(pthread_descr th)
368 pthread_handle handle;
369 ASSERT(th->p_exited);
370 /* Make the handle invalid */
371 handle = thread_handle(th->p_tid);
372 __pthread_lock(&handle->h_lock);
373 handle->h_descr = NULL;
374 handle->h_bottom = (char *)(-1L);
375 __pthread_unlock(&handle->h_lock);
376 /* One fewer threads in __pthread_handles */
377 __pthread_handles_num--;
378 /* If initial thread, nothing to free */
379 if (th == &__pthread_initial_thread) return;
380 if (!th->p_userstack)
382 /* Free the stack and thread descriptor area */
383 if (th->p_guardsize != 0)
384 munmap(th->p_guardaddr, th->p_guardsize);
385 munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
389 /* Handle threads that have exited */
391 static void pthread_exited(pid_t pid)
393 pthread_descr th;
394 int detached;
395 /* Find thread with that pid */
396 for (th = __pthread_main_thread->p_nextlive;
397 th != __pthread_main_thread;
398 th = th->p_nextlive) {
399 if (th->p_pid == pid) {
400 /* Remove thread from list of active threads */
401 th->p_nextlive->p_prevlive = th->p_prevlive;
402 th->p_prevlive->p_nextlive = th->p_nextlive;
403 /* Mark thread as exited, and if detached, free its resources */
404 __pthread_lock(th->p_lock);
405 th->p_exited = 1;
406 detached = th->p_detached;
407 __pthread_unlock(th->p_lock);
408 if (detached)
409 pthread_free(th);
410 break;
413 /* If all threads have exited and the main thread is pending on a
414 pthread_exit, wake up the main thread and terminate ourselves. */
415 if (main_thread_exiting &&
416 __pthread_main_thread->p_nextlive == __pthread_main_thread) {
417 restart(__pthread_main_thread);
418 _exit(0);
422 static void pthread_reap_children(void)
424 pid_t pid;
425 int status;
427 while ((pid = __libc_waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) {
428 pthread_exited(pid);
429 if (WIFSIGNALED(status)) {
430 /* If a thread died due to a signal, send the same signal to
431 all other threads, including the main thread. */
432 pthread_kill_all_threads(WTERMSIG(status), 1);
433 _exit(0);
438 /* Try to free the resources of a thread when requested by pthread_join
439 or pthread_detach on a terminated thread. */
441 static void pthread_handle_free(pthread_t th_id)
443 pthread_handle handle = thread_handle(th_id);
444 pthread_descr th;
446 __pthread_lock(&handle->h_lock);
447 if (invalid_handle(handle, th_id)) {
448 /* pthread_reap_children has deallocated the thread already,
449 nothing needs to be done */
450 __pthread_unlock(&handle->h_lock);
451 return;
453 th = handle->h_descr;
454 if (th->p_exited) {
455 __pthread_unlock(&handle->h_lock);
456 pthread_free(th);
457 } else {
458 /* The Unix process of the thread is still running.
459 Mark the thread as detached so that the thread manager will
460 deallocate its resources when the Unix process exits. */
461 th->p_detached = 1;
462 __pthread_unlock(&handle->h_lock);
466 /* Send a signal to all running threads */
468 static void pthread_kill_all_threads(int sig, int main_thread_also)
470 pthread_descr th;
471 for (th = __pthread_main_thread->p_nextlive;
472 th != __pthread_main_thread;
473 th = th->p_nextlive) {
474 kill(th->p_pid, sig);
476 if (main_thread_also) {
477 kill(__pthread_main_thread->p_pid, sig);
481 /* Process-wide exit() */
483 static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
485 pthread_descr th;
486 __pthread_exit_requested = 1;
487 __pthread_exit_code = exitcode;
488 /* Send the CANCEL signal to all running threads, including the main
489 thread, but excluding the thread from which the exit request originated
490 (that thread must complete the exit, e.g. calling atexit functions
491 and flushing stdio buffers). */
492 for (th = issuing_thread->p_nextlive;
493 th != issuing_thread;
494 th = th->p_nextlive) {
495 kill(th->p_pid, PTHREAD_SIG_CANCEL);
497 /* Now, wait for all these threads, so that they don't become zombies
498 and their times are properly added to the thread manager's times. */
499 for (th = issuing_thread->p_nextlive;
500 th != issuing_thread;
501 th = th->p_nextlive) {
502 waitpid(th->p_pid, NULL, __WCLONE);
504 restart(issuing_thread);
505 _exit(0);
508 /* Handler for PTHREAD_SIG_RESTART in thread manager thread */
510 void __pthread_manager_sighandler(int sig)
512 terminated_children = 1;
515 /* Adjust priority of thread manager so that it always run at a priority
516 higher than all threads */
518 void __pthread_manager_adjust_prio(int thread_prio)
520 struct sched_param param;
522 if (thread_prio <= __pthread_manager_thread.p_priority) return;
523 param.sched_priority =
524 thread_prio < __sched_get_priority_max(SCHED_FIFO)
525 ? thread_prio + 1 : thread_prio;
526 __sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, &param);
527 __pthread_manager_thread.p_priority = thread_prio;