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 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 pthread
277   library or not.  However, these interfaces aren't available in early
278   libc versions.  We also can't use pthread_once as some libc versions
279   call the init function.  So, we use pthread_create to check whether it
280   is possible to create a thread or not.  The stub implementation returns
281   the error number ENOSYS.  */
282
283#if defined(__hppa__) && defined(__hpux__)
284
285#include <errno.h>
286
287static volatile int __gthread_active = -1;
288
289static void *
290__gthread_start (void *__arg __attribute__((unused)))
291{
292  return NULL;
293}
294
295static void __gthread_active_init (void) __attribute__((noinline));
296static void
297__gthread_active_init (void)
298{
299  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
300  pthread_t __t;
301  pthread_attr_t __a;
302  int __result;
303
304  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
305  if (__gthread_active < 0)
306    {
307      __gthrw_(pthread_attr_init) (&__a);
308      __gthrw_(pthread_attr_setdetachstate) (&__a, PTHREAD_CREATE_DETACHED);
309      __result = __gthrw_(pthread_create) (&__t, &__a, __gthread_start, NULL);
310      if (__result != ENOSYS)
311	__gthread_active = 1;
312      else
313	__gthread_active = 0;
314      __gthrw_(pthread_attr_destroy) (&__a);
315    }
316  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
317}
318
319static inline int
320__gthread_active_p (void)
321{
322  /* Avoid reading __gthread_active twice on the main code path.  */
323  int __gthread_active_latest_value = __gthread_active;
324
325  /* This test is not protected to avoid taking a lock on the main code
326     path so every update of __gthread_active in a threaded program must
327     be atomic with regard to the result of the test.  */
328  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
329    {
330      __gthread_active_init ();
331      __gthread_active_latest_value = __gthread_active;
332    }
333
334  return __gthread_active_latest_value != 0;
335}
336
337#else /* not hppa-hpux */
338
339static inline int
340__gthread_active_p (void)
341{
342  return 1;
343}
344
345#endif /* hppa-hpux */
346
347#endif /* __GXX_WEAK__ */
348
349#ifdef _LIBOBJC
350
351/* This is the config.h file in libobjc/ */
352#include <config.h>
353
354#ifdef HAVE_SCHED_H
355# include <sched.h>
356#endif
357
358/* Key structure for maintaining thread specific storage */
359static pthread_key_t _objc_thread_storage;
360static pthread_attr_t _objc_thread_attribs;
361
362/* Thread local storage for a single thread */
363static void *thread_local_storage = NULL;
364
365/* Backend initialization functions */
366
367/* Initialize the threads subsystem.  */
368static inline int
369__gthread_objc_init_thread_system (void)
370{
371  if (__gthread_active_p ())
372    {
373      /* Initialize the thread storage key.  */
374      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
375	{
376	  /* The normal default detach state for threads is
377	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
378	   * when you think they should.  */
379	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
380	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
381					      PTHREAD_CREATE_DETACHED) == 0)
382	    return 0;
383	}
384    }
385
386  return -1;
387}
388
389/* Close the threads subsystem.  */
390static inline int
391__gthread_objc_close_thread_system (void)
392{
393  if (__gthread_active_p ()
394      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
395      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
396    return 0;
397
398  return -1;
399}
400
401/* Backend thread functions */
402
403/* Create a new thread of execution.  */
404static inline objc_thread_t
405__gthread_objc_thread_detach (void (*func)(void *), void *arg)
406{
407  objc_thread_t thread_id;
408  pthread_t new_thread_handle;
409
410  if (!__gthread_active_p ())
411    return NULL;
412
413  if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
414    thread_id = (objc_thread_t) new_thread_handle;
415  else
416    thread_id = NULL;
417
418  return thread_id;
419}
420
421/* Set the current thread's priority.  */
422static inline int
423__gthread_objc_thread_set_priority (int priority)
424{
425  if (!__gthread_active_p ())
426    return -1;
427  else
428    {
429#ifdef _POSIX_PRIORITY_SCHEDULING
430#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
431      pthread_t thread_id = __gthrw_(pthread_self) ();
432      int policy;
433      struct sched_param params;
434      int priority_min, priority_max;
435
436      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
437	{
438	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
439	    return -1;
440
441	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
442	    return -1;
443
444	  if (priority > priority_max)
445	    priority = priority_max;
446	  else if (priority < priority_min)
447	    priority = priority_min;
448	  params.sched_priority = priority;
449
450	  /*
451	   * The solaris 7 and several other man pages incorrectly state that
452	   * this should be a pointer to policy but pthread.h is universally
453	   * at odds with this.
454	   */
455	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
456	    return 0;
457	}
458#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
459#endif /* _POSIX_PRIORITY_SCHEDULING */
460      return -1;
461    }
462}
463
464/* Return the current thread's priority.  */
465static inline int
466__gthread_objc_thread_get_priority (void)
467{
468#ifdef _POSIX_PRIORITY_SCHEDULING
469#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
470  if (__gthread_active_p ())
471    {
472      int policy;
473      struct sched_param params;
474
475      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
476	return params.sched_priority;
477      else
478	return -1;
479    }
480  else
481#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
482#endif /* _POSIX_PRIORITY_SCHEDULING */
483    return OBJC_THREAD_INTERACTIVE_PRIORITY;
484}
485
486/* Yield our process time to another thread.  */
487static inline void
488__gthread_objc_thread_yield (void)
489{
490  if (__gthread_active_p ())
491    __gthrw_(sched_yield) ();
492}
493
494/* Terminate the current thread.  */
495static inline int
496__gthread_objc_thread_exit (void)
497{
498  if (__gthread_active_p ())
499    /* exit the thread */
500    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
501
502  /* Failed if we reached here */
503  return -1;
504}
505
506/* Returns an integer value which uniquely describes a thread.  */
507static inline objc_thread_t
508__gthread_objc_thread_id (void)
509{
510  if (__gthread_active_p ())
511    return (objc_thread_t) __gthrw_(pthread_self) ();
512  else
513    return (objc_thread_t) 1;
514}
515
516/* Sets the thread's local storage pointer.  */
517static inline int
518__gthread_objc_thread_set_data (void *value)
519{
520  if (__gthread_active_p ())
521    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
522  else
523    {
524      thread_local_storage = value;
525      return 0;
526    }
527}
528
529/* Returns the thread's local storage pointer.  */
530static inline void *
531__gthread_objc_thread_get_data (void)
532{
533  if (__gthread_active_p ())
534    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
535  else
536    return thread_local_storage;
537}
538
539/* Backend mutex functions */
540
541/* Allocate a mutex.  */
542static inline int
543__gthread_objc_mutex_allocate (objc_mutex_t mutex)
544{
545  if (__gthread_active_p ())
546    {
547      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
548
549      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
550	{
551	  objc_free (mutex->backend);
552	  mutex->backend = NULL;
553	  return -1;
554	}
555    }
556
557  return 0;
558}
559
560/* Deallocate a mutex.  */
561static inline int
562__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
563{
564  if (__gthread_active_p ())
565    {
566      int count;
567
568      /*
569       * Posix Threads specifically require that the thread be unlocked
570       * for __gthrw_(pthread_mutex_destroy) to work.
571       */
572
573      do
574	{
575	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
576	  if (count < 0)
577	    return -1;
578	}
579      while (count);
580
581      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
582	return -1;
583
584      objc_free (mutex->backend);
585      mutex->backend = NULL;
586    }
587  return 0;
588}
589
590/* Grab a lock on a mutex.  */
591static inline int
592__gthread_objc_mutex_lock (objc_mutex_t mutex)
593{
594  if (__gthread_active_p ()
595      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
596    {
597      return -1;
598    }
599
600  return 0;
601}
602
603/* Try to grab a lock on a mutex.  */
604static inline int
605__gthread_objc_mutex_trylock (objc_mutex_t mutex)
606{
607  if (__gthread_active_p ()
608      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
609    {
610      return -1;
611    }
612
613  return 0;
614}
615
616/* Unlock the mutex */
617static inline int
618__gthread_objc_mutex_unlock (objc_mutex_t mutex)
619{
620  if (__gthread_active_p ()
621      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
622    {
623      return -1;
624    }
625
626  return 0;
627}
628
629/* Backend condition mutex functions */
630
631/* Allocate a condition.  */
632static inline int
633__gthread_objc_condition_allocate (objc_condition_t condition)
634{
635  if (__gthread_active_p ())
636    {
637      condition->backend = objc_malloc (sizeof (pthread_cond_t));
638
639      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
640	{
641	  objc_free (condition->backend);
642	  condition->backend = NULL;
643	  return -1;
644	}
645    }
646
647  return 0;
648}
649
650/* Deallocate a condition.  */
651static inline int
652__gthread_objc_condition_deallocate (objc_condition_t condition)
653{
654  if (__gthread_active_p ())
655    {
656      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
657	return -1;
658
659      objc_free (condition->backend);
660      condition->backend = NULL;
661    }
662  return 0;
663}
664
665/* Wait on the condition */
666static inline int
667__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
668{
669  if (__gthread_active_p ())
670    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
671			      (pthread_mutex_t *) mutex->backend);
672  else
673    return 0;
674}
675
676/* Wake up all threads waiting on this condition.  */
677static inline int
678__gthread_objc_condition_broadcast (objc_condition_t condition)
679{
680  if (__gthread_active_p ())
681    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
682  else
683    return 0;
684}
685
686/* Wake up one thread waiting on this condition.  */
687static inline int
688__gthread_objc_condition_signal (objc_condition_t condition)
689{
690  if (__gthread_active_p ())
691    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
692  else
693    return 0;
694}
695
696#else /* _LIBOBJC */
697
698static inline int
699__gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
700		  void *__args)
701{
702  return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
703}
704
705static inline int
706__gthread_join (__gthread_t __threadid, void **__value_ptr)
707{
708  return __gthrw_(pthread_join) (__threadid, __value_ptr);
709}
710
711static inline int
712__gthread_detach (__gthread_t __threadid)
713{
714  return __gthrw_(pthread_detach) (__threadid);
715}
716
717static inline int
718__gthread_equal (__gthread_t __t1, __gthread_t __t2)
719{
720  return __gthrw_(pthread_equal) (__t1, __t2);
721}
722
723static inline __gthread_t
724__gthread_self (void)
725{
726  return __gthrw_(pthread_self) ();
727}
728
729static inline int
730__gthread_yield (void)
731{
732  return __gthrw_(sched_yield) ();
733}
734
735static inline int
736__gthread_once (__gthread_once_t *__once, void (*__func) (void))
737{
738  if (__gthread_active_p ())
739    return __gthrw_(pthread_once) (__once, __func);
740  else
741    return -1;
742}
743
744static inline int
745__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
746{
747  return __gthrw_(pthread_key_create) (__key, __dtor);
748}
749
750static inline int
751__gthread_key_delete (__gthread_key_t __key)
752{
753  return __gthrw_(pthread_key_delete) (__key);
754}
755
756static inline void *
757__gthread_getspecific (__gthread_key_t __key)
758{
759  return __gthrw_(pthread_getspecific) (__key);
760}
761
762static inline int
763__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
764{
765  return __gthrw_(pthread_setspecific) (__key, __ptr);
766}
767
768static inline int
769__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
770{
771  if (__gthread_active_p ())
772    return __gthrw_(pthread_mutex_destroy) (__mutex);
773  else
774    return 0;
775}
776
777static inline int
778__gthread_mutex_lock (__gthread_mutex_t *__mutex)
779{
780  if (__gthread_active_p ())
781    return __gthrw_(pthread_mutex_lock) (__mutex);
782  else
783    return 0;
784}
785
786static inline int
787__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
788{
789  if (__gthread_active_p ())
790    return __gthrw_(pthread_mutex_trylock) (__mutex);
791  else
792    return 0;
793}
794
795#ifdef _POSIX_TIMEOUTS
796#if _POSIX_TIMEOUTS >= 0
797static inline int
798__gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
799			   const __gthread_time_t *__abs_timeout)
800{
801  if (__gthread_active_p ())
802    return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout);
803  else
804    return 0;
805}
806#endif
807#endif
808
809static inline int
810__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
811{
812  if (__gthread_active_p ())
813    return __gthrw_(pthread_mutex_unlock) (__mutex);
814  else
815    return 0;
816}
817
818#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
819static inline int
820__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
821{
822  if (__gthread_active_p ())
823    {
824      pthread_mutexattr_t __attr;
825      int __r;
826
827      __r = __gthrw_(pthread_mutexattr_init) (&__attr);
828      if (!__r)
829	__r = __gthrw_(pthread_mutexattr_settype) (&__attr,
830						   PTHREAD_MUTEX_RECURSIVE);
831      if (!__r)
832	__r = __gthrw_(pthread_mutex_init) (__mutex, &__attr);
833      if (!__r)
834	__r = __gthrw_(pthread_mutexattr_destroy) (&__attr);
835      return __r;
836    }
837  return 0;
838}
839#endif
840
841static inline int
842__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
843{
844  return __gthread_mutex_lock (__mutex);
845}
846
847static inline int
848__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
849{
850  return __gthread_mutex_trylock (__mutex);
851}
852
853#ifdef _POSIX_TIMEOUTS
854#if _POSIX_TIMEOUTS >= 0
855static inline int
856__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
857				     const __gthread_time_t *__abs_timeout)
858{
859  return __gthread_mutex_timedlock (__mutex, __abs_timeout);
860}
861#endif
862#endif
863
864static inline int
865__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
866{
867  return __gthread_mutex_unlock (__mutex);
868}
869
870static inline int
871__gthread_cond_broadcast (__gthread_cond_t *__cond)
872{
873  return __gthrw_(pthread_cond_broadcast) (__cond);
874}
875
876static inline int
877__gthread_cond_signal (__gthread_cond_t *__cond)
878{
879  return __gthrw_(pthread_cond_signal) (__cond);
880}
881
882static inline int
883__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
884{
885  return __gthrw_(pthread_cond_wait) (__cond, __mutex);
886}
887
888static inline int
889__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
890			  const __gthread_time_t *__abs_timeout)
891{
892  return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
893}
894
895static inline int
896__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
897			       __gthread_recursive_mutex_t *__mutex)
898{
899  return __gthread_cond_wait (__cond, __mutex);
900}
901
902static inline int
903__gthread_cond_timedwait_recursive (__gthread_cond_t *__cond,
904				    __gthread_recursive_mutex_t *__mutex,
905				    const __gthread_time_t *__abs_timeout)
906{
907  return __gthread_cond_timedwait (__cond, __mutex, __abs_timeout);
908}
909
910static inline int
911__gthread_cond_destroy (__gthread_cond_t* __cond)
912{
913  return __gthrw_(pthread_cond_destroy) (__cond);
914}
915
916#endif /* _LIBOBJC */
917
918#endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */
919