* sysdeps/m68k/bits/setjmp.h (_JMPBUF_UNWINDS): Added.
[glibc.git] / linuxthreads / manager.c
blob8844decab710fad8e347ebd042ecf2bacd7004e1
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/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>
30 #include "pthread.h"
31 #include "internals.h"
32 #include "spinlock.h"
33 #include "restart.h"
35 /* Array of active threads. Entry 0 is reserved for the initial thread. */
37 struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =
38 { { 0, &__pthread_initial_thread}, /* All NULLs */ };
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. */
44 static inline pthread_descr thread_segment(int seg)
46 return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE)
47 - 1;
50 /* Flag set in signal handler to record child termination */
52 static volatile int terminated_children = 0;
54 /* Flag set when the initial thread is blocked on pthread_exit waiting
55 for all other threads to terminate */
57 static int main_thread_exiting = 0;
59 /* Counter used to generate unique thread identifier.
60 Thread identifier is pthread_threads_counter + segment. */
62 static pthread_t pthread_threads_counter = 0;
64 /* Forward declarations */
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);
74 /* The server thread managing requests for thread creation and termination */
76 int __pthread_manager(void *arg)
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;
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);
104 /* Check for termination of the main thread */
105 if (getppid() == 1) {
106 pthread_kill_all_threads(SIGKILL, 0);
107 _exit(0);
109 /* Check for dead children */
110 if (terminated_children) {
111 terminated_children = 0;
112 pthread_reap_children();
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;
142 break;
148 /* Process creation */
150 static int pthread_start_thread(void *arg)
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;
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)
179 size_t sseg;
180 int pid;
181 pthread_descr new_thread;
182 pthread_t new_thread_id;
183 void *guardaddr = NULL;
185 /* Find a free stack segment for the current stack */
186 for (sseg = 1; ; sseg++)
188 if (sseg >= PTHREAD_THREADS_MAX)
189 return EAGAIN;
190 if (__pthread_handles[sseg].h_descr != NULL)
191 continue;
193 if (attr == NULL || !attr->stackaddr_set)
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)
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)
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;
214 break;
216 /* It seems part of this segment is already mapped. Try the next. */
218 else
220 new_thread = (pthread_descr) attr->stackaddr - 1;
221 break;
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
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;
272 new_thread->p_priority =
273 new_thread->p_start_args.schedparam.sched_priority;
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)
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);
294 __pthread_handles[sseg].h_descr = NULL;
295 return errno;
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;
311 /* Free the resources of a thread. */
313 static void pthread_free(pthread_descr th)
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)
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);
333 /* Handle threads that have exited */
335 static void pthread_exited(pid_t pid)
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;
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);
365 static void pthread_reap_children(void)
367 pid_t pid;
368 int status;
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);
381 /* Free the resources of a thread */
383 static void pthread_handle_free(pthread_descr th)
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);
398 /* Send a signal to all running threads */
400 static void pthread_kill_all_threads(int sig, int main_thread_also)
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);
408 if (main_thread_also) {
409 kill(__pthread_main_thread->p_pid, sig);
413 /* Process-wide exit() */
415 static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
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);
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);
436 restart(issuing_thread);
437 _exit(0);
440 /* Handler for PTHREAD_SIG_RESTART in thread manager thread */
442 void __pthread_manager_sighandler(int sig)
444 terminated_children = 1;