Adjust for pthread.h and pthreadtypes.h change.
[kopensolaris-gnu/glibc.git] / linuxthreads / pthread.c
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.                 */
14
15 /* Thread creation, initialization, and basic low-level routines */
16
17 #include <errno.h>
18 #include <stddef.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <sys/wait.h>
25 #include <sys/resource.h>
26 #include "pthread.h"
27 #include "internals.h"
28 #include "spinlock.h"
29 #include "restart.h"
30
31 /* Descriptor of the initial thread */
32
33 struct _pthread_descr_struct __pthread_initial_thread = {
34   &__pthread_initial_thread,  /* pthread_descr p_nextlive */
35   &__pthread_initial_thread,  /* pthread_descr p_prevlive */
36   NULL,                       /* pthread_descr p_nextwaiting */
37   PTHREAD_THREADS_MAX,        /* pthread_t p_tid */
38   0,                          /* int p_pid */
39   0,                          /* int p_priority */
40   &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */
41   0,                          /* int p_signal */
42   NULL,                       /* sigjmp_buf * p_signal_buf */
43   NULL,                       /* sigjmp_buf * p_cancel_buf */
44   0,                          /* char p_terminated */
45   0,                          /* char p_detached */
46   0,                          /* char p_exited */
47   NULL,                       /* void * p_retval */
48   0,                          /* int p_retval */
49   NULL,                       /* pthread_descr p_joining */
50   NULL,                       /* struct _pthread_cleanup_buffer * p_cleanup */
51   0,                          /* char p_cancelstate */
52   0,                          /* char p_canceltype */
53   0,                          /* char p_canceled */
54   NULL,                       /* int *p_errnop */
55   0,                          /* int p_errno */
56   NULL,                       /* int *p_h_errnop */
57   0,                          /* int p_h_errno */
58   NULL,                       /* char * p_in_sighandler */
59   0,                          /* char p_sigwaiting */
60   PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
61   {NULL},                     /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
62   {NULL},                     /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
63   0,                          /* int p_userstack */
64   NULL,                       /* void * p_guardaddr */
65   0,                          /* size_t p_guardsize */
66   &__pthread_initial_thread,  /* pthread_descr p_self */
67   0                           /* Always index 0 */
68 };
69
70 /* Descriptor of the manager thread; none of this is used but the error
71    variables, the p_pid and p_priority fields,
72    and the address for identification.  */
73
74 struct _pthread_descr_struct __pthread_manager_thread = {
75   NULL,                       /* pthread_descr p_nextlive */
76   NULL,                       /* pthread_descr p_prevlive */
77   NULL,                       /* pthread_descr p_nextwaiting */
78   0,                          /* int p_tid */
79   0,                          /* int p_pid */
80   0,                          /* int p_priority */
81   NULL,                       /* struct _pthread_fastlock * p_lock */
82   0,                          /* int p_signal */
83   NULL,                       /* sigjmp_buf * p_signal_buf */
84   NULL,                       /* sigjmp_buf * p_cancel_buf */
85   0,                          /* char p_terminated */
86   0,                          /* char p_detached */
87   0,                          /* char p_exited */
88   NULL,                       /* void * p_retval */
89   0,                          /* int p_retval */
90   NULL,                       /* pthread_descr p_joining */
91   NULL,                       /* struct _pthread_cleanup_buffer * p_cleanup */
92   0,                          /* char p_cancelstate */
93   0,                          /* char p_canceltype */
94   0,                          /* char p_canceled */
95   &__pthread_manager_thread.p_errno, /* int *p_errnop */
96   0,                          /* int p_errno */
97   NULL,                       /* int *p_h_errnop */
98   0,                          /* int p_h_errno */
99   NULL,                       /* char * p_in_sighandler */
100   0,                          /* char p_sigwaiting */
101   PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */
102   {NULL},                     /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */
103   {NULL},                     /* void * p_libc_specific[_LIBC_TSD_KEY_N] */
104   0,                          /* int p_userstack */
105   NULL,                       /* void * p_guardaddr */
106   0,                          /* size_t p_guardsize */
107   &__pthread_manager_thread,  /* pthread_descr p_self */
108   1                           /* Always index 1 */
109 };
110
111 /* Pointer to the main thread (the father of the thread manager thread) */
112 /* Originally, this is the initial thread, but this changes after fork() */
113
114 pthread_descr __pthread_main_thread = &__pthread_initial_thread;
115
116 /* Limit between the stack of the initial thread (above) and the
117    stacks of other threads (below). Aligned on a STACK_SIZE boundary. */
118
119 char *__pthread_initial_thread_bos = NULL;
120
121 /* File descriptor for sending requests to the thread manager. */
122 /* Initially -1, meaning that the thread manager is not running. */
123
124 int __pthread_manager_request = -1;
125
126 /* Other end of the pipe for sending requests to the thread manager. */
127
128 int __pthread_manager_reader;
129
130 /* Limits of the thread manager stack */
131
132 char *__pthread_manager_thread_bos = NULL;
133 char *__pthread_manager_thread_tos = NULL;
134
135 /* For process-wide exit() */
136
137 int __pthread_exit_requested = 0;
138 int __pthread_exit_code = 0;
139
140 /* Communicate relevant LinuxThreads constants to gdb */
141
142 const int __pthread_threads_max = PTHREAD_THREADS_MAX;
143 const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct);
144 const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct,
145                                               h_descr);
146 const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct,
147                                             p_pid);
148
149 /* Signal numbers used for the communication.  */
150 int __pthread_sig_restart = DEFAULT_SIG_RESTART;
151 int __pthread_sig_cancel = DEFAULT_SIG_CANCEL;
152
153 /* These variables are used by the setup code.  */
154 extern int _errno;
155 extern int _h_errno;
156
157 /* Forward declarations */
158
159 static void pthread_exit_process(int retcode, void *arg);
160 #ifndef __i386__
161 static void pthread_handle_sigcancel(int sig);
162 static void pthread_handle_sigrestart(int sig);
163 #else
164 static void pthread_handle_sigcancel(int sig, struct sigcontext ctx);
165 static void pthread_handle_sigrestart(int sig, struct sigcontext ctx);
166 #endif
167
168 /* Initialize the pthread library.
169    Initialization is split in two functions:
170    - a constructor function that blocks the __pthread_sig_restart signal
171      (must do this very early, since the program could capture the signal
172       mask with e.g. sigsetjmp before creating the first thread);
173    - a regular function called from pthread_create when needed. */
174
175 static void pthread_initialize(void) __attribute__((constructor));
176
177 static void pthread_initialize(void)
178 {
179   struct sigaction sa;
180   sigset_t mask;
181   struct rlimit limit;
182   int max_stack;
183
184   /* If already done (e.g. by a constructor called earlier!), bail out */
185   if (__pthread_initial_thread_bos != NULL) return;
186 #ifdef TEST_FOR_COMPARE_AND_SWAP
187   /* Test if compare-and-swap is available */
188   __pthread_has_cas = compare_and_swap_is_available();
189 #endif
190   /* For the initial stack, reserve at least STACK_SIZE bytes of stack
191      below the current stack address, and align that on a
192      STACK_SIZE boundary. */
193   __pthread_initial_thread_bos =
194     (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
195   /* Play with the stack size limit to make sure that no stack ever grows
196      beyond STACK_SIZE minus two pages (one page for the thread descriptor
197      immediately beyond, and one page to act as a guard page). */
198   getrlimit(RLIMIT_STACK, &limit);
199   max_stack = STACK_SIZE - 2 * __getpagesize();
200   if (limit.rlim_cur > max_stack) {
201     limit.rlim_cur = max_stack;
202     setrlimit(RLIMIT_STACK, &limit);
203   }
204   /* Update the descriptor for the initial thread. */
205   __pthread_initial_thread.p_pid = __getpid();
206   /* If we have special thread_self processing, initialize that for the
207      main thread now.  */
208 #ifdef INIT_THREAD_SELF
209   INIT_THREAD_SELF(&__pthread_initial_thread, 0);
210 #endif
211   /* The errno/h_errno variable of the main thread are the global ones.  */
212   __pthread_initial_thread.p_errnop = &_errno;
213   __pthread_initial_thread.p_h_errnop = &_h_errno;
214 #ifdef SIGRTMIN
215   /* Allocate the signals used.  */
216   __pthread_sig_restart = __libc_allocate_rtsig (1);
217   __pthread_sig_cancel = __libc_allocate_rtsig (1);
218   if (__pthread_sig_restart < 0 || __pthread_sig_cancel < 0)
219     {
220       /* The kernel does not support real-time signals.  Use as before
221          the available signals in the fixed set.  */
222       __pthread_sig_restart = DEFAULT_SIG_RESTART;
223       __pthread_sig_cancel = DEFAULT_SIG_CANCEL;
224     }
225 #endif
226   /* Setup signal handlers for the initial thread.
227      Since signal handlers are shared between threads, these settings
228      will be inherited by all other threads. */
229 #ifndef __i386__
230   sa.sa_handler = pthread_handle_sigrestart;
231 #else
232   sa.sa_handler = (__sighandler_t) pthread_handle_sigrestart;
233 #endif
234   sigemptyset(&sa.sa_mask);
235   sa.sa_flags = SA_RESTART; /* does not matter for regular threads, but
236                                better for the thread manager */
237   __sigaction(__pthread_sig_restart, &sa, NULL);
238 #ifndef __i386__
239   sa.sa_handler = pthread_handle_sigcancel;
240 #else
241   sa.sa_handler = (__sighandler_t) pthread_handle_sigcancel;
242 #endif
243   sa.sa_flags = 0;
244   __sigaction(__pthread_sig_cancel, &sa, NULL);
245
246   /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
247   sigemptyset(&mask);
248   sigaddset(&mask, __pthread_sig_restart);
249   sigprocmask(SIG_BLOCK, &mask, NULL);
250   /* Register an exit function to kill all other threads. */
251   /* Do it early so that user-registered atexit functions are called
252      before pthread_exit_process. */
253   __on_exit(pthread_exit_process, NULL);
254 }
255
256 void __pthread_initialize(void)
257 {
258   pthread_initialize();
259 }
260
261 int __pthread_initialize_manager(void)
262 {
263   int manager_pipe[2];
264   int pid;
265   struct pthread_request request;
266
267   /* If basic initialization not done yet (e.g. we're called from a
268      constructor run before our constructor), do it now */
269   if (__pthread_initial_thread_bos == NULL) pthread_initialize();
270   /* Setup stack for thread manager */
271   __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
272   if (__pthread_manager_thread_bos == NULL) return -1;
273   __pthread_manager_thread_tos =
274     __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
275   /* Setup pipe to communicate with thread manager */
276   if (pipe(manager_pipe) == -1) {
277     free(__pthread_manager_thread_bos);
278     return -1;
279   }
280   /* Start the thread manager */
281   pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
282                 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
283 #ifdef CLONE_PTRACE
284                 | CLONE_PTRACE
285 #endif
286                 , (void *)(long)manager_pipe[0]);
287   if (pid == -1) {
288     free(__pthread_manager_thread_bos);
289     __libc_close(manager_pipe[0]);
290     __libc_close(manager_pipe[1]);
291     return -1;
292   }
293   __pthread_manager_request = manager_pipe[1]; /* writing end */
294   __pthread_manager_reader = manager_pipe[0]; /* reading end */
295   __pthread_manager_thread.p_pid = pid;
296   /* Make gdb aware of new thread manager */
297   if (__pthread_threads_debug) raise(__pthread_sig_cancel);
298   /* Synchronize debugging of the thread manager */
299   request.req_kind = REQ_DEBUG;
300   __libc_write(__pthread_manager_request, (char *) &request, sizeof(request));
301   return 0;
302 }
303
304 /* Thread creation */
305
306 int __pthread_create_2_1(pthread_t *thread, const pthread_attr_t *attr,
307                          void * (*start_routine)(void *), void *arg)
308 {
309   pthread_descr self = thread_self();
310   struct pthread_request request;
311   if (__pthread_manager_request < 0) {
312     if (__pthread_initialize_manager() < 0) return EAGAIN;
313   }
314   request.req_thread = self;
315   request.req_kind = REQ_CREATE;
316   request.req_args.create.attr = attr;
317   request.req_args.create.fn = start_routine;
318   request.req_args.create.arg = arg;
319   sigprocmask(SIG_SETMASK, (const sigset_t *) NULL,
320               &request.req_args.create.mask);
321   __libc_write(__pthread_manager_request, (char *) &request, sizeof(request));
322   suspend(self);
323   if (THREAD_GETMEM(self, p_retcode) == 0)
324     *thread = (pthread_t) THREAD_GETMEM(self, p_retval);
325   return THREAD_GETMEM(self, p_retcode);
326 }
327
328 #if defined HAVE_ELF && defined PIC && defined DO_VERSIONING
329 default_symbol_version (__pthread_create_2_1, pthread_create, GLIBC_2.1);
330
331 int __pthread_create_2_0(pthread_t *thread, const pthread_attr_t *attr,
332                          void * (*start_routine)(void *), void *arg)
333 {
334   /* The ATTR attribute is not really of type `pthread_attr_t *'.  It has
335      the old size and access to the new members might crash the program.
336      We convert the struct now.  */
337   pthread_attr_t new_attr;
338
339   if (attr != NULL)
340     {
341       size_t ps = __getpagesize ();
342
343       memcpy (&new_attr, attr,
344               (size_t) &(((pthread_attr_t*)NULL)->__guardsize));
345       new_attr.__guardsize = ps;
346       new_attr.__stackaddr_set = 0;
347       new_attr.__stackaddr = NULL;
348       new_attr.__stacksize = STACK_SIZE - ps;
349       attr = &new_attr;
350     }
351   return __pthread_create_2_1 (thread, attr, start_routine, arg);
352 }
353 symbol_version (__pthread_create_2_0, pthread_create, GLIBC_2.0);
354 #else
355 strong_alias (__pthread_create_2_1, pthread_create)
356 #endif
357
358 /* Simple operations on thread identifiers */
359
360 pthread_t pthread_self(void)
361 {
362   pthread_descr self = thread_self();
363   return THREAD_GETMEM(self, p_tid);
364 }
365
366 int pthread_equal(pthread_t thread1, pthread_t thread2)
367 {
368   return thread1 == thread2;
369 }
370
371 /* Helper function for thread_self in the case of user-provided stacks */
372
373 #ifndef THREAD_SELF
374
375 pthread_descr __pthread_find_self()
376 {
377   char * sp = CURRENT_STACK_FRAME;
378   pthread_handle h;
379
380   /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is
381      the manager threads handled specially in thread_self(), so start at 2 */
382   h = __pthread_handles + 2;
383   while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++;
384   return h->h_descr;
385 }
386
387 #endif
388
389 /* Thread scheduling */
390
391 int pthread_setschedparam(pthread_t thread, int policy,
392                           const struct sched_param *param)
393 {
394   pthread_handle handle = thread_handle(thread);
395   pthread_descr th;
396
397   __pthread_lock(&handle->h_lock);
398   if (invalid_handle(handle, thread)) {
399     __pthread_unlock(&handle->h_lock);
400     return ESRCH;
401   }
402   th = handle->h_descr;
403   if (__sched_setscheduler(th->p_pid, policy, param) == -1) {
404     __pthread_unlock(&handle->h_lock);
405     return errno;
406   }
407   th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;
408   __pthread_unlock(&handle->h_lock);
409   if (__pthread_manager_request >= 0)
410     __pthread_manager_adjust_prio(th->p_priority);
411   return 0;
412 }
413
414 int pthread_getschedparam(pthread_t thread, int *policy,
415                           struct sched_param *param)
416 {
417   pthread_handle handle = thread_handle(thread);
418   int pid, pol;
419
420   __pthread_lock(&handle->h_lock);
421   if (invalid_handle(handle, thread)) {
422     __pthread_unlock(&handle->h_lock);
423     return ESRCH;
424   }
425   pid = handle->h_descr->p_pid;
426   __pthread_unlock(&handle->h_lock);
427   pol = __sched_getscheduler(pid);
428   if (pol == -1) return errno;
429   if (__sched_getparam(pid, param) == -1) return errno;
430   *policy = pol;
431   return 0;
432 }
433
434 /* Process-wide exit() request */
435
436 static void pthread_exit_process(int retcode, void *arg)
437 {
438   struct pthread_request request;
439   pthread_descr self = thread_self();
440
441   if (__pthread_manager_request >= 0) {
442     request.req_thread = self;
443     request.req_kind = REQ_PROCESS_EXIT;
444     request.req_args.exit.code = retcode;
445     __libc_write(__pthread_manager_request,
446                  (char *) &request, sizeof(request));
447     suspend(self);
448     /* Main thread should accumulate times for thread manager and its
449        children, so that timings for main thread account for all threads. */
450     if (self == __pthread_main_thread)
451       waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
452   }
453 }
454
455 /* The handler for the RESTART signal just records the signal received
456    in the thread descriptor, and optionally performs a siglongjmp
457    (for pthread_cond_timedwait).
458    For the thread manager thread, redirect the signal to
459    __pthread_manager_sighandler. */
460
461 #ifndef __i386__
462 static void pthread_handle_sigrestart(int sig)
463 {
464   pthread_descr self = thread_self();
465 #else
466 static void pthread_handle_sigrestart(int sig, struct sigcontext ctx)
467 {
468   pthread_descr self;
469   asm volatile ("movw %w0,%%gs" : : "r" (ctx.gs));
470   self = thread_self();
471 #endif
472   if (self == &__pthread_manager_thread) {
473     __pthread_manager_sighandler(sig);
474   } else {
475     THREAD_SETMEM(self, p_signal, sig);
476     if (THREAD_GETMEM(self, p_signal_jmp) != NULL)
477       siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1);
478   }
479 }
480
481 /* The handler for the CANCEL signal checks for cancellation
482    (in asynchronous mode), for process-wide exit and exec requests.
483    For the thread manager thread, we ignore the signal.
484    The debugging strategy is as follows:
485    On reception of a REQ_DEBUG request (sent by new threads created to
486    the thread manager under debugging mode), the thread manager throws
487    __pthread_sig_cancel to itself. The debugger (if active) intercepts
488    this signal, takes into account new threads and continue execution
489    of the thread manager by propagating the signal because it doesn't
490    know what it is specifically done for. In the current implementation,
491    the thread manager simply discards it. */
492
493 #ifndef __i386__
494 static void pthread_handle_sigcancel(int sig)
495 {
496   pthread_descr self = thread_self();
497   sigjmp_buf * jmpbuf;
498 #else
499 static void pthread_handle_sigcancel(int sig, struct sigcontext ctx)
500 {
501   pthread_descr self;
502   sigjmp_buf * jmpbuf;
503   asm volatile ("movw %w0,%%gs" : : "r" (ctx.gs));
504   self = thread_self();
505 #endif
506
507   if (self == &__pthread_manager_thread)
508     return;
509   if (__pthread_exit_requested) {
510     /* Main thread should accumulate times for thread manager and its
511        children, so that timings for main thread account for all threads. */
512     if (self == __pthread_main_thread)
513       waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
514     _exit(__pthread_exit_code);
515   }
516   if (THREAD_GETMEM(self, p_canceled)
517       && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
518     if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
519       pthread_exit(PTHREAD_CANCELED);
520     jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);
521     if (jmpbuf != NULL) {
522       THREAD_SETMEM(self, p_cancel_jmp, NULL);
523       siglongjmp(*jmpbuf, 1);
524     }
525   }
526 }
527
528 /* Reset the state of the thread machinery after a fork().
529    Close the pipe used for requests and set the main thread to the forked
530    thread.
531    Notice that we can't free the stack segments, as the forked thread
532    may hold pointers into them. */
533
534 void __pthread_reset_main_thread()
535 {
536   pthread_descr self = thread_self();
537
538   if (__pthread_manager_request != -1) {
539     /* Free the thread manager stack */
540     free(__pthread_manager_thread_bos);
541     __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
542     /* Close the two ends of the pipe */
543     __libc_close(__pthread_manager_request);
544     __libc_close(__pthread_manager_reader);
545     __pthread_manager_request = __pthread_manager_reader = -1;
546   }
547   /* Update the pid of the main thread */
548   THREAD_SETMEM(self, p_pid, __getpid());
549   /* Make the forked thread the main thread */
550   __pthread_main_thread = self;
551   THREAD_SETMEM(self, p_nextlive, self);
552   THREAD_SETMEM(self, p_prevlive, self);
553   /* Now this thread modifies the global variables.  */
554   THREAD_SETMEM(self, p_errnop, &_errno);
555   THREAD_SETMEM(self, p_h_errnop, &_h_errno);
556 }
557
558 /* Process-wide exec() request */
559
560 void __pthread_kill_other_threads_np(void)
561 {
562   /* Terminate all other threads and thread manager */
563   pthread_exit_process(0, NULL);
564   /* Make current thread the main thread in case the calling thread
565      changes its mind, does not exec(), and creates new threads instead. */
566   __pthread_reset_main_thread();
567 }
568 weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
569
570 /* Concurrency symbol level.  */
571 static int current_level;
572
573 int __pthread_setconcurrency(int level)
574 {
575   /* We don't do anything unless we have found a useful interpretation.  */
576   current_level = level;
577   return 0;
578 }
579 weak_alias (__pthread_setconcurrency, pthread_setconcurrency)
580
581 int __pthread_getconcurrency(void)
582 {
583   return current_level;
584 }
585 weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
586
587 /* Debugging aid */
588
589 #ifdef DEBUG
590 #include <stdarg.h>
591
592 void __pthread_message(char * fmt, ...)
593 {
594   char buffer[1024];
595   va_list args;
596   sprintf(buffer, "%05d : ", __getpid());
597   va_start(args, fmt);
598   vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args);
599   va_end(args);
600   __libc_write(2, buffer, strlen(buffer));
601 }
602
603 #endif
604
605
606 #ifndef PIC
607 /* We need a hook to force the cancelation wrappers to be linked in when
608    static libpthread is used.  */
609 extern const int __pthread_provide_wrappers;
610 static const int *const __pthread_require_wrappers =
611   &__pthread_provide_wrappers;
612 #endif