1/* Threads compatibility routines for libgcc2 and libobjc.  */
2/* Compile this one with gcc.  */
3/* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4   2008, 2009, 2010 Free Software Foundation, Inc.
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18Under Section 7 of GPL version 3, you are granted additional
19permissions described in the GCC Runtime Library Exception, version
203.1, as published by the Free Software Foundation.
21
22You should have received a copy of the GNU General Public License and
23a copy of the GCC Runtime Library Exception along with this program;
24see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25<http://www.gnu.org/licenses/>.  */
26
27#ifndef _GLIBCXX_GCC_GTHR_POSIX_H
28#define _GLIBCXX_GCC_GTHR_POSIX_H
29
30/* POSIX threads specific definitions.
31   Easy, since the interface is just one-to-one mapping.  */
32
33#define __GTHREADS 1
34#define __GTHREADS_CXX0X 1
35
36/* Some implementations of <pthread.h> require this to be defined.  */
37#if !defined(_REENTRANT) && defined(__osf__)
38#define _REENTRANT 1
39#endif
40
41/* The following should normally be in a different header file,
42 * but I couldn't find the right location. The point of the macro
43 * definition below is to prevent libsupc++ and libstdc++ to reference
44 * weak symbols in their static C++ constructors. Such code crashes
45 * when a shared object linked statically to these libraries is
46 * loaded on Android 2.1 (Eclair) and older platform releases, due
47 * to a dynamic linker bug.
48 */
49#ifdef __ANDROID__
50#undef _GLIBCXX_GTHREAD_USE_WEAK
51#define _GLIBCXX_GTHREAD_USE_WEAK 0
52#endif
53
54#include <pthread.h>
55#include <unistd.h>
56
57typedef pthread_t __gthread_t;
58typedef pthread_key_t __gthread_key_t;
59typedef pthread_once_t __gthread_once_t;
60typedef pthread_mutex_t __gthread_mutex_t;
61typedef pthread_mutex_t __gthread_recursive_mutex_t;
62typedef pthread_cond_t __gthread_cond_t;
63typedef struct timespec __gthread_time_t;
64
65/* POSIX like conditional variables are supported.  Please look at comments
66   in gthr.h for details. */
67#define __GTHREAD_HAS_COND	1
68
69#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
70#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
71#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
72#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
73#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
74#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
75#else
76#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
77#endif
78#define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
79#define __GTHREAD_TIME_INIT {0,0}
80
81#if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
82# ifndef __gthrw_pragma
83#  define __gthrw_pragma(pragma)
84# endif
85# define __gthrw2(name,name2,type) \
86  static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
87  __gthrw_pragma(weak type)
88# define __gthrw_(name) __gthrw_ ## name
89#else
90# define __gthrw2(name,name2,type)
91# define __gthrw_(name) name
92#endif
93
94/* Typically, __gthrw_foo is a weak reference to symbol foo.  */
95#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
96
97/* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
98   map a subset of the POSIX pthread API to mangled versions of their
99   names.  */
100#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
101#define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
102__gthrw3(pthread_once)
103__gthrw3(pthread_getspecific)
104__gthrw3(pthread_setspecific)
105
106__gthrw3(pthread_create)
107__gthrw3(pthread_join)
108__gthrw3(pthread_detach)
109__gthrw3(pthread_equal)
110__gthrw3(pthread_self)
111__gthrw3(pthread_cancel)
112__gthrw3(sched_yield)
113
114__gthrw3(pthread_mutex_lock)
115__gthrw3(pthread_mutex_trylock)
116#ifdef _POSIX_TIMEOUTS
117#if _POSIX_TIMEOUTS >= 0
118__gthrw3(pthread_mutex_timedlock)
119#endif
120#endif /* _POSIX_TIMEOUTS */
121__gthrw3(pthread_mutex_unlock)
122__gthrw3(pthread_mutex_init)
123__gthrw3(pthread_mutex_destroy)
124
125__gthrw3(pthread_cond_broadcast)
126__gthrw3(pthread_cond_signal)
127__gthrw3(pthread_cond_wait)
128__gthrw3(pthread_cond_timedwait)
129__gthrw3(pthread_cond_destroy)
130#else
131__gthrw(pthread_once)
132__gthrw(pthread_getspecific)
133__gthrw(pthread_setspecific)
134
135__gthrw(pthread_create)
136__gthrw(pthread_join)
137__gthrw(pthread_equal)
138__gthrw(pthread_self)
139__gthrw(pthread_detach)
140#ifndef __BIONIC__
141__gthrw(pthread_cancel)
142#endif
143__gthrw(sched_yield)
144
145__gthrw(pthread_mutex_lock)
146__gthrw(pthread_mutex_trylock)
147#ifdef _POSIX_TIMEOUTS
148#if _POSIX_TIMEOUTS >= 0
149__gthrw(pthread_mutex_timedlock)
150#endif
151#endif /* _POSIX_TIMEOUTS */
152__gthrw(pthread_mutex_unlock)
153__gthrw(pthread_mutex_init)
154__gthrw(pthread_mutex_destroy)
155
156__gthrw(pthread_cond_broadcast)
157__gthrw(pthread_cond_signal)
158__gthrw(pthread_cond_wait)
159__gthrw(pthread_cond_timedwait)
160__gthrw(pthread_cond_destroy)
161#endif
162
163__gthrw(pthread_key_create)
164__gthrw(pthread_key_delete)
165__gthrw(pthread_mutexattr_init)
166__gthrw(pthread_mutexattr_settype)
167__gthrw(pthread_mutexattr_destroy)
168
169
170#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
171/* Objective-C.  */
172#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
173__gthrw3(pthread_cond_init)
174__gthrw3(pthread_exit)
175#else
176__gthrw(pthread_cond_init)
177__gthrw(pthread_exit)
178#endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
179#ifdef _POSIX_PRIORITY_SCHEDULING
180#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
181__gthrw(sched_get_priority_max)
182__gthrw(sched_get_priority_min)
183#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
184#endif /* _POSIX_PRIORITY_SCHEDULING */
185__gthrw(pthread_attr_destroy)
186__gthrw(pthread_attr_init)
187__gthrw(pthread_attr_setdetachstate)
188#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
189__gthrw(pthread_getschedparam)
190__gthrw(pthread_setschedparam)
191#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
192#endif /* _LIBOBJC || _LIBOBJC_WEAK */
193
194#if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
195
196/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
197   -pthreads is not specified.  The functions are dummies and most return an
198   error value.  However pthread_once returns 0 without invoking the routine
199   it is passed so we cannot pretend that the interface is active if -pthreads
200   is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
201   we need to play the usual game with weak symbols.  On Solaris 10 and up, a
202   working interface is always exposed.  On FreeBSD 6 and later, libc also
203   exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
204   to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
205   which means the alternate __gthread_active_p below cannot be used there.  */
206
207#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
208
209static volatile int __gthread_active = -1;
210
211static void
212__gthread_trigger (void)
213{
214  __gthread_active = 1;
215}
216
217static inline int
218__gthread_active_p (void)
219{
220  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
221  static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
222
223  /* Avoid reading __gthread_active twice on the main code path.  */
224  int __gthread_active_latest_value = __gthread_active;
225
226  /* This test is not protected to avoid taking a lock on the main code
227     path so every update of __gthread_active in a threaded program must
228     be atomic with regard to the result of the test.  */
229  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
230    {
231      if (__gthrw_(pthread_once))
232	{
233	  /* If this really is a threaded program, then we must ensure that
234	     __gthread_active has been set to 1 before exiting this block.  */
235	  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
236	  __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
237	  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
238	}
239
240      /* Make sure we'll never enter this block again.  */
241      if (__gthread_active < 0)
242	__gthread_active = 0;
243
244      __gthread_active_latest_value = __gthread_active;
245    }
246
247  return __gthread_active_latest_value != 0;
248}
249
250#else /* neither FreeBSD nor Solaris */
251
252static inline int
253__gthread_active_p (void)
254{
255  static void *const __gthread_active_ptr
256    = __extension__ (void *) &__gthrw_(
257/* Android's C library does not provide pthread_cancel, check for
258   `pthread_create' instead.  */
259#ifndef __BIONIC__
260				       pthread_cancel
261#else
262				       pthread_create
263#endif
264				       );
265  return __gthread_active_ptr != 0;
266}
267
268#endif /* FreeBSD or Solaris */
269
270#else /* not __GXX_WEAK__ */
271
272/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
273   calls in shared flavors of the HP-UX C library.  Most of the stubs
274   have no functionality.  The details are described in the "libc cumulative
275   patch" for each subversion of HP-UX 11.  There are two special interfaces
276   provided for checking whether an application is linked to a shared pthread
277   library or not.  However, these interfaces aren't available in early
278   libpthread libraries.  We also need a test that works for archive
279   libraries.  We can't use pthread_once as some libc versions call the
280   init function.  We also can't use pthread_create or pthread_attr_init
281   as these create a thread and thereby prevent changing the default stack
282   size.  The function pthread_default_stacksize_np is available in both
283   the archive and shared versions of libpthread.   It can be used to
284   determine the default pthread stack size.  There is a stub in some
285   shared libc versions which returns a zero size if pthreads are not
286   active.  We provide an equivalent stub to handle cases where libc
287   doesn't provide one.  */
288
289#if defined(__hppa__) && defined(__hpux__)
290
291static volatile int __gthread_active = -1;
292
293static inline int
294__gthread_active_p (void)
295{
296  /* Avoid reading __gthread_active twice on the main code path.  */
297  int __gthread_active_latest_value = __gthread_active;
298  size_t __s;
299
300  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
301    {
302      pthread_default_stacksize_np (0, &__s);
303      __gthread_active = __s ? 1 : 0;
304      __gthread_active_latest_value = __gthread_active;
305    }
306
307  return __gthread_active_latest_value != 0;
308}
309
310#else /* not hppa-hpux */
311
312static inline int
313__gthread_active_p (void)
314{
315  return 1;
316}
317
318#endif /* hppa-hpux */
319
320#endif /* __GXX_WEAK__ */
321
322#ifdef _LIBOBJC
323
324/* This is the config.h file in libobjc/ */
325#include <config.h>
326
327#ifdef HAVE_SCHED_H
328# include <sched.h>
329#endif
330
331/* Key structure for maintaining thread specific storage */
332static pthread_key_t _objc_thread_storage;
333static pthread_attr_t _objc_thread_attribs;
334
335/* Thread local storage for a single thread */
336static void *thread_local_storage = NULL;
337
338/* Backend initialization functions */
339
340/* Initialize the threads subsystem.  */
341static inline int
342__gthread_objc_init_thread_system (void)
343{
344  if (__gthread_active_p ())
345    {
346      /* Initialize the thread storage key.  */
347      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
348	{
349	  /* The normal default detach state for threads is
350	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
351	   * when you think they should.  */
352	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
353	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
354					      PTHREAD_CREATE_DETACHED) == 0)
355	    return 0;
356	}
357    }
358
359  return -1;
360}
361
362/* Close the threads subsystem.  */
363static inline int
364__gthread_objc_close_thread_system (void)
365{
366  if (__gthread_active_p ()
367      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
368      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
369    return 0;
370
371  return -1;
372}
373
374/* Backend thread functions */
375
376/* Create a new thread of execution.  */
377static inline objc_thread_t
378__gthread_objc_thread_detach (void (*func)(void *), void *arg)
379{
380  objc_thread_t thread_id;
381  pthread_t new_thread_handle;
382
383  if (!__gthread_active_p ())
384    return NULL;
385
386  if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs,
387				  (void *) func, arg)))
388    thread_id = (objc_thread_t) new_thread_handle;
389  else
390    thread_id = NULL;
391
392  return thread_id;
393}
394
395/* Set the current thread's priority.  */
396static inline int
397__gthread_objc_thread_set_priority (int priority)
398{
399  if (!__gthread_active_p ())
400    return -1;
401  else
402    {
403#ifdef _POSIX_PRIORITY_SCHEDULING
404#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
405      pthread_t thread_id = __gthrw_(pthread_self) ();
406      int policy;
407      struct sched_param params;
408      int priority_min, priority_max;
409
410      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
411	{
412	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
413	    return -1;
414
415	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
416	    return -1;
417
418	  if (priority > priority_max)
419	    priority = priority_max;
420	  else if (priority < priority_min)
421	    priority = priority_min;
422	  params.sched_priority = priority;
423
424	  /*
425	   * The solaris 7 and several other man pages incorrectly state that
426	   * this should be a pointer to policy but pthread.h is universally
427	   * at odds with this.
428	   */
429	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
430	    return 0;
431	}
432#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
433#endif /* _POSIX_PRIORITY_SCHEDULING */
434      return -1;
435    }
436}
437
438/* Return the current thread's priority.  */
439static inline int
440__gthread_objc_thread_get_priority (void)
441{
442#ifdef _POSIX_PRIORITY_SCHEDULING
443#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
444  if (__gthread_active_p ())
445    {
446      int policy;
447      struct sched_param params;
448
449      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
450	return params.sched_priority;
451      else
452	return -1;
453    }
454  else
455#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
456#endif /* _POSIX_PRIORITY_SCHEDULING */
457    return OBJC_THREAD_INTERACTIVE_PRIORITY;
458}
459
460/* Yield our process time to another thread.  */
461static inline void
462__gthread_objc_thread_yield (void)
463{
464  if (__gthread_active_p ())
465    __gthrw_(sched_yield) ();
466}
467
468/* Terminate the current thread.  */
469static inline int
470__gthread_objc_thread_exit (void)
471{
472  if (__gthread_active_p ())
473    /* exit the thread */
474    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
475
476  /* Failed if we reached here */
477  return -1;
478}
479
480/* Returns an integer value which uniquely describes a thread.  */
481static inline objc_thread_t
482__gthread_objc_thread_id (void)
483{
484  if (__gthread_active_p ())
485    return (objc_thread_t) __gthrw_(pthread_self) ();
486  else
487    return (objc_thread_t) 1;
488}
489
490/* Sets the thread's local storage pointer.  */
491static inline int
492__gthread_objc_thread_set_data (void *value)
493{
494  if (__gthread_active_p ())
495    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
496  else
497    {
498      thread_local_storage = value;
499      return 0;
500    }
501}
502
503/* Returns the thread's local storage pointer.  */
504static inline void *
505__gthread_objc_thread_get_data (void)
506{
507  if (__gthread_active_p ())
508    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
509  else
510    return thread_local_storage;
511}
512
513/* Backend mutex functions */
514
515/* Allocate a mutex.  */
516static inline int
517__gthread_objc_mutex_allocate (objc_mutex_t mutex)
518{
519  if (__gthread_active_p ())
520    {
521      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
522
523      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
524	{
525	  objc_free (mutex->backend);
526	  mutex->backend = NULL;
527	  return -1;
528	}
529    }
530
531  return 0;
532}
533
534/* Deallocate a mutex.  */
535static inline int
536__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
537{
538  if (__gthread_active_p ())
539    {
540      int count;
541
542      /*
543       * Posix Threads specifically require that the thread be unlocked
544       * for __gthrw_(pthread_mutex_destroy) to work.
545       */
546
547      do
548	{
549	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
550	  if (count < 0)
551	    return -1;
552	}
553      while (count);
554
555      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
556	return -1;
557
558      objc_free (mutex->backend);
559      mutex->backend = NULL;
560    }
561  return 0;
562}
563
564/* Grab a lock on a mutex.  */
565static inline int
566__gthread_objc_mutex_lock (objc_mutex_t mutex)
567{
568  if (__gthread_active_p ()
569      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
570    {
571      return -1;
572    }
573
574  return 0;
575}
576
577/* Try to grab a lock on a mutex.  */
578static inline int
579__gthread_objc_mutex_trylock (objc_mutex_t mutex)
580{
581  if (__gthread_active_p ()
582      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
583    {
584      return -1;
585    }
586
587  return 0;
588}
589
590/* Unlock the mutex */
591static inline int
592__gthread_objc_mutex_unlock (objc_mutex_t mutex)
593{
594  if (__gthread_active_p ()
595      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
596    {
597      return -1;
598    }
599
600  return 0;
601}
602
603/* Backend condition mutex functions */
604
605/* Allocate a condition.  */
606static inline int
607__gthread_objc_condition_allocate (objc_condition_t condition)
608{
609  if (__gthread_active_p ())
610    {
611      condition->backend = objc_malloc (sizeof (pthread_cond_t));
612
613      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
614	{
615	  objc_free (condition->backend);
616	  condition->backend = NULL;
617	  return -1;
618	}
619    }
620
621  return 0;
622}
623
624/* Deallocate a condition.  */
625static inline int
626__gthread_objc_condition_deallocate (objc_condition_t condition)
627{
628  if (__gthread_active_p ())
629    {
630      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
631	return -1;
632
633      objc_free (condition->backend);
634      condition->backend = NULL;
635    }
636  return 0;
637}
638
639/* Wait on the condition */
640static inline int
641__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
642{
643  if (__gthread_active_p ())
644    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
645			      (pthread_mutex_t *) mutex->backend);
646  else
647    return 0;
648}
649
650/* Wake up all threads waiting on this condition.  */
651static inline int
652__gthread_objc_condition_broadcast (objc_condition_t condition)
653{
654  if (__gthread_active_p ())
655    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
656  else
657    return 0;
658}
659
660/* Wake up one thread waiting on this condition.  */
661static inline int
662__gthread_objc_condition_signal (objc_condition_t condition)
663{
664  if (__gthread_active_p ())
665    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
666  else
667    return 0;
668}
669
670#else /* _LIBOBJC */
671
672static inline int
673__gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
674		  void *__args)
675{
676  return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
677}
678
679static inline int
680__gthread_join (__gthread_t __threadid, void **__value_ptr)
681{
682  return __gthrw_(pthread_join) (__threadid, __value_ptr);
683}
684
685static inline int
686__gthread_detach (__gthread_t __threadid)
687{
688  return __gthrw_(pthread_detach) (__threadid);
689}
690
691static inline int
692__gthread_equal (__gthread_t __t1, __gthread_t __t2)
693{
694  return __gthrw_(pthread_equal) (__t1, __t2);
695}
696
697static inline __gthread_t
698__gthread_self (void)
699{
700  return __gthrw_(pthread_self) ();
701}
702
703static inline int
704__gthread_yield (void)
705{
706  return __gthrw_(sched_yield) ();
707}
708
709static inline int
710__gthread_once (__gthread_once_t *__once, void (*__func) (void))
711{
712  if (__gthread_active_p ())
713    return __gthrw_(pthread_once) (__once, __func);
714  else
715    return -1;
716}
717
718static inline int
719__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
720{
721  return __gthrw_(pthread_key_create) (__key, __dtor);
722}
723
724static inline int
725__gthread_key_delete (__gthread_key_t __key)
726{
727  return __gthrw_(pthread_key_delete) (__key);
728}
729
730static inline void *
731__gthread_getspecific (__gthread_key_t __key)
732{
733  return __gthrw_(pthread_getspecific) (__key);
734}
735
736static inline int
737__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
738{
739  return __gthrw_(pthread_setspecific) (__key, __ptr);
740}
741
742static inline int
743__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
744{
745  if (__gthread_active_p ())
746    return __gthrw_(pthread_mutex_destroy) (__mutex);
747  else
748    return 0;
749}
750
751static inline int
752__gthread_mutex_lock (__gthread_mutex_t *__mutex)
753{
754  if (__gthread_active_p ())
755    return __gthrw_(pthread_mutex_lock) (__mutex);
756  else
757    return 0;
758}
759
760static inline int
761__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
762{
763  if (__gthread_active_p ())
764    return __gthrw_(pthread_mutex_trylock) (__mutex);
765  else
766    return 0;
767}
768
769#ifdef _POSIX_TIMEOUTS
770#if _POSIX_TIMEOUTS >= 0
771static inline int
772__gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
773			   const __gthread_time_t *__abs_timeout)
774{
775  if (__gthread_active_p ())
776    return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout);
777  else
778    return 0;
779}
780#endif
781#endif
782
783static inline int
784__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
785{
786  if (__gthread_active_p ())
787    return __gthrw_(pthread_mutex_unlock) (__mutex);
788  else
789    return 0;
790}
791
792#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
793static inline int
794__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
795{
796  if (__gthread_active_p ())
797    {
798      pthread_mutexattr_t __attr;
799      int __r;
800
801      __r = __gthrw_(pthread_mutexattr_init) (&__attr);
802      if (!__r)
803	__r = __gthrw_(pthread_mutexattr_settype) (&__attr,
804						   PTHREAD_MUTEX_RECURSIVE);
805      if (!__r)
806	__r = __gthrw_(pthread_mutex_init) (__mutex, &__attr);
807      if (!__r)
808	__r = __gthrw_(pthread_mutexattr_destroy) (&__attr);
809      return __r;
810    }
811  return 0;
812}
813#endif
814
815static inline int
816__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
817{
818  return __gthread_mutex_lock (__mutex);
819}
820
821static inline int
822__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
823{
824  return __gthread_mutex_trylock (__mutex);
825}
826
827#ifdef _POSIX_TIMEOUTS
828#if _POSIX_TIMEOUTS >= 0
829static inline int
830__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
831				     const __gthread_time_t *__abs_timeout)
832{
833  return __gthread_mutex_timedlock (__mutex, __abs_timeout);
834}
835#endif
836#endif
837
838static inline int
839__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
840{
841  return __gthread_mutex_unlock (__mutex);
842}
843
844static inline int
845__gthread_cond_broadcast (__gthread_cond_t *__cond)
846{
847  return __gthrw_(pthread_cond_broadcast) (__cond);
848}
849
850static inline int
851__gthread_cond_signal (__gthread_cond_t *__cond)
852{
853  return __gthrw_(pthread_cond_signal) (__cond);
854}
855
856static inline int
857__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
858{
859  return __gthrw_(pthread_cond_wait) (__cond, __mutex);
860}
861
862static inline int
863__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
864			  const __gthread_time_t *__abs_timeout)
865{
866  return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
867}
868
869static inline int
870__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
871			       __gthread_recursive_mutex_t *__mutex)
872{
873  return __gthread_cond_wait (__cond, __mutex);
874}
875
876static inline int
877__gthread_cond_timedwait_recursive (__gthread_cond_t *__cond,
878				    __gthread_recursive_mutex_t *__mutex,
879				    const __gthread_time_t *__abs_timeout)
880{
881  return __gthread_cond_timedwait (__cond, __mutex, __abs_timeout);
882}
883
884static inline int
885__gthread_cond_destroy (__gthread_cond_t* __cond)
886{
887  return __gthrw_(pthread_cond_destroy) (__cond);
888}
889
890#endif /* _LIBOBJC */
891
892#endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */
893