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 _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
__gthread_trigger(void)174 __gthread_trigger (void)
175 {
176   __gthread_active = 1;
177 }
178 
179 static inline int
__gthread_active_p(void)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 /* L4Re added: "&& !defined(__UCLIBC__)" */
236 #if defined(__GLIBC__) && !defined(__UCLIBC__)
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 *) &GTHR_ACTIVE_PROXY;
252   return __gthread_active_ptr != 0;
253 }
254 
255 #endif /* FreeBSD or Solaris */
256 
257 #else /* not __GXX_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 /* __GXX_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
__gthread_objc_init_thread_system(void)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
__gthread_objc_close_thread_system(void)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
__gthread_objc_thread_detach(void (* func)(void *),void * arg)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
__gthread_objc_thread_set_priority(int priority)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, &params) == 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, &params) == 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
__gthread_objc_thread_get_priority(void)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, &params) == 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
__gthread_objc_thread_yield(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
__gthread_objc_thread_exit(void)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
__gthread_objc_thread_id(void)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
__gthread_objc_thread_set_data(void * value)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 *
__gthread_objc_thread_get_data(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
__gthread_objc_mutex_allocate(objc_mutex_t mutex)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
__gthread_objc_mutex_deallocate(objc_mutex_t mutex)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
__gthread_objc_mutex_lock(objc_mutex_t mutex)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
__gthread_objc_mutex_trylock(objc_mutex_t mutex)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
__gthread_objc_mutex_unlock(objc_mutex_t mutex)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
__gthread_objc_condition_allocate(objc_condition_t condition)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
__gthread_objc_condition_deallocate(objc_condition_t condition)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
__gthread_objc_condition_wait(objc_condition_t condition,objc_mutex_t mutex)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
__gthread_objc_condition_broadcast(objc_condition_t condition)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
__gthread_objc_condition_signal(objc_condition_t condition)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
__gthread_create(__gthread_t * __threadid,void * (* __func)(void *),void * __args)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
__gthread_join(__gthread_t __threadid,void ** __value_ptr)667 __gthread_join (__gthread_t __threadid, void **__value_ptr)
668 {
669   return __gthrw_(pthread_join) (__threadid, __value_ptr);
670 }
671 
672 static inline int
__gthread_detach(__gthread_t __threadid)673 __gthread_detach (__gthread_t __threadid)
674 {
675   return __gthrw_(pthread_detach) (__threadid);
676 }
677 
678 static inline int
__gthread_equal(__gthread_t __t1,__gthread_t __t2)679 __gthread_equal (__gthread_t __t1, __gthread_t __t2)
680 {
681   return __gthrw_(pthread_equal) (__t1, __t2);
682 }
683 
684 static inline __gthread_t
__gthread_self(void)685 __gthread_self (void)
686 {
687   return __gthrw_(pthread_self) ();
688 }
689 
690 static inline int
__gthread_yield(void)691 __gthread_yield (void)
692 {
693   return __gthrw_(sched_yield) ();
694 }
695 
696 static inline int
__gthread_once(__gthread_once_t * __once,void (* __func)(void))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
__gthread_key_create(__gthread_key_t * __key,void (* __dtor)(void *))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
__gthread_key_delete(__gthread_key_t __key)712 __gthread_key_delete (__gthread_key_t __key)
713 {
714   return __gthrw_(pthread_key_delete) (__key);
715 }
716 
717 static inline void *
__gthread_getspecific(__gthread_key_t __key)718 __gthread_getspecific (__gthread_key_t __key)
719 {
720   return __gthrw_(pthread_getspecific) (__key);
721 }
722 
723 static inline int
__gthread_setspecific(__gthread_key_t __key,const void * __ptr)724 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
725 {
726   return __gthrw_(pthread_setspecific) (__key, __ptr);
727 }
728 
729 static inline void
__gthread_mutex_init_function(__gthread_mutex_t * __mutex)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
__gthread_mutex_destroy(__gthread_mutex_t * __mutex)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
__gthread_mutex_lock(__gthread_mutex_t * __mutex)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
__gthread_mutex_trylock(__gthread_mutex_t * __mutex)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
__gthread_mutex_timedlock(__gthread_mutex_t * __mutex,const __gthread_time_t * __abs_timeout)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
__gthread_mutex_unlock(__gthread_mutex_t * __mutex)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
__gthread_recursive_mutex_init_function(__gthread_recursive_mutex_t * __mutex)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
__gthread_recursive_mutex_lock(__gthread_recursive_mutex_t * __mutex)809 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
810 {
811   return __gthread_mutex_lock (__mutex);
812 }
813 
814 static inline int
__gthread_recursive_mutex_trylock(__gthread_recursive_mutex_t * __mutex)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
__gthread_recursive_mutex_timedlock(__gthread_recursive_mutex_t * __mutex,const __gthread_time_t * __abs_timeout)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
__gthread_recursive_mutex_unlock(__gthread_recursive_mutex_t * __mutex)830 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
831 {
832   return __gthread_mutex_unlock (__mutex);
833 }
834 
835 static inline int
__gthread_recursive_mutex_destroy(__gthread_recursive_mutex_t * __mutex)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
__gthread_cond_init_function(__gthread_cond_t * __cond)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
__gthread_cond_broadcast(__gthread_cond_t * __cond)851 __gthread_cond_broadcast (__gthread_cond_t *__cond)
852 {
853   return __gthrw_(pthread_cond_broadcast) (__cond);
854 }
855 
856 static inline int
__gthread_cond_signal(__gthread_cond_t * __cond)857 __gthread_cond_signal (__gthread_cond_t *__cond)
858 {
859   return __gthrw_(pthread_cond_signal) (__cond);
860 }
861 
862 static inline int
__gthread_cond_wait(__gthread_cond_t * __cond,__gthread_mutex_t * __mutex)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
__gthread_cond_timedwait(__gthread_cond_t * __cond,__gthread_mutex_t * __mutex,const __gthread_time_t * __abs_timeout)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
__gthread_cond_wait_recursive(__gthread_cond_t * __cond,__gthread_recursive_mutex_t * __mutex)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
__gthread_cond_destroy(__gthread_cond_t * __cond)883 __gthread_cond_destroy (__gthread_cond_t* __cond)
884 {
885   return __gthrw_(pthread_cond_destroy) (__cond);
886 }
887 
888 #endif /* _LIBOBJC */
889 
890 #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */
891