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