8d892b7bb5189986952c4e0f3da4ebcc6614abaf
[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 #ifdef SIGRTMIN
151 int __pthread_sig_restart;
152 int __pthread_sig_cancel;
153 #else
154 int __pthread_sig_restart = DEFAULT_SIG_RESTART;
155 int __pthread_sig_cancel = DEFAULT_SIG_CANCEL;
156 #endif
157
158 /* These variables are used by the setup code.  */
159 extern int _errno;
160 extern int _h_errno;
161
162 /* Forward declarations */
163
164 static void pthread_exit_process(int retcode, void *arg);
165 #ifndef __i386__
166 static void pthread_handle_sigcancel(int sig);
167 static void pthread_handle_sigrestart(int sig);
168 #else
169 static void pthread_handle_sigcancel(int sig, struct sigcontext ctx);
170 static void pthread_handle_sigrestart(int sig, struct sigcontext ctx);
171 #endif
172
173 /* Initialize the pthread library.
174    Initialization is split in two functions:
175    - a constructor function that blocks the __pthread_sig_restart signal
176      (must do this very early, since the program could capture the signal
177       mask with e.g. sigsetjmp before creating the first thread);
178    - a regular function called from pthread_create when needed. */
179
180 static void pthread_initialize(void) __attribute__((constructor));
181
182 static void pthread_initialize(void)
183 {
184   struct sigaction sa;
185   sigset_t mask;
186   struct rlimit limit;
187   int max_stack;
188
189   /* If already done (e.g. by a constructor called earlier!), bail out */
190   if (__pthread_initial_thread_bos != NULL) return;
191 #ifdef TEST_FOR_COMPARE_AND_SWAP
192   /* Test if compare-and-swap is available */
193   __pthread_has_cas = compare_and_swap_is_available();
194 #endif
195   /* For the initial stack, reserve at least STACK_SIZE bytes of stack
196      below the current stack address, and align that on a
197      STACK_SIZE boundary. */
198   __pthread_initial_thread_bos =
199     (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
200   /* Play with the stack size limit to make sure that no stack ever grows
201      beyond STACK_SIZE minus two pages (one page for the thread descriptor
202      immediately beyond, and one page to act as a guard page). */
203   getrlimit(RLIMIT_STACK, &limit);
204   max_stack = STACK_SIZE - 2 * __getpagesize();
205   if (limit.rlim_cur > max_stack) {
206     limit.rlim_cur = max_stack;
207     setrlimit(RLIMIT_STACK, &limit);
208   }
209   /* Update the descriptor for the initial thread. */
210   __pthread_initial_thread.p_pid = __getpid();
211   /* If we have special thread_self processing, initialize that for the
212      main thread now.  */
213 #ifdef INIT_THREAD_SELF
214   INIT_THREAD_SELF(&__pthread_initial_thread, 0);
215 #endif
216   /* The errno/h_errno variable of the main thread are the global ones.  */
217   __pthread_initial_thread.p_errnop = &_errno;
218   __pthread_initial_thread.p_h_errnop = &_h_errno;
219 #ifdef SIGRTMIN
220   /* Allocate the signals used.  */
221   __pthread_sig_restart = __libc_allocate_rtsig (1);
222   __pthread_sig_cancel = __libc_allocate_rtsig (1);
223   if (__pthread_sig_restart < 0 || __pthread_sig_cancel < 0)
224     {
225       /* The kernel does not support real-time signals.  Use as before
226          the available signals in the fixed set.  */
227       __pthread_sig_restart = DEFAULT_SIG_RESTART;
228       __pthread_sig_cancel = DEFAULT_SIG_CANCEL;
229     }
230 #endif
231   /* Setup signal handlers for the initial thread.
232      Since signal handlers are shared between threads, these settings
233      will be inherited by all other threads. */
234 #ifndef __i386__
235   sa.sa_handler = pthread_handle_sigrestart;
236 #else
237   sa.sa_handler = (__sighandler_t) pthread_handle_sigrestart;
238 #endif
239   sigemptyset(&sa.sa_mask);
240   sa.sa_flags = SA_RESTART; /* does not matter for regular threads, but
241                                better for the thread manager */
242   __sigaction(__pthread_sig_restart, &sa, NULL);
243 #ifndef __i386__
244   sa.sa_handler = pthread_handle_sigcancel;
245 #else
246   sa.sa_handler = (__sighandler_t) pthread_handle_sigcancel;
247 #endif
248   sa.sa_flags = 0;
249   __sigaction(__pthread_sig_cancel, &sa, NULL);
250
251   /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */
252   sigemptyset(&mask);
253   sigaddset(&mask, __pthread_sig_restart);
254   sigprocmask(SIG_BLOCK, &mask, NULL);
255   /* Register an exit function to kill all other threads. */
256   /* Do it early so that user-registered atexit functions are called
257      before pthread_exit_process. */
258   __on_exit(pthread_exit_process, NULL);
259 }
260
261 void __pthread_initialize(void)
262 {
263   pthread_initialize();
264 }
265
266 int __pthread_initialize_manager(void)
267 {
268   int manager_pipe[2];
269   int pid;
270   struct pthread_request request;
271
272   /* If basic initialization not done yet (e.g. we're called from a
273      constructor run before our constructor), do it now */
274   if (__pthread_initial_thread_bos == NULL) pthread_initialize();
275   /* Setup stack for thread manager */
276   __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE);
277   if (__pthread_manager_thread_bos == NULL) return -1;
278   __pthread_manager_thread_tos =
279     __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE;
280   /* Setup pipe to communicate with thread manager */
281   if (pipe(manager_pipe) == -1) {
282     free(__pthread_manager_thread_bos);
283     return -1;
284   }
285   /* Start the thread manager */
286   pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
287                 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND
288 #ifdef CLONE_PTRACE
289                 | CLONE_PTRACE
290 #endif
291                 , (void *)(long)manager_pipe[0]);
292   if (pid == -1) {
293     free(__pthread_manager_thread_bos);
294     __libc_close(manager_pipe[0]);
295     __libc_close(manager_pipe[1]);
296     return -1;
297   }
298   __pthread_manager_request = manager_pipe[1]; /* writing end */
299   __pthread_manager_reader = manager_pipe[0]; /* reading end */
300   __pthread_manager_thread.p_pid = pid;
301   /* Make gdb aware of new thread manager */
302   if (__pthread_threads_debug) raise(__pthread_sig_cancel);
303   /* Synchronize debugging of the thread manager */
304   request.req_kind = REQ_DEBUG;
305   __libc_write(__pthread_manager_request, (char *) &request, sizeof(request));
306   return 0;
307 }
308
309 /* Thread creation */
310
311 int __pthread_create_2_1(pthread_t *thread, const pthread_attr_t *attr,
312                          void * (*start_routine)(void *), void *arg)
313 {
314   pthread_descr self = thread_self();
315   struct pthread_request request;
316   if (__pthread_manager_request < 0) {
317     if (__pthread_initialize_manager() < 0) return EAGAIN;
318   }
319   request.req_thread = self;
320   request.req_kind = REQ_CREATE;
321   request.req_args.create.attr = attr;
322   request.req_args.create.fn = start_routine;
323   request.req_args.create.arg = arg;
324   sigprocmask(SIG_SETMASK, (const sigset_t *) NULL,
325               &request.req_args.create.mask);
326   __libc_write(__pthread_manager_request, (char *) &request, sizeof(request));
327   suspend(self);
328   if (THREAD_GETMEM(self, p_retcode) == 0)
329     *thread = (pthread_t) THREAD_GETMEM(self, p_retval);
330   return THREAD_GETMEM(self, p_retcode);
331 }
332
333 #if defined HAVE_ELF && defined PIC && defined DO_VERSIONING
334 default_symbol_version (__pthread_create_2_1, pthread_create, GLIBC_2.1);
335
336 int __pthread_create_2_0(pthread_t *thread, const pthread_attr_t *attr,
337                          void * (*start_routine)(void *), void *arg)
338 {
339   /* The ATTR attribute is not really of type `pthread_attr_t *'.  It has
340      the old size and access to the new members might crash the program.
341      We convert the struct now.  */
342   pthread_attr_t new_attr;
343
344   if (attr != NULL)
345     {
346       size_t ps = __getpagesize ();
347
348       memcpy (&new_attr, attr,
349               (size_t) &(((pthread_attr_t*)NULL)->__guardsize));
350       new_attr.__guardsize = ps;
351       new_attr.__stackaddr_set = 0;
352       new_attr.__stackaddr = NULL;
353       new_attr.__stacksize = STACK_SIZE - ps;
354       attr = &new_attr;
355     }
356   return __pthread_create_2_1 (thread, attr, start_routine, arg);
357 }
358 symbol_version (__pthread_create_2_0, pthread_create, GLIBC_2.0);
359 #else
360 strong_alias (__pthread_create_2_1, pthread_create)
361 #endif
362
363 /* Simple operations on thread identifiers */
364
365 pthread_t pthread_self(void)
366 {
367   pthread_descr self = thread_self();
368   return THREAD_GETMEM(self, p_tid);
369 }
370
371 int pthread_equal(pthread_t thread1, pthread_t thread2)
372 {
373   return thread1 == thread2;
374 }
375
376 /* Helper function for thread_self in the case of user-provided stacks */
377
378 #ifndef THREAD_SELF
379
380 pthread_descr __pthread_find_self()
381 {
382   char * sp = CURRENT_STACK_FRAME;
383   pthread_handle h;
384
385   /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is
386      the manager threads handled specially in thread_self(), so start at 2 */
387   h = __pthread_handles + 2;
388   while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++;
389   return h->h_descr;
390 }
391
392 #endif
393
394 /* Thread scheduling */
395
396 int pthread_setschedparam(pthread_t thread, int policy,
397                           const struct sched_param *param)
398 {
399   pthread_handle handle = thread_handle(thread);
400   pthread_descr th;
401
402   __pthread_lock(&handle->h_lock, NULL);
403   if (invalid_handle(handle, thread)) {
404     __pthread_unlock(&handle->h_lock);
405     return ESRCH;
406   }
407   th = handle->h_descr;
408   if (__sched_setscheduler(th->p_pid, policy, param) == -1) {
409     __pthread_unlock(&handle->h_lock);
410     return errno;
411   }
412   th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority;
413   __pthread_unlock(&handle->h_lock);
414   if (__pthread_manager_request >= 0)
415     __pthread_manager_adjust_prio(th->p_priority);
416   return 0;
417 }
418
419 int pthread_getschedparam(pthread_t thread, int *policy,
420                           struct sched_param *param)
421 {
422   pthread_handle handle = thread_handle(thread);
423   int pid, pol;
424
425   __pthread_lock(&handle->h_lock, NULL);
426   if (invalid_handle(handle, thread)) {
427     __pthread_unlock(&handle->h_lock);
428     return ESRCH;
429   }
430   pid = handle->h_descr->p_pid;
431   __pthread_unlock(&handle->h_lock);
432   pol = __sched_getscheduler(pid);
433   if (pol == -1) return errno;
434   if (__sched_getparam(pid, param) == -1) return errno;
435   *policy = pol;
436   return 0;
437 }
438
439 /* Process-wide exit() request */
440
441 static void pthread_exit_process(int retcode, void *arg)
442 {
443   struct pthread_request request;
444   pthread_descr self = thread_self();
445
446   if (__pthread_manager_request >= 0) {
447     request.req_thread = self;
448     request.req_kind = REQ_PROCESS_EXIT;
449     request.req_args.exit.code = retcode;
450     __libc_write(__pthread_manager_request,
451                  (char *) &request, sizeof(request));
452     suspend(self);
453     /* Main thread should accumulate times for thread manager and its
454        children, so that timings for main thread account for all threads. */
455     if (self == __pthread_main_thread)
456       waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
457   }
458 }
459
460 /* The handler for the RESTART signal just records the signal received
461    in the thread descriptor, and optionally performs a siglongjmp
462    (for pthread_cond_timedwait). */
463
464 #ifndef __i386__
465 static void pthread_handle_sigrestart(int sig)
466 {
467   pthread_descr self = thread_self();
468 #else
469 static void pthread_handle_sigrestart(int sig, struct sigcontext ctx)
470 {
471   pthread_descr self;
472   asm volatile ("movw %w0,%%gs" : : "r" (ctx.gs));
473   self = thread_self();
474 #endif
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 /* The handler for the CANCEL signal checks for cancellation
481    (in asynchronous mode), for process-wide exit and exec requests.
482    For the thread manager thread, redirect the signal to 
483    __pthread_manager_sighandler.
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     {
509       __pthread_manager_sighandler(sig);
510       return;
511     }
512   if (__pthread_exit_requested) {
513     /* Main thread should accumulate times for thread manager and its
514        children, so that timings for main thread account for all threads. */
515     if (self == __pthread_main_thread)
516       waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE);
517     _exit(__pthread_exit_code);
518   }
519   if (THREAD_GETMEM(self, p_canceled)
520       && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
521     if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS)
522       pthread_exit(PTHREAD_CANCELED);
523     jmpbuf = THREAD_GETMEM(self, p_cancel_jmp);
524     if (jmpbuf != NULL) {
525       THREAD_SETMEM(self, p_cancel_jmp, NULL);
526       siglongjmp(*jmpbuf, 1);
527     }
528   }
529 }
530
531 /* Reset the state of the thread machinery after a fork().
532    Close the pipe used for requests and set the main thread to the forked
533    thread.
534    Notice that we can't free the stack segments, as the forked thread
535    may hold pointers into them. */
536
537 void __pthread_reset_main_thread()
538 {
539   pthread_descr self = thread_self();
540
541   if (__pthread_manager_request != -1) {
542     /* Free the thread manager stack */
543     free(__pthread_manager_thread_bos);
544     __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL;
545     /* Close the two ends of the pipe */
546     __libc_close(__pthread_manager_request);
547     __libc_close(__pthread_manager_reader);
548     __pthread_manager_request = __pthread_manager_reader = -1;
549   }
550   /* Update the pid of the main thread */
551   THREAD_SETMEM(self, p_pid, __getpid());
552   /* Make the forked thread the main thread */
553   __pthread_main_thread = self;
554   THREAD_SETMEM(self, p_nextlive, self);
555   THREAD_SETMEM(self, p_prevlive, self);
556   /* Now this thread modifies the global variables.  */
557   THREAD_SETMEM(self, p_errnop, &_errno);
558   THREAD_SETMEM(self, p_h_errnop, &_h_errno);
559 }
560
561 /* Process-wide exec() request */
562
563 void __pthread_kill_other_threads_np(void)
564 {
565   /* Terminate all other threads and thread manager */
566   pthread_exit_process(0, NULL);
567   /* Make current thread the main thread in case the calling thread
568      changes its mind, does not exec(), and creates new threads instead. */
569   __pthread_reset_main_thread();
570 }
571 weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np)
572
573 /* Concurrency symbol level.  */
574 static int current_level;
575
576 int __pthread_setconcurrency(int level)
577 {
578   /* We don't do anything unless we have found a useful interpretation.  */
579   current_level = level;
580   return 0;
581 }
582 weak_alias (__pthread_setconcurrency, pthread_setconcurrency)
583
584 int __pthread_getconcurrency(void)
585 {
586   return current_level;
587 }
588 weak_alias (__pthread_getconcurrency, pthread_getconcurrency)
589
590 /* Debugging aid */
591
592 #ifdef DEBUG
593 #include <stdarg.h>
594
595 void __pthread_message(char * fmt, ...)
596 {
597   char buffer[1024];
598   va_list args;
599   sprintf(buffer, "%05d : ", __getpid());
600   va_start(args, fmt);
601   vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args);
602   va_end(args);
603   __libc_write(2, buffer, strlen(buffer));
604 }
605
606 #endif
607
608
609 #ifndef PIC
610 /* We need a hook to force the cancelation wrappers to be linked in when
611    static libpthread is used.  */
612 extern const int __pthread_provide_wrappers;
613 static const int *const __pthread_require_wrappers =
614   &__pthread_provide_wrappers;
615 #endif