1 /* Linuxthreads - a simple clone()-based implementation of Posix */
2 /* threads for Linux. */
3 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
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. */
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 */
24 #include <sys/select.h> /* for select */
25 #include <sys/mman.h> /* for mmap */
27 #include <sys/wait.h> /* for waitpid macros */
28 #include <linux/tasks.h>
31 #include "internals.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
)
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
)
81 struct timeval timeout
;
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
);
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 */
94 sigdelset(&mask
, PTHREAD_SIG_RESTART
);
95 sigprocmask(SIG_SETMASK
, &mask
, NULL
);
96 /* Enter server loop */
99 FD_SET(reqfd
, &readfds
);
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);
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
) {
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
);
130 pthread_handle_free(request
.req_args
.free
.thread
);
132 case REQ_PROCESS_EXIT
:
133 pthread_handle_exit(request
.req_thread
,
134 request
.req_args
.exit
.code
);
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
);
148 /* Process creation */
150 static int pthread_start_thread(void *arg
)
152 pthread_descr self
= (pthread_descr
) arg
;
154 /* Initialize special thread_self processing, if any. */
155 #ifdef INIT_THREAD_SELF
156 INIT_THREAD_SELF(self
);
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
);
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
)
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
)
190 if (__pthread_handles
[sseg
].h_descr
!= NULL
)
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)
208 attr
? attr
->guardsize
: __getpagesize (),
209 0, MAP_FIXED
, -1, 0);
210 if (guardaddr
== MAP_FAILED
)
211 /* We don't make this an error. */
216 /* It seems part of this segment is already mapped. Try the next. */
220 new_thread
= (pthread_descr
) attr
->stackaddr
- 1;
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
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;
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
;
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
);
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
;
280 pid
= __clone(pthread_start_thread
, (void **) new_thread
,
281 CLONE_VM
| CLONE_FS
| CLONE_FILES
| CLONE_SIGHAND
|
284 /* Check if cloning succeeded */
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
),
291 if (new_thread
->p_guardsize
!= 0)
292 munmap(new_thread
->p_guardaddr
, new_thread
->p_guardsize
);
294 __pthread_handles
[sseg
].h_descr
= NULL
;
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
304 new_thread
->p_pid
= pid
;
306 *thread
= new_thread_id
;
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
)
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
);
350 detached
= th
->p_detached
;
351 release(th
->p_spinlock
);
352 if (detached
) pthread_free(th
);
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
);
365 static void pthread_reap_children(void)
370 while ((pid
= __libc_waitpid(-1, &status
, WNOHANG
| __WCLONE
)) > 0) {
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);
381 /* Free the resources of a thread */
383 static void pthread_handle_free(pthread_descr th
)
385 acquire(th
->p_spinlock
);
387 release(th
->p_spinlock
);
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. */
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
)
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
)
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
);
440 /* Handler for PTHREAD_SIG_RESTART in thread manager thread */
442 void __pthread_manager_sighandler(int sig
)
444 terminated_children
= 1;