Home | History | Annotate | Download | only in bits
      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 
      6 This file is part of GCC.
      7 
      8 GCC is free software; you can redistribute it and/or modify it under
      9 the terms of the GNU General Public License as published by the Free
     10 Software Foundation; either version 3, or (at your option) any later
     11 version.
     12 
     13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16 for more details.
     17 
     18 Under Section 7 of GPL version 3, you are granted additional
     19 permissions described in the GCC Runtime Library Exception, version
     20 3.1, as published by the Free Software Foundation.
     21 
     22 You should have received a copy of the GNU General Public License and
     23 a copy of the GCC Runtime Library Exception along with this program;
     24 see 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 
     57 typedef pthread_t __gthread_t;
     58 typedef pthread_key_t __gthread_key_t;
     59 typedef pthread_once_t __gthread_once_t;
     60 typedef pthread_mutex_t __gthread_mutex_t;
     61 typedef pthread_mutex_t __gthread_recursive_mutex_t;
     62 typedef pthread_cond_t __gthread_cond_t;
     63 typedef 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 
    209 static volatile int __gthread_active = -1;
    210 
    211 static void
    212 __gthread_trigger (void)
    213 {
    214   __gthread_active = 1;
    215 }
    216 
    217 static 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 
    252 static 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 
    287 static volatile int __gthread_active = -1;
    288 
    289 static void *
    290 __gthread_start (void *__arg __attribute__((unused)))
    291 {
    292   return NULL;
    293 }
    294 
    295 static void __gthread_active_init (void) __attribute__((noinline));
    296 static 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 
    319 static 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 
    339 static 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 */
    359 static pthread_key_t _objc_thread_storage;
    360 static pthread_attr_t _objc_thread_attribs;
    361 
    362 /* Thread local storage for a single thread */
    363 static void *thread_local_storage = NULL;
    364 
    365 /* Backend initialization functions */
    366 
    367 /* Initialize the threads subsystem.  */
    368 static 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.  */
    390 static 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.  */
    404 static 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.  */
    422 static 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.  */
    465 static 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.  */
    487 static 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.  */
    495 static 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.  */
    507 static 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.  */
    517 static 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.  */
    530 static 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.  */
    542 static 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.  */
    561 static 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.  */
    591 static 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.  */
    604 static 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 */
    617 static 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.  */
    632 static 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.  */
    651 static 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 */
    666 static 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.  */
    677 static 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.  */
    687 static 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 
    698 static 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 
    705 static inline int
    706 __gthread_join (__gthread_t __threadid, void **__value_ptr)
    707 {
    708   return __gthrw_(pthread_join) (__threadid, __value_ptr);
    709 }
    710 
    711 static inline int
    712 __gthread_detach (__gthread_t __threadid)
    713 {
    714   return __gthrw_(pthread_detach) (__threadid);
    715 }
    716 
    717 static inline int
    718 __gthread_equal (__gthread_t __t1, __gthread_t __t2)
    719 {
    720   return __gthrw_(pthread_equal) (__t1, __t2);
    721 }
    722 
    723 static inline __gthread_t
    724 __gthread_self (void)
    725 {
    726   return __gthrw_(pthread_self) ();
    727 }
    728 
    729 static inline int
    730 __gthread_yield (void)
    731 {
    732   return __gthrw_(sched_yield) ();
    733 }
    734 
    735 static 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 
    744 static inline int
    745 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
    746 {
    747   return __gthrw_(pthread_key_create) (__key, __dtor);
    748 }
    749 
    750 static inline int
    751 __gthread_key_delete (__gthread_key_t __key)
    752 {
    753   return __gthrw_(pthread_key_delete) (__key);
    754 }
    755 
    756 static inline void *
    757 __gthread_getspecific (__gthread_key_t __key)
    758 {
    759   return __gthrw_(pthread_getspecific) (__key);
    760 }
    761 
    762 static inline int
    763 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
    764 {
    765   return __gthrw_(pthread_setspecific) (__key, __ptr);
    766 }
    767 
    768 static 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 
    777 static 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 
    786 static 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
    797 static 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 
    809 static 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
    819 static 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 
    841 static inline int
    842 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
    843 {
    844   return __gthread_mutex_lock (__mutex);
    845 }
    846 
    847 static 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
    855 static 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 
    864 static inline int
    865 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
    866 {
    867   return __gthread_mutex_unlock (__mutex);
    868 }
    869 
    870 static inline int
    871 __gthread_cond_broadcast (__gthread_cond_t *__cond)
    872 {
    873   return __gthrw_(pthread_cond_broadcast) (__cond);
    874 }
    875 
    876 static inline int
    877 __gthread_cond_signal (__gthread_cond_t *__cond)
    878 {
    879   return __gthrw_(pthread_cond_signal) (__cond);
    880 }
    881 
    882 static 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 
    888 static 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 
    895 static 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 
    902 static 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 
    910 static 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