Update.
[glibc.git] / linuxthreads / manager.c
bloba650bbe4ddacd3c287e87c03bd2dc8a4d6840ba6
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(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);
108 /* Check for dead children */
109 if (terminated_children) {
110 terminated_children = 0;
111 pthread_reap_children();
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;
141 break;
147 /* Process creation */
149 static int pthread_start_thread(void *arg)
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;
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)
178 size_t sseg;
179 int pid;
180 pthread_descr new_thread;
181 pthread_t new_thread_id;
182 int i;
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->guardsize != 0)
206 guardaddr = mmap ((caddr_t)((char *)(new_thread+1)
207 - 2*1024*1024),
208 attr->guardsize, 0, MAP_FIXED, -1, 0);
209 if (guardaddr == MAP_FAILED)
210 /* We don't make this an error. */
211 guardaddr = NULL;
213 break;
215 /* It seems part of this segment is already mapped. Try the next. */
217 else
219 new_thread = (pthread_descr) attr->stackaddr - 1;
220 break;
223 /* Allocate new thread identifier */
224 pthread_threads_counter += PTHREAD_THREADS_MAX;
225 new_thread_id = sseg + pthread_threads_counter;
226 /* Initialize the thread descriptor */
227 new_thread->p_nextwaiting = NULL;
228 new_thread->p_tid = new_thread_id;
229 new_thread->p_priority = 0;
230 new_thread->p_spinlock = &(__pthread_handles[sseg].h_spinlock);
231 new_thread->p_signal = 0;
232 new_thread->p_signal_jmp = NULL;
233 new_thread->p_cancel_jmp = NULL;
234 new_thread->p_terminated = 0;
235 new_thread->p_detached = attr == NULL ? 0 : attr->detachstate;
236 new_thread->p_exited = 0;
237 new_thread->p_retval = NULL;
238 new_thread->p_joining = NULL;
239 new_thread->p_cleanup = NULL;
240 new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE;
241 new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED;
242 new_thread->p_canceled = 0;
243 new_thread->p_errnop = &new_thread->p_errno;
244 new_thread->p_errno = 0;
245 new_thread->p_h_errnop = &new_thread->p_h_errno;
246 new_thread->p_h_errno = 0;
247 new_thread->p_guardaddr = guardaddr;
248 new_thread->p_guardsize = (attr == NULL || !attr->stackaddr_set
249 ? attr->guardsize : 0);
250 new_thread->p_userstack = attr != NULL && attr->stackaddr_set;
251 for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++)
252 new_thread->p_specific[i] = NULL;
253 /* Initialize the thread handle */
254 __pthread_handles[sseg].h_spinlock = 0; /* should already be 0 */
255 __pthread_handles[sseg].h_descr = new_thread;
256 /* Determine scheduling parameters for the thread */
257 new_thread->p_start_args.schedpolicy = -1;
258 if (attr != NULL) {
259 switch(attr->inheritsched) {
260 case PTHREAD_EXPLICIT_SCHED:
261 new_thread->p_start_args.schedpolicy = attr->schedpolicy;
262 new_thread->p_start_args.schedparam = attr->schedparam;
263 break;
264 case PTHREAD_INHERIT_SCHED:
265 /* schedpolicy doesn't need to be set, only get priority */
266 __sched_getparam(father_pid, &new_thread->p_start_args.schedparam);
267 break;
269 new_thread->p_priority =
270 new_thread->p_start_args.schedparam.sched_priority;
272 /* Finish setting up arguments to pthread_start_thread */
273 new_thread->p_start_args.start_routine = start_routine;
274 new_thread->p_start_args.arg = arg;
275 new_thread->p_start_args.mask = *mask;
276 /* Do the cloning */
277 pid = __clone(pthread_start_thread, (void **) new_thread,
278 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
279 PTHREAD_SIG_RESTART,
280 new_thread);
281 /* Check if cloning succeeded */
282 if (pid == -1) {
283 /* Free the stack if we allocated it */
284 if (attr == NULL || !attr->stackaddr_set)
286 munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE),
287 INITIAL_STACK_SIZE);
288 if (attr->guardsize != 0)
289 munmap(new_thread->p_guardaddr, new_thread->p_guardsize);
291 __pthread_handles[sseg].h_descr = NULL;
292 return errno;
294 /* Insert new thread in doubly linked list of active threads */
295 new_thread->p_prevlive = __pthread_main_thread;
296 new_thread->p_nextlive = __pthread_main_thread->p_nextlive;
297 __pthread_main_thread->p_nextlive->p_prevlive = new_thread;
298 __pthread_main_thread->p_nextlive = new_thread;
299 /* Set pid field of the new thread, in case we get there before the
300 child starts. */
301 new_thread->p_pid = pid;
302 /* We're all set */
303 *thread = new_thread_id;
304 return 0;
308 /* Free the resources of a thread. */
310 static void pthread_free(pthread_descr th)
312 pthread_handle handle;
313 ASSERT(th->p_exited);
314 /* Make the handle invalid */
315 handle = thread_handle(th->p_tid);
316 acquire(&handle->h_spinlock);
317 handle->h_descr = NULL;
318 release(&handle->h_spinlock);
319 /* If initial thread, nothing to free */
320 if (th == &__pthread_initial_thread) return;
321 if (!th->p_userstack)
323 /* Free the stack and thread descriptor area */
324 munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE);
325 if (th->p_guardsize != 0)
326 munmap(th->p_guardaddr, th->p_guardsize);
330 /* Handle threads that have exited */
332 static void pthread_exited(pid_t pid)
334 pthread_descr th;
335 int detached;
336 /* Find thread with that pid */
337 for (th = __pthread_main_thread->p_nextlive;
338 th != __pthread_main_thread;
339 th = th->p_nextlive) {
340 if (th->p_pid == pid) {
341 /* Remove thread from list of active threads */
342 th->p_nextlive->p_prevlive = th->p_prevlive;
343 th->p_prevlive->p_nextlive = th->p_nextlive;
344 /* Mark thread as exited, and if detached, free its resources */
345 acquire(th->p_spinlock);
346 th->p_exited = 1;
347 detached = th->p_detached;
348 release(th->p_spinlock);
349 if (detached) pthread_free(th);
350 break;
353 /* If all threads have exited and the main thread is pending on a
354 pthread_exit, wake up the main thread and terminate ourselves. */
355 if (main_thread_exiting &&
356 __pthread_main_thread->p_nextlive == __pthread_main_thread) {
357 restart(__pthread_main_thread);
358 _exit(0);
362 static void pthread_reap_children(void)
364 pid_t pid;
365 int status;
367 while ((pid = __libc_waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) {
368 pthread_exited(pid);
369 if (WIFSIGNALED(status)) {
370 /* If a thread died due to a signal, send the same signal to
371 all other threads, including the main thread. */
372 pthread_kill_all_threads(WTERMSIG(status), 1);
373 _exit(0);
378 /* Free the resources of a thread */
380 static void pthread_handle_free(pthread_descr th)
382 acquire(th->p_spinlock);
383 if (th->p_exited) {
384 release(th->p_spinlock);
385 pthread_free(th);
386 } else {
387 /* The Unix process of the thread is still running.
388 Mark the thread as detached so that the thread manager will
389 deallocate its resources when the Unix process exits. */
390 th->p_detached = 1;
391 release(th->p_spinlock);
395 /* Send a signal to all running threads */
397 static void pthread_kill_all_threads(int sig, int main_thread_also)
399 pthread_descr th;
400 for (th = __pthread_main_thread->p_nextlive;
401 th != __pthread_main_thread;
402 th = th->p_nextlive) {
403 kill(th->p_pid, sig);
405 if (main_thread_also) {
406 kill(__pthread_main_thread->p_pid, sig);
410 /* Process-wide exit() */
412 static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode)
414 pthread_descr th;
415 __pthread_exit_requested = 1;
416 __pthread_exit_code = exitcode;
417 /* Send the CANCEL signal to all running threads, including the main
418 thread, but excluding the thread from which the exit request originated
419 (that thread must complete the exit, e.g. calling atexit functions
420 and flushing stdio buffers). */
421 for (th = issuing_thread->p_nextlive;
422 th != issuing_thread;
423 th = th->p_nextlive) {
424 kill(th->p_pid, PTHREAD_SIG_CANCEL);
426 /* Now, wait for all these threads, so that they don't become zombies
427 and their times are properly added to the thread manager's times. */
428 for (th = issuing_thread->p_nextlive;
429 th != issuing_thread;
430 th = th->p_nextlive) {
431 waitpid(th->p_pid, NULL, __WCLONE);
433 restart(issuing_thread);
434 _exit(0);
437 /* Handler for PTHREAD_SIG_RESTART in thread manager thread */
439 void __pthread_manager_sighandler(int sig)
441 terminated_children = 1;