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 /* Thread creation, initialization, and basic low-level routines */
20 #include <netdb.h> /* for h_errno */
28 #include <sys/resource.h>
30 #include "internals.h"
33 #include "debug.h" /* added to linuxthreads -StS */
36 /* Mods for uClibc: Some includes */
38 #include <sys/types.h>
39 #include <sys/syscall.h>
41 /* mods for uClibc: getpwd and getpagesize are the syscalls */
42 #define __getpid getpid
43 #define __getpagesize getpagesize
44 /* mods for uClibc: __libc_sigaction is not in any standard headers */
45 extern int __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact);
48 /* These variables are used by the setup code. */
53 /* Descriptor of the initial thread */
55 struct _pthread_descr_struct __pthread_initial_thread = {
56 &__pthread_initial_thread, /* pthread_descr p_nextlive */
57 &__pthread_initial_thread, /* pthread_descr p_prevlive */
58 NULL, /* pthread_descr p_nextwaiting */
59 NULL, /* pthread_descr p_nextlock */
60 PTHREAD_THREADS_MAX, /* pthread_t p_tid */
62 0, /* int p_priority */
63 &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */
65 NULL, /* sigjmp_buf * p_signal_buf */
66 NULL, /* sigjmp_buf * p_cancel_buf */
67 0, /* char p_terminated */
68 0, /* char p_detached */
69 0, /* char p_exited */
70 NULL, /* void * p_retval */
72 NULL, /* pthread_descr p_joining */
73 NULL, /* struct _pthread_cleanup_buffer * p_cleanup */
74 0, /* char p_cancelstate */
75 0, /* char p_canceltype */
76 0, /* char p_canceled */
77 &_errno, /* int *p_errnop */
79 &_h_errno, /* int *p_h_errnop */
80 0, /* int p_h_errno */
81 NULL, /* char * p_in_sighandler */
82 0, /* char p_sigwaiting */
83 PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
84 {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
85 {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
86 0, /* int p_userstack */
87 NULL, /* void * p_guardaddr */
88 0, /* size_t p_guardsize */
89 &__pthread_initial_thread, /* pthread_descr p_self */
90 0, /* Always index 0 */
91 0, /* int p_report_events */
92 {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */
93 ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */
94 0, /* char p_woken_by_cancel */
95 NULL, /* struct pthread_extricate_if *p_extricate */
96 NULL, /* pthread_readlock_info *p_readlock_list; */
97 NULL, /* pthread_readlock_info *p_readlock_free; */
98 0 /* int p_untracked_readlock_count; */
101 /* Descriptor of the manager thread; none of this is used but the error
102 variables, the p_pid and p_priority fields,
103 and the address for identification. */
105 struct _pthread_descr_struct __pthread_manager_thread = {
106 NULL, /* pthread_descr p_nextlive */
107 NULL, /* pthread_descr p_prevlive */
108 NULL, /* pthread_descr p_nextwaiting */
109 NULL, /* pthread_descr p_nextlock */
112 0, /* int p_priority */
113 &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */
114 0, /* int p_signal */
115 NULL, /* sigjmp_buf * p_signal_buf */
116 NULL, /* sigjmp_buf * p_cancel_buf */
117 0, /* char p_terminated */
118 0, /* char p_detached */
119 0, /* char p_exited */
120 NULL, /* void * p_retval */
121 0, /* int p_retval */
122 NULL, /* pthread_descr p_joining */
123 NULL, /* struct _pthread_cleanup_buffer * p_cleanup */
124 0, /* char p_cancelstate */
125 0, /* char p_canceltype */
126 0, /* char p_canceled */
127 &__pthread_manager_thread.p_errno, /* int *p_errnop */
129 NULL, /* int *p_h_errnop */
130 0, /* int p_h_errno */
131 NULL, /* char * p_in_sighandler */
132 0, /* char p_sigwaiting */
133 PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
134 {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
135 {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
136 0, /* int p_userstack */
137 NULL, /* void * p_guardaddr */
138 0, /* size_t p_guardsize */
139 &__pthread_manager_thread, /* pthread_descr p_self */
140 1, /* Always index 1 */
141 0, /* int p_report_events */
142 {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */
143 ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */
144 0, /* char p_woken_by_cancel */
145 NULL, /* struct pthread_extricate_if *p_extricate */
146 NULL, /* pthread_readlock_info *p_readlock_list; */
147 NULL, /* pthread_readlock_info *p_readlock_free; */
148 0 /* int p_untracked_readlock_count; */
151 /* Pointer to the main thread (the father of the thread manager thread) */
152 /* Originally, this is the initial thread, but this changes after fork() */
154 pthread_descr __pthread_main_thread = &__pthread_initial_thread;
156 /* Limit between the stack of the initial thread (above) and the
157 stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
159 char *__pthread_initial_thread_bos = NULL;
161 /* For non-MMU systems also remember to stack top of the initial thread.
162 * This is adapted when other stacks are malloc'ed since we don't know
163 * the bounds a-priori. -StS */
165 #ifndef __UCLIBC_HAS_MMU__
166 char *__pthread_initial_thread_tos = NULL;
167 #endif /* __UCLIBC_HAS_MMU__ */
169 /* File descriptor for sending requests to the thread manager. */
170 /* Initially -1, meaning that the thread manager is not running. */
172 int __pthread_manager_request = -1;
174 /* Other end of the pipe for sending requests to the thread manager. */
176 int __pthread_manager_reader;
178 /* Limits of the thread manager stack */
180 char *__pthread_manager_thread_bos = NULL;
181 char *__pthread_manager_thread_tos = NULL;
183 /* For process-wide exit() */
185 int __pthread_exit_requested = 0;
186 int __pthread_exit_code = 0;
188 /* Communicate relevant LinuxThreads constants to gdb */
190 const int __pthread_threads_max = PTHREAD_THREADS_MAX;
191 const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct);
192 const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct,
194 const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
197 /* Forward declarations */
199 static void pthread_exit_process(int retcode, void *arg);
201 static void pthread_handle_sigcancel(int sig);
202 static void pthread_handle_sigrestart(int sig);
204 static void pthread_handle_sigcancel(int sig, struct sigcontext ctx);
205 static void pthread_handle_sigrestart(int sig, struct sigcontext ctx);
207 static void pthread_handle_sigdebug(int sig);
209 /* Signal numbers used for the communication.
210 In these variables we keep track of the used variables. If the
211 platform does not support any real-time signals we will define the
212 values to some unreasonable value which will signal failing of all
213 the functions below. */
214 #ifdef __NR_rt_sigaction
215 int __pthread_sig_restart = __SIGRTMIN;
216 int __pthread_sig_cancel = __SIGRTMIN + 1;
217 int __pthread_sig_debug = __SIGRTMIN + 2;
218 void (*__pthread_restart)(pthread_descr) = __pthread_restart_new;
219 void (*__pthread_suspend)(pthread_descr) = __pthread_wait_for_restart_signal;
221 int __pthread_sig_restart = SIGUSR1;
222 int __pthread_sig_cancel = SIGUSR2;
223 int __pthread_sig_debug = 0;
224 /* Pointers that select new or old suspend/resume functions
225 based on availability of rt signals. */
226 void (*__pthread_restart)(pthread_descr) = __pthread_restart_old;
227 void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old;
230 /* Initialize the pthread library.
231 Initialization is split in two functions:
232 - a constructor function that blocks the __pthread_sig_restart signal
233 (must do this very early, since the program could capture the signal
234 mask with e.g. sigsetjmp before creating the first thread);
235 - a regular function called from pthread_create when needed. */
237 static void pthread_initialize(void) __attribute__((constructor));
239 static void pthread_initialize(void)
246 /* If already done (e.g. by a constructor called earlier!), bail out */
247 if (__pthread_initial_thread_bos != NULL) return;
248 #ifdef TEST_FOR_COMPARE_AND_SWAP
249 /* Test if compare-and-swap is available */
250 __pthread_has_cas = compare_and_swap_is_available();
252 /* For the initial stack, reserve at least STACK_SIZE bytes of stack
253 below the current stack address, and align that on a
254 STACK_SIZE boundary. */
255 __pthread_initial_thread_bos =
256 (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
257 /* Update the descriptor for the initial thread. */
258 __pthread_initial_thread.p_pid = __getpid();
259 /* If we have special thread_self processing, initialize that for the
261 #ifdef INIT_THREAD_SELF
262 INIT_THREAD_SELF(&__pthread_initial_thread, 0);
264 /* The errno/h_errno variable of the main thread are the global ones. */
265 __pthread_initial_thread.p_errnop = &_errno;
266 __pthread_initial_thread.p_h_errnop = &_h_errno;
267 /* Play with the stack size limit to make sure that no stack ever grows
268 beyond STACK_SIZE minus two pages (one page for the thread descriptor
269 immediately beyond, and one page to act as a guard page). */
271 #ifdef __UCLIBC_HAS_MMU__
272 /* We cannot allocate a huge chunk of memory to mmap all thread stacks later
273 * on a non-MMU system. Thus, we don't need the rlimit either. -StS */
274 getrlimit(RLIMIT_STACK, &limit);
275 max_stack = STACK_SIZE - 2 * __getpagesize();
276 if (limit.rlim_cur > max_stack) {
277 limit.rlim_cur = max_stack;
278 setrlimit(RLIMIT_STACK, &limit);
281 /* For non-MMU assume __pthread_initial_thread_tos at upper page boundary, and
282 * __pthread_initial_thread_bos at address 0. These bounds are refined as we
283 * malloc other stack frames such that they don't overlap. -StS
285 __pthread_initial_thread_tos =
286 (char *)(((long)CURRENT_STACK_FRAME + __getpagesize()) & ~(__getpagesize() - 1));
287 __pthread_initial_thread_bos = (char *) 1; /* set it non-zero so we know we have been here */
288 PDEBUG("initial thread stack bounds: bos=%p, tos=%p\n",
289 __pthread_initial_thread_bos, __pthread_initial_thread_tos);
290 #endif /* __UCLIBC_HAS_MMU__ */
292 /* Setup signal handlers for the initial thread.
293 Since signal handlers are shared between threads, these settings
294 will be inherited by all other threads. */
296 sa.sa_handler = pthread_handle_sigrestart;
298 sa.sa_handler = (__sighandler_t) pthread_handle_sigrestart;
300 sigemptyset(&sa.sa_mask);
302 __libc_sigaction(__pthread_sig_restart, &sa, NULL);
304 sa.sa_handler = pthread_handle_sigcancel;
306 sa.sa_handler = (__sighandler_t) pthread_handle_sigcancel;
309 __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
310 if (__pthread_sig_debug > 0) {
311 sa.sa_handler = pthread_handle_sigdebug;
312 sigemptyset(&sa.sa_mask);
314 __libc_sigaction(__pthread_sig_debug, &sa, NULL);
316 /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
318 sigaddset(&mask, __pthread_sig_restart);
319 PDEBUG("block mask = %x\n", mask);
320 sigprocmask(SIG_BLOCK, &mask, NULL);
321 /* Register an exit function to kill all other threads. */
322 /* Do it early so that user-registered atexit functions are called
323 before pthread_exit_process. */
324 on_exit(pthread_exit_process, NULL);
327 void __pthread_initialize(void)
329 pthread_initialize();
332 int __pthread_initialize_manager(void)
336 struct pthread_request request;
338 /* If basic initialization not done yet (e.g. we're called from a
339 constructor run before our constructor), do it now */
340 if (__pthread_initial_thread_bos == NULL) pthread_initialize();
341 /* Setup stack for thread manager */
342 __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
343 if (__pthread_manager_thread_bos == NULL) return -1;
344 __pthread_manager_thread_tos =
345 __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
347 /* On non-MMU systems we make sure that the initial thread bounds don't overlap
348 * with the manager stack frame */
349 NOMMU_INITIAL_THREAD_BOUNDS(__pthread_manager_thread_tos,__pthread_manager_thread_bos);
350 PDEBUG("manager stack: size=%d, bos=%p, tos=%p\n", THREAD_MANAGER_STACK_SIZE,
351 __pthread_manager_thread_bos, __pthread_manager_thread_tos);
353 PDEBUG("initial stack: estimate bos=%p, tos=%p\n",
354 __pthread_initial_thread_bos, __pthread_initial_thread_tos);
357 /* Setup pipe to communicate with thread manager */
358 if (pipe(manager_pipe) == -1) {
359 free(__pthread_manager_thread_bos);
362 /* Start the thread manager */
364 if (__pthread_initial_thread.p_report_events)
366 /* It's a bit more complicated. We have to report the creation of
367 the manager thread. */
368 int idx = __td_eventword (TD_CREATE);
369 uint32_t mask = __td_eventmask (TD_CREATE);
371 if ((mask & (__pthread_threads_events.event_bits[idx]
372 | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]))
375 pid = clone(__pthread_manager_event,
376 (void **) __pthread_manager_thread_tos,
377 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
378 (void *)(long)manager_pipe[0]);
382 /* Now fill in the information about the new thread in
383 the newly created thread's data structure. We cannot let
384 the new thread do this since we don't know whether it was
385 already scheduled when we send the event. */
386 __pthread_manager_thread.p_eventbuf.eventdata =
387 &__pthread_manager_thread;
388 __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE;
389 __pthread_last_event = &__pthread_manager_thread;
390 __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
391 __pthread_manager_thread.p_pid = pid;
393 /* Now call the function which signals the event. */
394 __linuxthreads_create_event ();
396 /* Now restart the thread. */
397 __pthread_unlock(__pthread_manager_thread.p_lock);
403 pid = clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
404 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
405 (void *)(long)manager_pipe[0]);
408 free(__pthread_manager_thread_bos);
409 __libc_close(manager_pipe[0]);
410 __libc_close(manager_pipe[1]);
413 __pthread_manager_request = manager_pipe[1]; /* writing end */
414 __pthread_manager_reader = manager_pipe[0]; /* reading end */
415 __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1;
416 __pthread_manager_thread.p_pid = pid;
417 /* Make gdb aware of new thread manager */
418 if (__pthread_threads_debug && __pthread_sig_debug > 0)
420 raise(__pthread_sig_debug);
421 /* We suspend ourself and gdb will wake us up when it is
422 ready to handle us. */
423 __pthread_wait_for_restart_signal(thread_self());
425 /* Synchronize debugging of the thread manager */
426 PDEBUG("send REQ_DEBUG to manager thread\n");
427 request.req_kind = REQ_DEBUG;
428 __libc_write(__pthread_manager_request, (char *) &request, sizeof(request));
432 /* Thread creation */
434 int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
435 void * (*start_routine)(void *), void *arg)
437 pthread_descr self = thread_self();
438 struct pthread_request request;
439 if (__pthread_manager_request < 0) {
440 if (__pthread_initialize_manager() < 0) return EAGAIN;
442 request.req_thread = self;
443 request.req_kind = REQ_CREATE;
444 request.req_args.create.attr = attr;
445 request.req_args.create.fn = start_routine;
446 request.req_args.create.arg = arg;
447 sigprocmask(SIG_SETMASK, (const sigset_t *) NULL,
448 &request.req_args.create.mask);
449 PDEBUG("write REQ_CREATE to manager thread\n");
450 __libc_write(__pthread_manager_request, (char *) &request, sizeof(request));
451 PDEBUG("before suspend(self)\n");
453 PDEBUG("after suspend(self)\n");
454 if (THREAD_GETMEM(self, p_retcode) == 0)
455 *thread = (pthread_t) THREAD_GETMEM(self, p_retval);
456 return THREAD_GETMEM(self, p_retcode);
459 /* Simple operations on thread identifiers */
461 pthread_t pthread_self(void)
463 pthread_descr self = thread_self();
464 return THREAD_GETMEM(self, p_tid);
467 int pthread_equal(pthread_t thread1, pthread_t thread2)
469 return thread1 == thread2;
472 /* Helper function for thread_self in the case of user-provided stacks */
476 pthread_descr __pthread_find_self()
478 char * sp = CURRENT_STACK_FRAME;
481 /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is
482 the manager threads handled specially in thread_self(), so start at 2 */
483 h = __pthread_handles + 2;
484 while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++;
487 if (h->h_descr == NULL) {
488 printf("*** "__FUNCTION__" ERROR descriptor is NULL!!!!! ***\n\n");
498 /* Thread scheduling */
500 int pthread_setschedparam(pthread_t thread, int policy,
501 const struct sched_param *param)
503 pthread_handle handle = thread_handle(thread);
506 __pthread_lock(&handle->h_lock, NULL);
507 if (invalid_handle(handle, thread)) {
508 __pthread_unlock(&handle->h_lock);
511 th = handle->h_descr;
512 if (sched_setscheduler(th->p_pid, policy, param) == -1) {
513 __pthread_unlock(&handle->h_lock);
516 th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;
517 __pthread_unlock(&handle->h_lock);
518 if (__pthread_manager_request >= 0)
519 __pthread_manager_adjust_prio(th->p_priority);
523 int pthread_getschedparam(pthread_t thread, int *policy,
524 struct sched_param *param)
526 pthread_handle handle = thread_handle(thread);
529 __pthread_lock(&handle->h_lock, NULL);
530 if (invalid_handle(handle, thread)) {
531 __pthread_unlock(&handle->h_lock);
534 pid = handle->h_descr->p_pid;
535 __pthread_unlock(&handle->h_lock);
536 pol = sched_getscheduler(pid);
537 if (pol == -1) return errno;
538 if (sched_getparam(pid, param) == -1) return errno;
543 /* Process-wide exit() request */
545 static void pthread_exit_process(int retcode, void *arg)
547 struct pthread_request request;
548 pthread_descr self = thread_self();
550 if (__pthread_manager_request >= 0) {
551 request.req_thread = self;
552 request.req_kind = REQ_PROCESS_EXIT;
553 request.req_args.exit.code = retcode;
554 __libc_write(__pthread_manager_request,
555 (char *) &request, sizeof(request));
557 /* Main thread should accumulate times for thread manager and its
558 children, so that timings for main thread account for all threads. */
559 if (self == __pthread_main_thread)
560 waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
564 /* The handler for the RESTART signal just records the signal received
565 in the thread descriptor, and optionally performs a siglongjmp
566 (for pthread_cond_timedwait). */
569 static void pthread_handle_sigrestart(int sig)
571 pthread_descr self = thread_self();
572 PDEBUG("got called in non-i386 mode for %u\n", self);
574 static void pthread_handle_sigrestart(int sig, struct sigcontext ctx)
577 asm volatile ("movw %w0,%%gs" : : "r" (ctx.gs));
578 self = thread_self();
579 PDEBUG("got called in i386-mode for %u\n", self);
581 THREAD_SETMEM(self, p_signal, sig);
582 if (THREAD_GETMEM(self, p_signal_jmp) != NULL)
583 siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1);
586 /* The handler for the CANCEL signal checks for cancellation
587 (in asynchronous mode), for process-wide exit and exec requests.
588 For the thread manager thread, redirect the signal to
589 __pthread_manager_sighandler. */
592 static void pthread_handle_sigcancel(int sig)
594 pthread_descr self = thread_self();
597 static void pthread_handle_sigcancel(int sig, struct sigcontext ctx)
601 asm volatile ("movw %w0,%%gs" : : "r" (ctx.gs));
602 self = thread_self();
605 if (self == &__pthread_manager_thread)
607 __pthread_manager_sighandler(sig);
610 if (__pthread_exit_requested) {
611 /* Main thread should accumulate times for thread manager and its
612 children, so that timings for main thread account for all threads. */
613 if (self == __pthread_main_thread)
614 waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
615 _exit(__pthread_exit_code);
617 if (THREAD_GETMEM(self, p_canceled)
618 && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
619 if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
620 pthread_exit(PTHREAD_CANCELED);
621 jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);
622 if (jmpbuf != NULL) {
623 THREAD_SETMEM(self, p_cancel_jmp, NULL);
624 siglongjmp(*jmpbuf, 1);
629 /* Handler for the DEBUG signal.
630 The debugging strategy is as follows:
631 On reception of a REQ_DEBUG request (sent by new threads created to
632 the thread manager under debugging mode), the thread manager throws
633 __pthread_sig_debug to itself. The debugger (if active) intercepts
634 this signal, takes into account new threads and continue execution
635 of the thread manager by propagating the signal because it doesn't
636 know what it is specifically done for. In the current implementation,
637 the thread manager simply discards it. */
639 static void pthread_handle_sigdebug(int sig)
644 /* Reset the state of the thread machinery after a fork().
645 Close the pipe used for requests and set the main thread to the forked
647 Notice that we can't free the stack segments, as the forked thread
648 may hold pointers into them. */
650 void __pthread_reset_main_thread()
652 pthread_descr self = thread_self();
654 if (__pthread_manager_request != -1) {
655 /* Free the thread manager stack */
656 free(__pthread_manager_thread_bos);
657 __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
658 /* Close the two ends of the pipe */
659 __libc_close(__pthread_manager_request);
660 __libc_close(__pthread_manager_reader);
661 __pthread_manager_request = __pthread_manager_reader = -1;
664 /* Update the pid of the main thread */
665 THREAD_SETMEM(self, p_pid, __getpid());
666 /* Make the forked thread the main thread */
667 __pthread_main_thread = self;
668 THREAD_SETMEM(self, p_nextlive, self);
669 THREAD_SETMEM(self, p_prevlive, self);
670 /* Now this thread modifies the global variables. */
671 THREAD_SETMEM(self, p_errnop, &_errno);
672 THREAD_SETMEM(self, p_h_errnop, &_h_errno);
675 /* Process-wide exec() request */
677 void __pthread_kill_other_threads_np(void)
680 /* Terminate all other threads and thread manager */
681 pthread_exit_process(0, NULL);
682 /* Make current thread the main thread in case the calling thread
683 changes its mind, does not exec(), and creates new threads instead. */
684 __pthread_reset_main_thread();
685 /* Reset the signal handlers behaviour for the signals the
686 implementation uses since this would be passed to the new
688 sigemptyset(&sa.sa_mask);
690 sa.sa_handler = SIG_DFL;
691 __libc_sigaction(__pthread_sig_restart, &sa, NULL);
692 __libc_sigaction(__pthread_sig_cancel, &sa, NULL);
693 if (__pthread_sig_debug > 0)
694 __libc_sigaction(__pthread_sig_debug, &sa, NULL);
696 weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
698 /* Concurrency symbol level. */
699 static int current_level;
701 int __pthread_setconcurrency(int level)
703 /* We don't do anything unless we have found a useful interpretation. */
704 current_level = level;
707 weak_alias (__pthread_setconcurrency, pthread_setconcurrency)
709 int __pthread_getconcurrency(void)
711 return current_level;
713 weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
715 void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif)
717 __pthread_lock(self->p_lock, self);
718 THREAD_SETMEM(self, p_extricate, peif);
719 __pthread_unlock(self->p_lock);
722 /* Primitives for controlling thread execution */
724 void __pthread_wait_for_restart_signal(pthread_descr self)
728 sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */
729 sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */
732 PDEBUG("temporary block mask = %x\n", mask);
733 sigsuspend(&mask); /* Wait for signal */
734 PDEBUG(" *** after sigsuspend *** \n");
735 } while (self->p_signal !=__pthread_sig_restart );
738 #ifdef __NR_rt_sigaction
739 void __pthread_restart_new(pthread_descr th)
741 kill(th->p_pid, __pthread_sig_restart);
744 /* There is no __pthread_suspend_new because it would just
745 be a wasteful wrapper for __pthread_wait_for_restart_signal */
747 void __pthread_suspend_new(pthread_descr th)
749 __pthread_wait_for_restart_signal(th);
754 /* The _old variants are for 2.0 and early 2.1 kernels which don't have RT signals.
755 On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation.
756 Since the restart signal does not queue, we use an atomic counter to create
757 queuing semantics. This is needed to resolve a rare race condition in
758 pthread_cond_timedwait_relative. */
759 void __pthread_restart_old(pthread_descr th)
761 if (atomic_increment(&th->p_resume_count) == -1)
762 kill(th->p_pid, __pthread_sig_restart);
765 void __pthread_suspend_old(pthread_descr self)
767 if (atomic_decrement(&self->p_resume_count) <= 0)
768 __pthread_wait_for_restart_signal(self);
772 /* There is no __pthread_suspend_new because it would just
773 be a wasteful wrapper for __pthread_wait_for_restart_signal */
780 void __pthread_message(char * fmt, ...)
784 sprintf(buffer, "%05d : ", __getpid());
786 vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args);
788 __libc_write(2, buffer, strlen(buffer));
795 /* We need a hook to force the cancelation wrappers to be linked in when
796 static libpthread is used. */
797 extern const int __pthread_provide_wrappers;
798 static const int *const __pthread_require_wrappers =
799 &__pthread_provide_wrappers;