gthr-posix.h

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