1  /* Threads compatibility routines for libgcc2 and libobjc.  */
       2  /* Compile this one with gcc.  */
       3  /* Copyright (C) 1997-2023 Free Software Foundation, Inc.
       4  
       5  This file is part of GCC.
       6  
       7  GCC is free software; you can redistribute it and/or modify it under
       8  the terms of the GNU General Public License as published by the Free
       9  Software Foundation; either version 3, or (at your option) any later
      10  version.
      11  
      12  GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13  WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15  for more details.
      16  
      17  Under Section 7 of GPL version 3, you are granted additional
      18  permissions described in the GCC Runtime Library Exception, version
      19  3.1, as published by the Free Software Foundation.
      20  
      21  You should have received a copy of the GNU General Public License and
      22  a copy of the GCC Runtime Library Exception along with this program;
      23  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      24  <http://www.gnu.org/licenses/>.  */
      25  
      26  #ifndef GCC_GTHR_POSIX_H
      27  #define GCC_GTHR_POSIX_H
      28  
      29  /* POSIX threads specific definitions.
      30     Easy, since the interface is just one-to-one mapping.  */
      31  
      32  #define __GTHREADS 1
      33  #define __GTHREADS_CXX0X 1
      34  
      35  #include <pthread.h>
      36  
      37  #if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \
      38       || !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK))
      39  # include <unistd.h>
      40  # if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 0
      41  #  define _GTHREAD_USE_MUTEX_TIMEDLOCK 1
      42  # else
      43  #  define _GTHREAD_USE_MUTEX_TIMEDLOCK 0
      44  # endif
      45  #endif
      46  
      47  typedef pthread_t __gthread_t;
      48  typedef pthread_key_t __gthread_key_t;
      49  typedef pthread_once_t __gthread_once_t;
      50  typedef pthread_mutex_t __gthread_mutex_t;
      51  typedef pthread_mutex_t __gthread_recursive_mutex_t;
      52  typedef pthread_cond_t __gthread_cond_t;
      53  typedef struct timespec __gthread_time_t;
      54  
      55  /* POSIX like conditional variables are supported.  Please look at comments
      56     in gthr.h for details. */
      57  #define __GTHREAD_HAS_COND	1
      58  
      59  #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
      60  #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
      61  #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
      62  #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
      63  #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
      64  #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
      65  #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
      66  #else
      67  #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
      68  #endif
      69  #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
      70  #define __GTHREAD_TIME_INIT {0,0}
      71  
      72  #ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
      73  # undef __GTHREAD_MUTEX_INIT
      74  #endif
      75  #ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC
      76  # undef __GTHREAD_RECURSIVE_MUTEX_INIT
      77  # undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
      78  # define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
      79  #endif
      80  #ifdef _GTHREAD_USE_COND_INIT_FUNC
      81  # undef __GTHREAD_COND_INIT
      82  # define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
      83  #endif
      84  
      85  #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
      86  # ifndef __gthrw_pragma
      87  #  define __gthrw_pragma(pragma)
      88  # endif
      89  # define __gthrw2(name,name2,type) \
      90    static __typeof(type) name \
      91      __attribute__ ((__weakref__(#name2), __copy__ (type))); \
      92    __gthrw_pragma(weak type)
      93  # define __gthrw_(name) __gthrw_ ## name
      94  #else
      95  # define __gthrw2(name,name2,type)
      96  # define __gthrw_(name) name
      97  #endif
      98  
      99  /* Typically, __gthrw_foo is a weak reference to symbol foo.  */
     100  #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
     101  
     102  __gthrw(pthread_once)
     103  __gthrw(pthread_getspecific)
     104  __gthrw(pthread_setspecific)
     105  
     106  __gthrw(pthread_create)
     107  __gthrw(pthread_join)
     108  __gthrw(pthread_equal)
     109  __gthrw(pthread_self)
     110  __gthrw(pthread_detach)
     111  #ifndef __BIONIC__
     112  __gthrw(pthread_cancel)
     113  #endif
     114  __gthrw(sched_yield)
     115  
     116  __gthrw(pthread_mutex_lock)
     117  __gthrw(pthread_mutex_trylock)
     118  #if _GTHREAD_USE_MUTEX_TIMEDLOCK
     119  __gthrw(pthread_mutex_timedlock)
     120  #endif
     121  __gthrw(pthread_mutex_unlock)
     122  __gthrw(pthread_mutex_init)
     123  __gthrw(pthread_mutex_destroy)
     124  
     125  __gthrw(pthread_cond_init)
     126  __gthrw(pthread_cond_broadcast)
     127  __gthrw(pthread_cond_signal)
     128  __gthrw(pthread_cond_wait)
     129  __gthrw(pthread_cond_timedwait)
     130  __gthrw(pthread_cond_destroy)
     131  
     132  __gthrw(pthread_key_create)
     133  __gthrw(pthread_key_delete)
     134  __gthrw(pthread_mutexattr_init)
     135  __gthrw(pthread_mutexattr_settype)
     136  __gthrw(pthread_mutexattr_destroy)
     137  
     138  
     139  #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
     140  /* Objective-C.  */
     141  __gthrw(pthread_exit)
     142  #ifdef _POSIX_PRIORITY_SCHEDULING
     143  #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
     144  __gthrw(sched_get_priority_max)
     145  __gthrw(sched_get_priority_min)
     146  #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
     147  #endif /* _POSIX_PRIORITY_SCHEDULING */
     148  __gthrw(pthread_attr_destroy)
     149  __gthrw(pthread_attr_init)
     150  __gthrw(pthread_attr_setdetachstate)
     151  #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
     152  __gthrw(pthread_getschedparam)
     153  __gthrw(pthread_setschedparam)
     154  #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
     155  #endif /* _LIBOBJC || _LIBOBJC_WEAK */
     156  
     157  #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
     158  
     159  /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
     160     -pthreads is not specified.  The functions are dummies and most return an
     161     error value.  However pthread_once returns 0 without invoking the routine
     162     it is passed so we cannot pretend that the interface is active if -pthreads
     163     is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
     164     we need to play the usual game with weak symbols.  On Solaris 10 and up, a
     165     working interface is always exposed.  On FreeBSD 6 and later, libc also
     166     exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
     167     to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
     168     which means the alternate __gthread_active_p below cannot be used there.  */
     169  
     170  #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
     171  
     172  static volatile int __gthread_active = -1;
     173  
     174  static void
     175  __gthread_trigger (void)
     176  {
     177    __gthread_active = 1;
     178  }
     179  
     180  static inline int
     181  __gthread_active_p (void)
     182  {
     183    static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
     184    static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
     185  
     186    /* Avoid reading __gthread_active twice on the main code path.  */
     187    int __gthread_active_latest_value = __gthread_active;
     188  
     189    /* This test is not protected to avoid taking a lock on the main code
     190       path so every update of __gthread_active in a threaded program must
     191       be atomic with regard to the result of the test.  */
     192    if (__builtin_expect (__gthread_active_latest_value < 0, 0))
     193      {
     194        if (__gthrw_(pthread_once))
     195  	{
     196  	  /* If this really is a threaded program, then we must ensure that
     197  	     __gthread_active has been set to 1 before exiting this block.  */
     198  	  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
     199  	  __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
     200  	  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
     201  	}
     202  
     203        /* Make sure we'll never enter this block again.  */
     204        if (__gthread_active < 0)
     205  	__gthread_active = 0;
     206  
     207        __gthread_active_latest_value = __gthread_active;
     208      }
     209  
     210    return __gthread_active_latest_value != 0;
     211  }
     212  
     213  #else /* neither FreeBSD nor Solaris */
     214  
     215  /* For a program to be multi-threaded the only thing that it certainly must
     216     be using is pthread_create.  However, there may be other libraries that
     217     intercept pthread_create with their own definitions to wrap pthreads
     218     functionality for some purpose.  In those cases, pthread_create being
     219     defined might not necessarily mean that libpthread is actually linked
     220     in.
     221  
     222     For the GNU C library, we can use a known internal name.  This is always
     223     available in the ABI, but no other library would define it.  That is
     224     ideal, since any public pthread function might be intercepted just as
     225     pthread_create might be.  __pthread_key_create is an "internal"
     226     implementation symbol, but it is part of the public exported ABI.  Also,
     227     it's among the symbols that the static libpthread.a always links in
     228     whenever pthread_create is used, so there is no danger of a false
     229     negative result in any statically-linked, multi-threaded program.
     230  
     231     For others, we choose pthread_cancel as a function that seems unlikely
     232     to be redefined by an interceptor library.  The bionic (Android) C
     233     library does not provide pthread_cancel, so we do use pthread_create
     234     there (and interceptor libraries lose).  */
     235  
     236  #ifdef __GLIBC__
     237  __gthrw2(__gthrw_(__pthread_key_create),
     238  	 __pthread_key_create,
     239  	 pthread_key_create)
     240  # define GTHR_ACTIVE_PROXY	__gthrw_(__pthread_key_create)
     241  #elif defined (__BIONIC__)
     242  # define GTHR_ACTIVE_PROXY	__gthrw_(pthread_create)
     243  #else
     244  # define GTHR_ACTIVE_PROXY	__gthrw_(pthread_cancel)
     245  #endif
     246  
     247  static inline int
     248  __gthread_active_p (void)
     249  {
     250    static void *const __gthread_active_ptr
     251      = __extension__ (void *) >HR_ACTIVE_PROXY;
     252    return __gthread_active_ptr != 0;
     253  }
     254  
     255  #endif /* FreeBSD or Solaris */
     256  
     257  #else /* not SUPPORTS_WEAK */
     258  
     259  /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
     260     calls in shared flavors of the HP-UX C library.  Most of the stubs
     261     have no functionality.  The details are described in the "libc cumulative
     262     patch" for each subversion of HP-UX 11.  There are two special interfaces
     263     provided for checking whether an application is linked to a shared pthread
     264     library or not.  However, these interfaces aren't available in early
     265     libpthread libraries.  We also need a test that works for archive
     266     libraries.  We can't use pthread_once as some libc versions call the
     267     init function.  We also can't use pthread_create or pthread_attr_init
     268     as these create a thread and thereby prevent changing the default stack
     269     size.  The function pthread_default_stacksize_np is available in both
     270     the archive and shared versions of libpthread.   It can be used to
     271     determine the default pthread stack size.  There is a stub in some
     272     shared libc versions which returns a zero size if pthreads are not
     273     active.  We provide an equivalent stub to handle cases where libc
     274     doesn't provide one.  */
     275  
     276  #if defined(__hppa__) && defined(__hpux__)
     277  
     278  static volatile int __gthread_active = -1;
     279  
     280  static inline int
     281  __gthread_active_p (void)
     282  {
     283    /* Avoid reading __gthread_active twice on the main code path.  */
     284    int __gthread_active_latest_value = __gthread_active;
     285    size_t __s;
     286  
     287    if (__builtin_expect (__gthread_active_latest_value < 0, 0))
     288      {
     289        pthread_default_stacksize_np (0, &__s);
     290        __gthread_active = __s ? 1 : 0;
     291        __gthread_active_latest_value = __gthread_active;
     292      }
     293  
     294    return __gthread_active_latest_value != 0;
     295  }
     296  
     297  #else /* not hppa-hpux */
     298  
     299  static inline int
     300  __gthread_active_p (void)
     301  {
     302    return 1;
     303  }
     304  
     305  #endif /* hppa-hpux */
     306  
     307  #endif /* SUPPORTS_WEAK */
     308  
     309  #ifdef _LIBOBJC
     310  
     311  /* This is the config.h file in libobjc/ */
     312  #include <config.h>
     313  
     314  #ifdef HAVE_SCHED_H
     315  # include <sched.h>
     316  #endif
     317  
     318  /* Key structure for maintaining thread specific storage */
     319  static pthread_key_t _objc_thread_storage;
     320  static pthread_attr_t _objc_thread_attribs;
     321  
     322  /* Thread local storage for a single thread */
     323  static void *thread_local_storage = NULL;
     324  
     325  /* Backend initialization functions */
     326  
     327  /* Initialize the threads subsystem.  */
     328  static inline int
     329  __gthread_objc_init_thread_system (void)
     330  {
     331    if (__gthread_active_p ())
     332      {
     333        /* Initialize the thread storage key.  */
     334        if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
     335  	{
     336  	  /* The normal default detach state for threads is
     337  	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
     338  	   * when you think they should.  */
     339  	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
     340  	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
     341  					      PTHREAD_CREATE_DETACHED) == 0)
     342  	    return 0;
     343  	}
     344      }
     345  
     346    return -1;
     347  }
     348  
     349  /* Close the threads subsystem.  */
     350  static inline int
     351  __gthread_objc_close_thread_system (void)
     352  {
     353    if (__gthread_active_p ()
     354        && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
     355        && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
     356      return 0;
     357  
     358    return -1;
     359  }
     360  
     361  /* Backend thread functions */
     362  
     363  /* Create a new thread of execution.  */
     364  static inline objc_thread_t
     365  __gthread_objc_thread_detach (void (*func)(void *), void *arg)
     366  {
     367    objc_thread_t thread_id;
     368    pthread_t new_thread_handle;
     369  
     370    if (!__gthread_active_p ())
     371      return NULL;
     372  
     373    if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs,
     374  				  (void *) func, arg)))
     375      thread_id = (objc_thread_t) new_thread_handle;
     376    else
     377      thread_id = NULL;
     378  
     379    return thread_id;
     380  }
     381  
     382  /* Set the current thread's priority.  */
     383  static inline int
     384  __gthread_objc_thread_set_priority (int priority)
     385  {
     386    if (!__gthread_active_p ())
     387      return -1;
     388    else
     389      {
     390  #ifdef _POSIX_PRIORITY_SCHEDULING
     391  #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
     392        pthread_t thread_id = __gthrw_(pthread_self) ();
     393        int policy;
     394        struct sched_param params;
     395        int priority_min, priority_max;
     396  
     397        if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0)
     398  	{
     399  	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
     400  	    return -1;
     401  
     402  	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
     403  	    return -1;
     404  
     405  	  if (priority > priority_max)
     406  	    priority = priority_max;
     407  	  else if (priority < priority_min)
     408  	    priority = priority_min;
     409  	  params.sched_priority = priority;
     410  
     411  	  /*
     412  	   * The solaris 7 and several other man pages incorrectly state that
     413  	   * this should be a pointer to policy but pthread.h is universally
     414  	   * at odds with this.
     415  	   */
     416  	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0)
     417  	    return 0;
     418  	}
     419  #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
     420  #endif /* _POSIX_PRIORITY_SCHEDULING */
     421        return -1;
     422      }
     423  }
     424  
     425  /* Return the current thread's priority.  */
     426  static inline int
     427  __gthread_objc_thread_get_priority (void)
     428  {
     429  #ifdef _POSIX_PRIORITY_SCHEDULING
     430  #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
     431    if (__gthread_active_p ())
     432      {
     433        int policy;
     434        struct sched_param params;
     435  
     436        if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0)
     437  	return params.sched_priority;
     438        else
     439  	return -1;
     440      }
     441    else
     442  #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
     443  #endif /* _POSIX_PRIORITY_SCHEDULING */
     444      return OBJC_THREAD_INTERACTIVE_PRIORITY;
     445  }
     446  
     447  /* Yield our process time to another thread.  */
     448  static inline void
     449  __gthread_objc_thread_yield (void)
     450  {
     451    if (__gthread_active_p ())
     452      __gthrw_(sched_yield) ();
     453  }
     454  
     455  /* Terminate the current thread.  */
     456  static inline int
     457  __gthread_objc_thread_exit (void)
     458  {
     459    if (__gthread_active_p ())
     460      /* exit the thread */
     461      __gthrw_(pthread_exit) (&__objc_thread_exit_status);
     462  
     463    /* Failed if we reached here */
     464    return -1;
     465  }
     466  
     467  /* Returns an integer value which uniquely describes a thread.  */
     468  static inline objc_thread_t
     469  __gthread_objc_thread_id (void)
     470  {
     471    if (__gthread_active_p ())
     472      return (objc_thread_t) __gthrw_(pthread_self) ();
     473    else
     474      return (objc_thread_t) 1;
     475  }
     476  
     477  /* Sets the thread's local storage pointer.  */
     478  static inline int
     479  __gthread_objc_thread_set_data (void *value)
     480  {
     481    if (__gthread_active_p ())
     482      return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
     483    else
     484      {
     485        thread_local_storage = value;
     486        return 0;
     487      }
     488  }
     489  
     490  /* Returns the thread's local storage pointer.  */
     491  static inline void *
     492  __gthread_objc_thread_get_data (void)
     493  {
     494    if (__gthread_active_p ())
     495      return __gthrw_(pthread_getspecific) (_objc_thread_storage);
     496    else
     497      return thread_local_storage;
     498  }
     499  
     500  /* Backend mutex functions */
     501  
     502  /* Allocate a mutex.  */
     503  static inline int
     504  __gthread_objc_mutex_allocate (objc_mutex_t mutex)
     505  {
     506    if (__gthread_active_p ())
     507      {
     508        mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
     509  
     510        if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
     511  	{
     512  	  objc_free (mutex->backend);
     513  	  mutex->backend = NULL;
     514  	  return -1;
     515  	}
     516      }
     517  
     518    return 0;
     519  }
     520  
     521  /* Deallocate a mutex.  */
     522  static inline int
     523  __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
     524  {
     525    if (__gthread_active_p ())
     526      {
     527        int count;
     528  
     529        /*
     530         * Posix Threads specifically require that the thread be unlocked
     531         * for __gthrw_(pthread_mutex_destroy) to work.
     532         */
     533  
     534        do
     535  	{
     536  	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
     537  	  if (count < 0)
     538  	    return -1;
     539  	}
     540        while (count);
     541  
     542        if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
     543  	return -1;
     544  
     545        objc_free (mutex->backend);
     546        mutex->backend = NULL;
     547      }
     548    return 0;
     549  }
     550  
     551  /* Grab a lock on a mutex.  */
     552  static inline int
     553  __gthread_objc_mutex_lock (objc_mutex_t mutex)
     554  {
     555    if (__gthread_active_p ()
     556        && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
     557      {
     558        return -1;
     559      }
     560  
     561    return 0;
     562  }
     563  
     564  /* Try to grab a lock on a mutex.  */
     565  static inline int
     566  __gthread_objc_mutex_trylock (objc_mutex_t mutex)
     567  {
     568    if (__gthread_active_p ()
     569        && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
     570      {
     571        return -1;
     572      }
     573  
     574    return 0;
     575  }
     576  
     577  /* Unlock the mutex */
     578  static inline int
     579  __gthread_objc_mutex_unlock (objc_mutex_t mutex)
     580  {
     581    if (__gthread_active_p ()
     582        && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
     583      {
     584        return -1;
     585      }
     586  
     587    return 0;
     588  }
     589  
     590  /* Backend condition mutex functions */
     591  
     592  /* Allocate a condition.  */
     593  static inline int
     594  __gthread_objc_condition_allocate (objc_condition_t condition)
     595  {
     596    if (__gthread_active_p ())
     597      {
     598        condition->backend = objc_malloc (sizeof (pthread_cond_t));
     599  
     600        if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
     601  	{
     602  	  objc_free (condition->backend);
     603  	  condition->backend = NULL;
     604  	  return -1;
     605  	}
     606      }
     607  
     608    return 0;
     609  }
     610  
     611  /* Deallocate a condition.  */
     612  static inline int
     613  __gthread_objc_condition_deallocate (objc_condition_t condition)
     614  {
     615    if (__gthread_active_p ())
     616      {
     617        if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
     618  	return -1;
     619  
     620        objc_free (condition->backend);
     621        condition->backend = NULL;
     622      }
     623    return 0;
     624  }
     625  
     626  /* Wait on the condition */
     627  static inline int
     628  __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
     629  {
     630    if (__gthread_active_p ())
     631      return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
     632  			      (pthread_mutex_t *) mutex->backend);
     633    else
     634      return 0;
     635  }
     636  
     637  /* Wake up all threads waiting on this condition.  */
     638  static inline int
     639  __gthread_objc_condition_broadcast (objc_condition_t condition)
     640  {
     641    if (__gthread_active_p ())
     642      return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
     643    else
     644      return 0;
     645  }
     646  
     647  /* Wake up one thread waiting on this condition.  */
     648  static inline int
     649  __gthread_objc_condition_signal (objc_condition_t condition)
     650  {
     651    if (__gthread_active_p ())
     652      return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
     653    else
     654      return 0;
     655  }
     656  
     657  #else /* _LIBOBJC */
     658  
     659  static inline int
     660  __gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
     661  		  void *__args)
     662  {
     663    return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
     664  }
     665  
     666  static inline int
     667  __gthread_join (__gthread_t __threadid, void **__value_ptr)
     668  {
     669    return __gthrw_(pthread_join) (__threadid, __value_ptr);
     670  }
     671  
     672  static inline int
     673  __gthread_detach (__gthread_t __threadid)
     674  {
     675    return __gthrw_(pthread_detach) (__threadid);
     676  }
     677  
     678  static inline int
     679  __gthread_equal (__gthread_t __t1, __gthread_t __t2)
     680  {
     681    return __gthrw_(pthread_equal) (__t1, __t2);
     682  }
     683  
     684  static inline __gthread_t
     685  __gthread_self (void)
     686  {
     687    return __gthrw_(pthread_self) ();
     688  }
     689  
     690  static inline int
     691  __gthread_yield (void)
     692  {
     693    return __gthrw_(sched_yield) ();
     694  }
     695  
     696  static inline int
     697  __gthread_once (__gthread_once_t *__once, void (*__func) (void))
     698  {
     699    if (__gthread_active_p ())
     700      return __gthrw_(pthread_once) (__once, __func);
     701    else
     702      return -1;
     703  }
     704  
     705  static inline int
     706  __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
     707  {
     708    return __gthrw_(pthread_key_create) (__key, __dtor);
     709  }
     710  
     711  static inline int
     712  __gthread_key_delete (__gthread_key_t __key)
     713  {
     714    return __gthrw_(pthread_key_delete) (__key);
     715  }
     716  
     717  static inline void *
     718  __gthread_getspecific (__gthread_key_t __key)
     719  {
     720    return __gthrw_(pthread_getspecific) (__key);
     721  }
     722  
     723  static inline int
     724  __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
     725  {
     726    return __gthrw_(pthread_setspecific) (__key, __ptr);
     727  }
     728  
     729  static inline void
     730  __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
     731  {
     732    if (__gthread_active_p ())
     733      __gthrw_(pthread_mutex_init) (__mutex, NULL);
     734  }
     735  
     736  static inline int
     737  __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
     738  {
     739    if (__gthread_active_p ())
     740      return __gthrw_(pthread_mutex_destroy) (__mutex);
     741    else
     742      return 0;
     743  }
     744  
     745  static inline int
     746  __gthread_mutex_lock (__gthread_mutex_t *__mutex)
     747  {
     748    if (__gthread_active_p ())
     749      return __gthrw_(pthread_mutex_lock) (__mutex);
     750    else
     751      return 0;
     752  }
     753  
     754  static inline int
     755  __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
     756  {
     757    if (__gthread_active_p ())
     758      return __gthrw_(pthread_mutex_trylock) (__mutex);
     759    else
     760      return 0;
     761  }
     762  
     763  #if _GTHREAD_USE_MUTEX_TIMEDLOCK
     764  static inline int
     765  __gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
     766  			   const __gthread_time_t *__abs_timeout)
     767  {
     768    if (__gthread_active_p ())
     769      return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout);
     770    else
     771      return 0;
     772  }
     773  #endif
     774  
     775  static inline int
     776  __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
     777  {
     778    if (__gthread_active_p ())
     779      return __gthrw_(pthread_mutex_unlock) (__mutex);
     780    else
     781      return 0;
     782  }
     783  
     784  #if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \
     785    || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
     786  static inline int
     787  __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
     788  {
     789    if (__gthread_active_p ())
     790      {
     791        pthread_mutexattr_t __attr;
     792        int __r;
     793  
     794        __r = __gthrw_(pthread_mutexattr_init) (&__attr);
     795        if (!__r)
     796  	__r = __gthrw_(pthread_mutexattr_settype) (&__attr,
     797  						   PTHREAD_MUTEX_RECURSIVE);
     798        if (!__r)
     799  	__r = __gthrw_(pthread_mutex_init) (__mutex, &__attr);
     800        if (!__r)
     801  	__r = __gthrw_(pthread_mutexattr_destroy) (&__attr);
     802        return __r;
     803      }
     804    return 0;
     805  }
     806  #endif
     807  
     808  static inline int
     809  __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
     810  {
     811    return __gthread_mutex_lock (__mutex);
     812  }
     813  
     814  static inline int
     815  __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
     816  {
     817    return __gthread_mutex_trylock (__mutex);
     818  }
     819  
     820  #if _GTHREAD_USE_MUTEX_TIMEDLOCK
     821  static inline int
     822  __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
     823  				     const __gthread_time_t *__abs_timeout)
     824  {
     825    return __gthread_mutex_timedlock (__mutex, __abs_timeout);
     826  }
     827  #endif
     828  
     829  static inline int
     830  __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
     831  {
     832    return __gthread_mutex_unlock (__mutex);
     833  }
     834  
     835  static inline int
     836  __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
     837  {
     838    return __gthread_mutex_destroy (__mutex);
     839  }
     840  
     841  #ifdef _GTHREAD_USE_COND_INIT_FUNC
     842  static inline void
     843  __gthread_cond_init_function (__gthread_cond_t *__cond)
     844  {
     845    if (__gthread_active_p ())
     846      __gthrw_(pthread_cond_init) (__cond, NULL);
     847  }
     848  #endif
     849  
     850  static inline int
     851  __gthread_cond_broadcast (__gthread_cond_t *__cond)
     852  {
     853    return __gthrw_(pthread_cond_broadcast) (__cond);
     854  }
     855  
     856  static inline int
     857  __gthread_cond_signal (__gthread_cond_t *__cond)
     858  {
     859    return __gthrw_(pthread_cond_signal) (__cond);
     860  }
     861  
     862  static inline int
     863  __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
     864  {
     865    return __gthrw_(pthread_cond_wait) (__cond, __mutex);
     866  }
     867  
     868  static inline int
     869  __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
     870  			  const __gthread_time_t *__abs_timeout)
     871  {
     872    return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
     873  }
     874  
     875  static inline int
     876  __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
     877  			       __gthread_recursive_mutex_t *__mutex)
     878  {
     879    return __gthread_cond_wait (__cond, __mutex);
     880  }
     881  
     882  static inline int
     883  __gthread_cond_destroy (__gthread_cond_t* __cond)
     884  {
     885    return __gthrw_(pthread_cond_destroy) (__cond);
     886  }
     887  
     888  #endif /* _LIBOBJC */
     889  
     890  #endif /* ! GCC_GTHR_POSIX_H */