libstdc++
gthr-posix.h
00001 /* Threads compatibility routines for libgcc2 and libobjc.  */
00002 /* Compile this one with gcc.  */
00003 /* Copyright (C) 1997-2013 Free Software Foundation, Inc.
00004 
00005 This file is part of GCC.
00006 
00007 GCC is free software; you can redistribute it and/or modify it under
00008 the terms of the GNU General Public License as published by the Free
00009 Software Foundation; either version 3, or (at your option) any later
00010 version.
00011 
00012 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
00013 WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 Under Section 7 of GPL version 3, you are granted additional
00018 permissions described in the GCC Runtime Library Exception, version
00019 3.1, as published by the Free Software Foundation.
00020 
00021 You should have received a copy of the GNU General Public License and
00022 a copy of the GCC Runtime Library Exception along with this program;
00023 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00024 <http://www.gnu.org/licenses/>.  */
00025 
00026 #ifndef _GLIBCXX_GCC_GTHR_POSIX_H
00027 #define _GLIBCXX_GCC_GTHR_POSIX_H
00028 
00029 /* POSIX threads specific definitions.
00030    Easy, since the interface is just one-to-one mapping.  */
00031 
00032 #define __GTHREADS 1
00033 #define __GTHREADS_CXX0X 1
00034 
00035 #include <pthread.h>
00036 
00037 #if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \
00038      || !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK))
00039 # include <unistd.h>
00040 # if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 0
00041 #  define _GTHREAD_USE_MUTEX_TIMEDLOCK 1
00042 # else
00043 #  define _GTHREAD_USE_MUTEX_TIMEDLOCK 0
00044 # endif
00045 #endif
00046 
00047 typedef pthread_t __gthread_t;
00048 typedef pthread_key_t __gthread_key_t;
00049 typedef pthread_once_t __gthread_once_t;
00050 typedef pthread_mutex_t __gthread_mutex_t;
00051 typedef pthread_mutex_t __gthread_recursive_mutex_t;
00052 typedef pthread_cond_t __gthread_cond_t;
00053 typedef struct timespec __gthread_time_t;
00054 
00055 /* POSIX like conditional variables are supported.  Please look at comments
00056    in gthr.h for details. */
00057 #define __GTHREAD_HAS_COND  1
00058 
00059 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
00060 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
00061 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
00062 #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
00063 #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
00064 #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
00065 #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00066 #else
00067 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
00068 #endif
00069 #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
00070 #define __GTHREAD_TIME_INIT {0,0}
00071 
00072 #ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
00073 # undef __GTHREAD_MUTEX_INIT
00074 #endif
00075 #ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC
00076 # undef __GTHREAD_RECURSIVE_MUTEX_INIT
00077 # undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
00078 # define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
00079 #endif
00080 #ifdef _GTHREAD_USE_COND_INIT_FUNC
00081 # undef __GTHREAD_COND_INIT
00082 # define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
00083 #endif
00084 
00085 #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
00086 # ifndef __gthrw_pragma
00087 #  define __gthrw_pragma(pragma)
00088 # endif
00089 # define __gthrw2(name,name2,type) \
00090   static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
00091   __gthrw_pragma(weak type)
00092 # define __gthrw_(name) __gthrw_ ## name
00093 #else
00094 # define __gthrw2(name,name2,type)
00095 # define __gthrw_(name) name
00096 #endif
00097 
00098 /* Typically, __gthrw_foo is a weak reference to symbol foo.  */
00099 #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
00100 
00101 __gthrw(pthread_once)
00102 __gthrw(pthread_getspecific)
00103 __gthrw(pthread_setspecific)
00104 
00105 __gthrw(pthread_create)
00106 __gthrw(pthread_join)
00107 __gthrw(pthread_equal)
00108 __gthrw(pthread_self)
00109 __gthrw(pthread_detach)
00110 #ifndef __BIONIC__
00111 __gthrw(pthread_cancel)
00112 #endif
00113 __gthrw(sched_yield)
00114 
00115 __gthrw(pthread_mutex_lock)
00116 __gthrw(pthread_mutex_trylock)
00117 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
00118 __gthrw(pthread_mutex_timedlock)
00119 #endif
00120 __gthrw(pthread_mutex_unlock)
00121 __gthrw(pthread_mutex_init)
00122 __gthrw(pthread_mutex_destroy)
00123 
00124 __gthrw(pthread_cond_init)
00125 __gthrw(pthread_cond_broadcast)
00126 __gthrw(pthread_cond_signal)
00127 __gthrw(pthread_cond_wait)
00128 __gthrw(pthread_cond_timedwait)
00129 __gthrw(pthread_cond_destroy)
00130 
00131 __gthrw(pthread_key_create)
00132 __gthrw(pthread_key_delete)
00133 __gthrw(pthread_mutexattr_init)
00134 __gthrw(pthread_mutexattr_settype)
00135 __gthrw(pthread_mutexattr_destroy)
00136 
00137 
00138 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
00139 /* Objective-C.  */
00140 __gthrw(pthread_exit)
00141 #ifdef _POSIX_PRIORITY_SCHEDULING
00142 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00143 __gthrw(sched_get_priority_max)
00144 __gthrw(sched_get_priority_min)
00145 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00146 #endif /* _POSIX_PRIORITY_SCHEDULING */
00147 __gthrw(pthread_attr_destroy)
00148 __gthrw(pthread_attr_init)
00149 __gthrw(pthread_attr_setdetachstate)
00150 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00151 __gthrw(pthread_getschedparam)
00152 __gthrw(pthread_setschedparam)
00153 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00154 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
00155 
00156 #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
00157 
00158 /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
00159    -pthreads is not specified.  The functions are dummies and most return an
00160    error value.  However pthread_once returns 0 without invoking the routine
00161    it is passed so we cannot pretend that the interface is active if -pthreads
00162    is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
00163    we need to play the usual game with weak symbols.  On Solaris 10 and up, a
00164    working interface is always exposed.  On FreeBSD 6 and later, libc also
00165    exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
00166    to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
00167    which means the alternate __gthread_active_p below cannot be used there.  */
00168 
00169 #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
00170 
00171 static volatile int __gthread_active = -1;
00172 
00173 static void
00174 __gthread_trigger (void)
00175 {
00176   __gthread_active = 1;
00177 }
00178 
00179 static inline int
00180 __gthread_active_p (void)
00181 {
00182   static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
00183   static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
00184 
00185   /* Avoid reading __gthread_active twice on the main code path.  */
00186   int __gthread_active_latest_value = __gthread_active;
00187 
00188   /* This test is not protected to avoid taking a lock on the main code
00189      path so every update of __gthread_active in a threaded program must
00190      be atomic with regard to the result of the test.  */
00191   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
00192     {
00193       if (__gthrw_(pthread_once))
00194     {
00195       /* If this really is a threaded program, then we must ensure that
00196          __gthread_active has been set to 1 before exiting this block.  */
00197       __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
00198       __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
00199       __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
00200     }
00201 
00202       /* Make sure we'll never enter this block again.  */
00203       if (__gthread_active < 0)
00204     __gthread_active = 0;
00205 
00206       __gthread_active_latest_value = __gthread_active;
00207     }
00208 
00209   return __gthread_active_latest_value != 0;
00210 }
00211 
00212 #else /* neither FreeBSD nor Solaris */
00213 
00214 /* For a program to be multi-threaded the only thing that it certainly must
00215    be using is pthread_create.  However, there may be other libraries that
00216    intercept pthread_create with their own definitions to wrap pthreads
00217    functionality for some purpose.  In those cases, pthread_create being
00218    defined might not necessarily mean that libpthread is actually linked
00219    in.
00220 
00221    For the GNU C library, we can use a known internal name.  This is always
00222    available in the ABI, but no other library would define it.  That is
00223    ideal, since any public pthread function might be intercepted just as
00224    pthread_create might be.  __pthread_key_create is an "internal"
00225    implementation symbol, but it is part of the public exported ABI.  Also,
00226    it's among the symbols that the static libpthread.a always links in
00227    whenever pthread_create is used, so there is no danger of a false
00228    negative result in any statically-linked, multi-threaded program.
00229 
00230    For others, we choose pthread_cancel as a function that seems unlikely
00231    to be redefined by an interceptor library.  The bionic (Android) C
00232    library does not provide pthread_cancel, so we do use pthread_create
00233    there (and interceptor libraries lose).  */
00234 
00235 #ifdef __GLIBC__
00236 __gthrw2(__gthrw_(__pthread_key_create),
00237      __pthread_key_create,
00238      pthread_key_create)
00239 # define GTHR_ACTIVE_PROXY  __gthrw_(__pthread_key_create)
00240 #elif defined (__BIONIC__)
00241 # define GTHR_ACTIVE_PROXY  __gthrw_(pthread_create)
00242 #else
00243 # define GTHR_ACTIVE_PROXY  __gthrw_(pthread_cancel)
00244 #endif
00245 
00246 static inline int
00247 __gthread_active_p (void)
00248 {
00249   static void *const __gthread_active_ptr
00250     = __extension__ (void *) &GTHR_ACTIVE_PROXY;
00251   return __gthread_active_ptr != 0;
00252 }
00253 
00254 #endif /* FreeBSD or Solaris */
00255 
00256 #else /* not __GXX_WEAK__ */
00257 
00258 /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
00259    calls in shared flavors of the HP-UX C library.  Most of the stubs
00260    have no functionality.  The details are described in the "libc cumulative
00261    patch" for each subversion of HP-UX 11.  There are two special interfaces
00262    provided for checking whether an application is linked to a shared pthread
00263    library or not.  However, these interfaces aren't available in early
00264    libpthread libraries.  We also need a test that works for archive
00265    libraries.  We can't use pthread_once as some libc versions call the
00266    init function.  We also can't use pthread_create or pthread_attr_init
00267    as these create a thread and thereby prevent changing the default stack
00268    size.  The function pthread_default_stacksize_np is available in both
00269    the archive and shared versions of libpthread.   It can be used to
00270    determine the default pthread stack size.  There is a stub in some
00271    shared libc versions which returns a zero size if pthreads are not
00272    active.  We provide an equivalent stub to handle cases where libc
00273    doesn't provide one.  */
00274 
00275 #if defined(__hppa__) && defined(__hpux__)
00276 
00277 static volatile int __gthread_active = -1;
00278 
00279 static inline int
00280 __gthread_active_p (void)
00281 {
00282   /* Avoid reading __gthread_active twice on the main code path.  */
00283   int __gthread_active_latest_value = __gthread_active;
00284   size_t __s;
00285 
00286   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
00287     {
00288       pthread_default_stacksize_np (0, &__s);
00289       __gthread_active = __s ? 1 : 0;
00290       __gthread_active_latest_value = __gthread_active;
00291     }
00292 
00293   return __gthread_active_latest_value != 0;
00294 }
00295 
00296 #else /* not hppa-hpux */
00297 
00298 static inline int
00299 __gthread_active_p (void)
00300 {
00301   return 1;
00302 }
00303 
00304 #endif /* hppa-hpux */
00305 
00306 #endif /* __GXX_WEAK__ */
00307 
00308 #ifdef _LIBOBJC
00309 
00310 /* This is the config.h file in libobjc/ */
00311 #include <config.h>
00312 
00313 #ifdef HAVE_SCHED_H
00314 # include <sched.h>
00315 #endif
00316 
00317 /* Key structure for maintaining thread specific storage */
00318 static pthread_key_t _objc_thread_storage;
00319 static pthread_attr_t _objc_thread_attribs;
00320 
00321 /* Thread local storage for a single thread */
00322 static void *thread_local_storage = NULL;
00323 
00324 /* Backend initialization functions */
00325 
00326 /* Initialize the threads subsystem.  */
00327 static inline int
00328 __gthread_objc_init_thread_system (void)
00329 {
00330   if (__gthread_active_p ())
00331     {
00332       /* Initialize the thread storage key.  */
00333       if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
00334     {
00335       /* The normal default detach state for threads is
00336        * PTHREAD_CREATE_JOINABLE which causes threads to not die
00337        * when you think they should.  */
00338       if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
00339           && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
00340                           PTHREAD_CREATE_DETACHED) == 0)
00341         return 0;
00342     }
00343     }
00344 
00345   return -1;
00346 }
00347 
00348 /* Close the threads subsystem.  */
00349 static inline int
00350 __gthread_objc_close_thread_system (void)
00351 {
00352   if (__gthread_active_p ()
00353       && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
00354       && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
00355     return 0;
00356 
00357   return -1;
00358 }
00359 
00360 /* Backend thread functions */
00361 
00362 /* Create a new thread of execution.  */
00363 static inline objc_thread_t
00364 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
00365 {
00366   objc_thread_t thread_id;
00367   pthread_t new_thread_handle;
00368 
00369   if (!__gthread_active_p ())
00370     return NULL;
00371 
00372   if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs,
00373                   (void *) func, arg)))
00374     thread_id = (objc_thread_t) new_thread_handle;
00375   else
00376     thread_id = NULL;
00377 
00378   return thread_id;
00379 }
00380 
00381 /* Set the current thread's priority.  */
00382 static inline int
00383 __gthread_objc_thread_set_priority (int priority)
00384 {
00385   if (!__gthread_active_p ())
00386     return -1;
00387   else
00388     {
00389 #ifdef _POSIX_PRIORITY_SCHEDULING
00390 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00391       pthread_t thread_id = __gthrw_(pthread_self) ();
00392       int policy;
00393       struct sched_param params;
00394       int priority_min, priority_max;
00395 
00396       if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
00397     {
00398       if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
00399         return -1;
00400 
00401       if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
00402         return -1;
00403 
00404       if (priority > priority_max)
00405         priority = priority_max;
00406       else if (priority < priority_min)
00407         priority = priority_min;
00408       params.sched_priority = priority;
00409 
00410       /*
00411        * The solaris 7 and several other man pages incorrectly state that
00412        * this should be a pointer to policy but pthread.h is universally
00413        * at odds with this.
00414        */
00415       if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
00416         return 0;
00417     }
00418 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00419 #endif /* _POSIX_PRIORITY_SCHEDULING */
00420       return -1;
00421     }
00422 }
00423 
00424 /* Return the current thread's priority.  */
00425 static inline int
00426 __gthread_objc_thread_get_priority (void)
00427 {
00428 #ifdef _POSIX_PRIORITY_SCHEDULING
00429 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00430   if (__gthread_active_p ())
00431     {
00432       int policy;
00433       struct sched_param params;
00434 
00435       if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
00436     return params.sched_priority;
00437       else
00438     return -1;
00439     }
00440   else
00441 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00442 #endif /* _POSIX_PRIORITY_SCHEDULING */
00443     return OBJC_THREAD_INTERACTIVE_PRIORITY;
00444 }
00445 
00446 /* Yield our process time to another thread.  */
00447 static inline void
00448 __gthread_objc_thread_yield (void)
00449 {
00450   if (__gthread_active_p ())
00451     __gthrw_(sched_yield) ();
00452 }
00453 
00454 /* Terminate the current thread.  */
00455 static inline int
00456 __gthread_objc_thread_exit (void)
00457 {
00458   if (__gthread_active_p ())
00459     /* exit the thread */
00460     __gthrw_(pthread_exit) (&__objc_thread_exit_status);
00461 
00462   /* Failed if we reached here */
00463   return -1;
00464 }
00465 
00466 /* Returns an integer value which uniquely describes a thread.  */
00467 static inline objc_thread_t
00468 __gthread_objc_thread_id (void)
00469 {
00470   if (__gthread_active_p ())
00471     return (objc_thread_t) __gthrw_(pthread_self) ();
00472   else
00473     return (objc_thread_t) 1;
00474 }
00475 
00476 /* Sets the thread's local storage pointer.  */
00477 static inline int
00478 __gthread_objc_thread_set_data (void *value)
00479 {
00480   if (__gthread_active_p ())
00481     return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
00482   else
00483     {
00484       thread_local_storage = value;
00485       return 0;
00486     }
00487 }
00488 
00489 /* Returns the thread's local storage pointer.  */
00490 static inline void *
00491 __gthread_objc_thread_get_data (void)
00492 {
00493   if (__gthread_active_p ())
00494     return __gthrw_(pthread_getspecific) (_objc_thread_storage);
00495   else
00496     return thread_local_storage;
00497 }
00498 
00499 /* Backend mutex functions */
00500 
00501 /* Allocate a mutex.  */
00502 static inline int
00503 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
00504 {
00505   if (__gthread_active_p ())
00506     {
00507       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
00508 
00509       if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
00510     {
00511       objc_free (mutex->backend);
00512       mutex->backend = NULL;
00513       return -1;
00514     }
00515     }
00516 
00517   return 0;
00518 }
00519 
00520 /* Deallocate a mutex.  */
00521 static inline int
00522 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
00523 {
00524   if (__gthread_active_p ())
00525     {
00526       int count;
00527 
00528       /*
00529        * Posix Threads specifically require that the thread be unlocked
00530        * for __gthrw_(pthread_mutex_destroy) to work.
00531        */
00532 
00533       do
00534     {
00535       count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
00536       if (count < 0)
00537         return -1;
00538     }
00539       while (count);
00540 
00541       if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
00542     return -1;
00543 
00544       objc_free (mutex->backend);
00545       mutex->backend = NULL;
00546     }
00547   return 0;
00548 }
00549 
00550 /* Grab a lock on a mutex.  */
00551 static inline int
00552 __gthread_objc_mutex_lock (objc_mutex_t mutex)
00553 {
00554   if (__gthread_active_p ()
00555       && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
00556     {
00557       return -1;
00558     }
00559 
00560   return 0;
00561 }
00562 
00563 /* Try to grab a lock on a mutex.  */
00564 static inline int
00565 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
00566 {
00567   if (__gthread_active_p ()
00568       && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
00569     {
00570       return -1;
00571     }
00572 
00573   return 0;
00574 }
00575 
00576 /* Unlock the mutex */
00577 static inline int
00578 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
00579 {
00580   if (__gthread_active_p ()
00581       && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
00582     {
00583       return -1;
00584     }
00585 
00586   return 0;
00587 }
00588 
00589 /* Backend condition mutex functions */
00590 
00591 /* Allocate a condition.  */
00592 static inline int
00593 __gthread_objc_condition_allocate (objc_condition_t condition)
00594 {
00595   if (__gthread_active_p ())
00596     {
00597       condition->backend = objc_malloc (sizeof (pthread_cond_t));
00598 
00599       if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
00600     {
00601       objc_free (condition->backend);
00602       condition->backend = NULL;
00603       return -1;
00604     }
00605     }
00606 
00607   return 0;
00608 }
00609 
00610 /* Deallocate a condition.  */
00611 static inline int
00612 __gthread_objc_condition_deallocate (objc_condition_t condition)
00613 {
00614   if (__gthread_active_p ())
00615     {
00616       if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
00617     return -1;
00618 
00619       objc_free (condition->backend);
00620       condition->backend = NULL;
00621     }
00622   return 0;
00623 }
00624 
00625 /* Wait on the condition */
00626 static inline int
00627 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
00628 {
00629   if (__gthread_active_p ())
00630     return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
00631                   (pthread_mutex_t *) mutex->backend);
00632   else
00633     return 0;
00634 }
00635 
00636 /* Wake up all threads waiting on this condition.  */
00637 static inline int
00638 __gthread_objc_condition_broadcast (objc_condition_t condition)
00639 {
00640   if (__gthread_active_p ())
00641     return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
00642   else
00643     return 0;
00644 }
00645 
00646 /* Wake up one thread waiting on this condition.  */
00647 static inline int
00648 __gthread_objc_condition_signal (objc_condition_t condition)
00649 {
00650   if (__gthread_active_p ())
00651     return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
00652   else
00653     return 0;
00654 }
00655 
00656 #else /* _LIBOBJC */
00657 
00658 static inline int
00659 __gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
00660           void *__args)
00661 {
00662   return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
00663 }
00664 
00665 static inline int
00666 __gthread_join (__gthread_t __threadid, void **__value_ptr)
00667 {
00668   return __gthrw_(pthread_join) (__threadid, __value_ptr);
00669 }
00670 
00671 static inline int
00672 __gthread_detach (__gthread_t __threadid)
00673 {
00674   return __gthrw_(pthread_detach) (__threadid);
00675 }
00676 
00677 static inline int
00678 __gthread_equal (__gthread_t __t1, __gthread_t __t2)
00679 {
00680   return __gthrw_(pthread_equal) (__t1, __t2);
00681 }
00682 
00683 static inline __gthread_t
00684 __gthread_self (void)
00685 {
00686   return __gthrw_(pthread_self) ();
00687 }
00688 
00689 static inline int
00690 __gthread_yield (void)
00691 {
00692   return __gthrw_(sched_yield) ();
00693 }
00694 
00695 static inline int
00696 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
00697 {
00698   if (__gthread_active_p ())
00699     return __gthrw_(pthread_once) (__once, __func);
00700   else
00701     return -1;
00702 }
00703 
00704 static inline int
00705 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
00706 {
00707   return __gthrw_(pthread_key_create) (__key, __dtor);
00708 }
00709 
00710 static inline int
00711 __gthread_key_delete (__gthread_key_t __key)
00712 {
00713   return __gthrw_(pthread_key_delete) (__key);
00714 }
00715 
00716 static inline void *
00717 __gthread_getspecific (__gthread_key_t __key)
00718 {
00719   return __gthrw_(pthread_getspecific) (__key);
00720 }
00721 
00722 static inline int
00723 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
00724 {
00725   return __gthrw_(pthread_setspecific) (__key, __ptr);
00726 }
00727 
00728 static inline void
00729 __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
00730 {
00731   if (__gthread_active_p ())
00732     __gthrw_(pthread_mutex_init) (__mutex, NULL);
00733 }
00734 
00735 static inline int
00736 __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
00737 {
00738   if (__gthread_active_p ())
00739     return __gthrw_(pthread_mutex_destroy) (__mutex);
00740   else
00741     return 0;
00742 }
00743 
00744 static inline int
00745 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
00746 {
00747   if (__gthread_active_p ())
00748     return __gthrw_(pthread_mutex_lock) (__mutex);
00749   else
00750     return 0;
00751 }
00752 
00753 static inline int
00754 __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
00755 {
00756   if (__gthread_active_p ())
00757     return __gthrw_(pthread_mutex_trylock) (__mutex);
00758   else
00759     return 0;
00760 }
00761 
00762 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
00763 static inline int
00764 __gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
00765                const __gthread_time_t *__abs_timeout)
00766 {
00767   if (__gthread_active_p ())
00768     return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout);
00769   else
00770     return 0;
00771 }
00772 #endif
00773 
00774 static inline int
00775 __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
00776 {
00777   if (__gthread_active_p ())
00778     return __gthrw_(pthread_mutex_unlock) (__mutex);
00779   else
00780     return 0;
00781 }
00782 
00783 #if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \
00784   || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
00785 static inline int
00786 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
00787 {
00788   if (__gthread_active_p ())
00789     {
00790       pthread_mutexattr_t __attr;
00791       int __r;
00792 
00793       __r = __gthrw_(pthread_mutexattr_init) (&__attr);
00794       if (!__r)
00795     __r = __gthrw_(pthread_mutexattr_settype) (&__attr,
00796                            PTHREAD_MUTEX_RECURSIVE);
00797       if (!__r)
00798     __r = __gthrw_(pthread_mutex_init) (__mutex, &__attr);
00799       if (!__r)
00800     __r = __gthrw_(pthread_mutexattr_destroy) (&__attr);
00801       return __r;
00802     }
00803   return 0;
00804 }
00805 #endif
00806 
00807 static inline int
00808 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
00809 {
00810   return __gthread_mutex_lock (__mutex);
00811 }
00812 
00813 static inline int
00814 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
00815 {
00816   return __gthread_mutex_trylock (__mutex);
00817 }
00818 
00819 #if _GTHREAD_USE_MUTEX_TIMEDLOCK
00820 static inline int
00821 __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
00822                      const __gthread_time_t *__abs_timeout)
00823 {
00824   return __gthread_mutex_timedlock (__mutex, __abs_timeout);
00825 }
00826 #endif
00827 
00828 static inline int
00829 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
00830 {
00831   return __gthread_mutex_unlock (__mutex);
00832 }
00833 
00834 static inline int
00835 __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
00836 {
00837   return __gthread_mutex_destroy (__mutex);
00838 }
00839 
00840 #ifdef _GTHREAD_USE_COND_INIT_FUNC
00841 static inline void
00842 __gthread_cond_init_function (__gthread_cond_t *__cond)
00843 {
00844   if (__gthread_active_p ())
00845     __gthrw_(pthread_cond_init) (__cond, NULL);
00846 }
00847 #endif
00848 
00849 static inline int
00850 __gthread_cond_broadcast (__gthread_cond_t *__cond)
00851 {
00852   return __gthrw_(pthread_cond_broadcast) (__cond);
00853 }
00854 
00855 static inline int
00856 __gthread_cond_signal (__gthread_cond_t *__cond)
00857 {
00858   return __gthrw_(pthread_cond_signal) (__cond);
00859 }
00860 
00861 static inline int
00862 __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
00863 {
00864   return __gthrw_(pthread_cond_wait) (__cond, __mutex);
00865 }
00866 
00867 static inline int
00868 __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
00869               const __gthread_time_t *__abs_timeout)
00870 {
00871   return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
00872 }
00873 
00874 static inline int
00875 __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
00876                    __gthread_recursive_mutex_t *__mutex)
00877 {
00878   return __gthread_cond_wait (__cond, __mutex);
00879 }
00880 
00881 static inline int
00882 __gthread_cond_destroy (__gthread_cond_t* __cond)
00883 {
00884   return __gthrw_(pthread_cond_destroy) (__cond);
00885 }
00886 
00887 #endif /* _LIBOBJC */
00888 
00889 #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */