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