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