]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/gthr-posix.h
gcc/testsuite/
[thirdparty/gcc.git] / libgcc / gthr-posix.h
CommitLineData
6319d58e 1/* Threads compatibility routines for libgcc2 and libobjc. */
58febf9e 2/* Compile this one with gcc. */
fbd26352 3/* Copyright (C) 1997-2019 Free Software Foundation, Inc.
58febf9e 4
f12b58b3 5This file is part of GCC.
58febf9e 6
f12b58b3 7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
6bc9506f 9Software Foundation; either version 3, or (at your option) any later
f12b58b3 10version.
58febf9e 11
f12b58b3 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
58febf9e 16
6bc9506f 17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24<http://www.gnu.org/licenses/>. */
58febf9e 25
2a281353 26#ifndef GCC_GTHR_POSIX_H
27#define GCC_GTHR_POSIX_H
58febf9e 28
29/* POSIX threads specific definitions.
5a54c45e 30 Easy, since the interface is just one-to-one mapping. */
58febf9e 31
32#define __GTHREADS 1
3fbf11ef 33#define __GTHREADS_CXX0X 1
58febf9e 34
35#include <pthread.h>
24335a64 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
58febf9e 46
3fbf11ef 47typedef pthread_t __gthread_t;
58febf9e 48typedef pthread_key_t __gthread_key_t;
49typedef pthread_once_t __gthread_once_t;
50typedef pthread_mutex_t __gthread_mutex_t;
4813f5af 51typedef pthread_mutex_t __gthread_recursive_mutex_t;
c0aa46db 52typedef pthread_cond_t __gthread_cond_t;
3fbf11ef 53typedef struct timespec __gthread_time_t;
c0aa46db 54
55/* POSIX like conditional variables are supported. Please look at comments
56 in gthr.h for details. */
48e1416a 57#define __GTHREAD_HAS_COND 1
58febf9e 58
59#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
2e7d9be1 60#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
58febf9e 61#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
4813f5af 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
ff00b6c5 66#else
09f175fa 67#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
4813f5af 68#endif
c0aa46db 69#define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
3fbf11ef 70#define __GTHREAD_TIME_INIT {0,0}
58febf9e 71
f47763a6 72#ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
73# undef __GTHREAD_MUTEX_INIT
f47763a6 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
58febf9e 85#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
7f385964 86# ifndef __gthrw_pragma
87# define __gthrw_pragma(pragma)
88# endif
80164241 89# define __gthrw2(name,name2,type) \
dd1ab8da 90 static __typeof(type) name \
91 __attribute__ ((__weakref__(#name2), __copy__ (type))); \
7f385964 92 __gthrw_pragma(weak type)
bfd7d80d 93# define __gthrw_(name) __gthrw_ ## name
6251c8ef 94#else
80164241 95# define __gthrw2(name,name2,type)
bfd7d80d 96# define __gthrw_(name) name
6251c8ef 97#endif
58febf9e 98
ba2ddb4b 99/* Typically, __gthrw_foo is a weak reference to symbol foo. */
80164241 100#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
3b19d3be 101
bfd7d80d 102__gthrw(pthread_once)
bfd7d80d 103__gthrw(pthread_getspecific)
104__gthrw(pthread_setspecific)
3fbf11ef 105
bfd7d80d 106__gthrw(pthread_create)
3fbf11ef 107__gthrw(pthread_join)
108__gthrw(pthread_equal)
109__gthrw(pthread_self)
110__gthrw(pthread_detach)
6c1af759 111#ifndef __BIONIC__
bfd7d80d 112__gthrw(pthread_cancel)
6c1af759 113#endif
3fbf11ef 114__gthrw(sched_yield)
115
bfd7d80d 116__gthrw(pthread_mutex_lock)
117__gthrw(pthread_mutex_trylock)
24335a64 118#if _GTHREAD_USE_MUTEX_TIMEDLOCK
3fbf11ef 119__gthrw(pthread_mutex_timedlock)
189a0b8c 120#endif
bfd7d80d 121__gthrw(pthread_mutex_unlock)
3b19d3be 122__gthrw(pthread_mutex_init)
1cd3a344 123__gthrw(pthread_mutex_destroy)
3fbf11ef 124
f47763a6 125__gthrw(pthread_cond_init)
c0aa46db 126__gthrw(pthread_cond_broadcast)
3fbf11ef 127__gthrw(pthread_cond_signal)
c0aa46db 128__gthrw(pthread_cond_wait)
3fbf11ef 129__gthrw(pthread_cond_timedwait)
130__gthrw(pthread_cond_destroy)
3b19d3be 131
132__gthrw(pthread_key_create)
133__gthrw(pthread_key_delete)
bfd7d80d 134__gthrw(pthread_mutexattr_init)
135__gthrw(pthread_mutexattr_settype)
136__gthrw(pthread_mutexattr_destroy)
fcbbb04c 137
6319d58e 138
ecd34a08 139#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
7fd957fe 140/* Objective-C. */
bfd7d80d 141__gthrw(pthread_exit)
a55f666d 142#ifdef _POSIX_PRIORITY_SCHEDULING
f9f6f55a 143#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
bfd7d80d 144__gthrw(sched_get_priority_max)
145__gthrw(sched_get_priority_min)
f9f6f55a 146#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
a55f666d 147#endif /* _POSIX_PRIORITY_SCHEDULING */
bfd7d80d 148__gthrw(pthread_attr_destroy)
149__gthrw(pthread_attr_init)
150__gthrw(pthread_attr_setdetachstate)
f9f6f55a 151#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
bfd7d80d 152__gthrw(pthread_getschedparam)
153__gthrw(pthread_setschedparam)
f9f6f55a 154#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
ecd34a08 155#endif /* _LIBOBJC || _LIBOBJC_WEAK */
58febf9e 156
6251c8ef 157#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
158
2f9d7fdd 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
4f364038 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. */
2f9d7fdd 169
4f364038 170#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
2f9d7fdd 171
172static volatile int __gthread_active = -1;
173
174static void
175__gthread_trigger (void)
176{
177 __gthread_active = 1;
178}
179
180static 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
4f364038 213#else /* neither FreeBSD nor Solaris */
2f9d7fdd 214
026e608e 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
58febf9e 247static inline int
205b5771 248__gthread_active_p (void)
58febf9e 249{
90590009 250 static void *const __gthread_active_ptr
026e608e 251 = __extension__ (void *) &GTHR_ACTIVE_PROXY;
58febf9e 252 return __gthread_active_ptr != 0;
253}
254
4f364038 255#endif /* FreeBSD or Solaris */
2f9d7fdd 256
58febf9e 257#else /* not SUPPORTS_WEAK */
258
05f60a3c 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
698b676d 263 provided for checking whether an application is linked to a shared pthread
05f60a3c 264 library or not. However, these interfaces aren't available in early
698b676d 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. */
05f60a3c 275
276#if defined(__hppa__) && defined(__hpux__)
277
05f60a3c 278static volatile int __gthread_active = -1;
279
05f60a3c 280static 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;
698b676d 285 size_t __s;
05f60a3c 286
05f60a3c 287 if (__builtin_expect (__gthread_active_latest_value < 0, 0))
288 {
698b676d 289 pthread_default_stacksize_np (0, &__s);
290 __gthread_active = __s ? 1 : 0;
05f60a3c 291 __gthread_active_latest_value = __gthread_active;
292 }
293
294 return __gthread_active_latest_value != 0;
295}
296
297#else /* not hppa-hpux */
298
58febf9e 299static inline int
205b5771 300__gthread_active_p (void)
58febf9e 301{
302 return 1;
303}
304
05f60a3c 305#endif /* hppa-hpux */
306
58febf9e 307#endif /* SUPPORTS_WEAK */
308
6319d58e 309#ifdef _LIBOBJC
310
53f5af15 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
6319d58e 318/* Key structure for maintaining thread specific storage */
319static pthread_key_t _objc_thread_storage;
eb7dae3a 320static pthread_attr_t _objc_thread_attribs;
6319d58e 321
322/* Thread local storage for a single thread */
323static void *thread_local_storage = NULL;
324
325/* Backend initialization functions */
326
5a54c45e 327/* Initialize the threads subsystem. */
6319d58e 328static inline int
b6546344 329__gthread_objc_init_thread_system (void)
6319d58e 330{
331 if (__gthread_active_p ())
eb7dae3a 332 {
778ac06a 333 /* Initialize the thread storage key. */
bfd7d80d 334 if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
3cfec666 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. */
bfd7d80d 339 if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
340 && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
b6546344 341 PTHREAD_CREATE_DETACHED) == 0)
3cfec666 342 return 0;
343 }
eb7dae3a 344 }
02cb9619 345
346 return -1;
6319d58e 347}
348
5a54c45e 349/* Close the threads subsystem. */
6319d58e 350static inline int
b6546344 351__gthread_objc_close_thread_system (void)
6319d58e 352{
eb7dae3a 353 if (__gthread_active_p ()
bfd7d80d 354 && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
355 && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
6319d58e 356 return 0;
eb7dae3a 357
358 return -1;
6319d58e 359}
360
361/* Backend thread functions */
362
5a54c45e 363/* Create a new thread of execution. */
6319d58e 364static inline objc_thread_t
b6546344 365__gthread_objc_thread_detach (void (*func)(void *), void *arg)
6319d58e 366{
367 objc_thread_t thread_id;
368 pthread_t new_thread_handle;
369
370 if (!__gthread_active_p ())
371 return NULL;
3cfec666 372
0c54aa2a 373 if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs,
374 (void *) func, arg)))
05036d9f 375 thread_id = (objc_thread_t) new_thread_handle;
6319d58e 376 else
377 thread_id = NULL;
3cfec666 378
6319d58e 379 return thread_id;
380}
381
5a54c45e 382/* Set the current thread's priority. */
6319d58e 383static inline int
b6546344 384__gthread_objc_thread_set_priority (int priority)
6319d58e 385{
b6546344 386 if (!__gthread_active_p ())
eb7dae3a 387 return -1;
b6546344 388 else
389 {
a55f666d 390#ifdef _POSIX_PRIORITY_SCHEDULING
f9f6f55a 391#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
bfd7d80d 392 pthread_t thread_id = __gthrw_(pthread_self) ();
b6546344 393 int policy;
394 struct sched_param params;
395 int priority_min, priority_max;
3cfec666 396
bfd7d80d 397 if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
b6546344 398 {
bfd7d80d 399 if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
b6546344 400 return -1;
401
bfd7d80d 402 if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
b6546344 403 return -1;
3cfec666 404
b6546344 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 */
bfd7d80d 416 if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
b6546344 417 return 0;
418 }
f9f6f55a 419#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
a55f666d 420#endif /* _POSIX_PRIORITY_SCHEDULING */
b6546344 421 return -1;
422 }
6319d58e 423}
424
5a54c45e 425/* Return the current thread's priority. */
6319d58e 426static inline int
b6546344 427__gthread_objc_thread_get_priority (void)
6319d58e 428{
a55f666d 429#ifdef _POSIX_PRIORITY_SCHEDULING
f9f6f55a 430#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
6319d58e 431 if (__gthread_active_p ())
eb7dae3a 432 {
433 int policy;
434 struct sched_param params;
435
bfd7d80d 436 if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
3cfec666 437 return params.sched_priority;
eb7dae3a 438 else
3cfec666 439 return -1;
eb7dae3a 440 }
6319d58e 441 else
f9f6f55a 442#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
a55f666d 443#endif /* _POSIX_PRIORITY_SCHEDULING */
6319d58e 444 return OBJC_THREAD_INTERACTIVE_PRIORITY;
445}
446
5a54c45e 447/* Yield our process time to another thread. */
6319d58e 448static inline void
b6546344 449__gthread_objc_thread_yield (void)
6319d58e 450{
451 if (__gthread_active_p ())
bfd7d80d 452 __gthrw_(sched_yield) ();
6319d58e 453}
454
5a54c45e 455/* Terminate the current thread. */
6319d58e 456static inline int
b6546344 457__gthread_objc_thread_exit (void)
6319d58e 458{
459 if (__gthread_active_p ())
460 /* exit the thread */
bfd7d80d 461 __gthrw_(pthread_exit) (&__objc_thread_exit_status);
6319d58e 462
463 /* Failed if we reached here */
464 return -1;
465}
466
5a54c45e 467/* Returns an integer value which uniquely describes a thread. */
6319d58e 468static inline objc_thread_t
b6546344 469__gthread_objc_thread_id (void)
6319d58e 470{
471 if (__gthread_active_p ())
bfd7d80d 472 return (objc_thread_t) __gthrw_(pthread_self) ();
6319d58e 473 else
05036d9f 474 return (objc_thread_t) 1;
6319d58e 475}
476
5a54c45e 477/* Sets the thread's local storage pointer. */
6319d58e 478static inline int
b6546344 479__gthread_objc_thread_set_data (void *value)
6319d58e 480{
481 if (__gthread_active_p ())
bfd7d80d 482 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
6319d58e 483 else
484 {
485 thread_local_storage = value;
486 return 0;
487 }
488}
489
5a54c45e 490/* Returns the thread's local storage pointer. */
6319d58e 491static inline void *
b6546344 492__gthread_objc_thread_get_data (void)
6319d58e 493{
494 if (__gthread_active_p ())
bfd7d80d 495 return __gthrw_(pthread_getspecific) (_objc_thread_storage);
6319d58e 496 else
497 return thread_local_storage;
498}
499
500/* Backend mutex functions */
501
5a54c45e 502/* Allocate a mutex. */
6319d58e 503static inline int
b6546344 504__gthread_objc_mutex_allocate (objc_mutex_t mutex)
6319d58e 505{
506 if (__gthread_active_p ())
507 {
b6546344 508 mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
6319d58e 509
bfd7d80d 510 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
6319d58e 511 {
b6546344 512 objc_free (mutex->backend);
6319d58e 513 mutex->backend = NULL;
514 return -1;
515 }
516 }
517
518 return 0;
519}
520
5a54c45e 521/* Deallocate a mutex. */
6319d58e 522static inline int
b6546344 523__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
6319d58e 524{
525 if (__gthread_active_p ())
526 {
527 int count;
528
529 /*
530 * Posix Threads specifically require that the thread be unlocked
bfd7d80d 531 * for __gthrw_(pthread_mutex_destroy) to work.
6319d58e 532 */
533
534 do
535 {
bfd7d80d 536 count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
6319d58e 537 if (count < 0)
538 return -1;
539 }
540 while (count);
541
bfd7d80d 542 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
6319d58e 543 return -1;
544
b6546344 545 objc_free (mutex->backend);
6319d58e 546 mutex->backend = NULL;
547 }
548 return 0;
549}
550
5a54c45e 551/* Grab a lock on a mutex. */
6319d58e 552static inline int
b6546344 553__gthread_objc_mutex_lock (objc_mutex_t mutex)
6319d58e 554{
3cfec666 555 if (__gthread_active_p ()
bfd7d80d 556 && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
273f030c 557 {
558 return -1;
559 }
560
561 return 0;
6319d58e 562}
563
5a54c45e 564/* Try to grab a lock on a mutex. */
6319d58e 565static inline int
b6546344 566__gthread_objc_mutex_trylock (objc_mutex_t mutex)
6319d58e 567{
3cfec666 568 if (__gthread_active_p ()
bfd7d80d 569 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
273f030c 570 {
571 return -1;
572 }
573
574 return 0;
6319d58e 575}
576
577/* Unlock the mutex */
578static inline int
b6546344 579__gthread_objc_mutex_unlock (objc_mutex_t mutex)
6319d58e 580{
3cfec666 581 if (__gthread_active_p ()
bfd7d80d 582 && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
273f030c 583 {
584 return -1;
585 }
586
587 return 0;
6319d58e 588}
589
590/* Backend condition mutex functions */
591
5a54c45e 592/* Allocate a condition. */
6319d58e 593static inline int
b6546344 594__gthread_objc_condition_allocate (objc_condition_t condition)
6319d58e 595{
596 if (__gthread_active_p ())
597 {
b6546344 598 condition->backend = objc_malloc (sizeof (pthread_cond_t));
6319d58e 599
bfd7d80d 600 if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
6319d58e 601 {
b6546344 602 objc_free (condition->backend);
6319d58e 603 condition->backend = NULL;
604 return -1;
605 }
606 }
607
608 return 0;
609}
610
5a54c45e 611/* Deallocate a condition. */
6319d58e 612static inline int
b6546344 613__gthread_objc_condition_deallocate (objc_condition_t condition)
6319d58e 614{
615 if (__gthread_active_p ())
616 {
bfd7d80d 617 if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
6319d58e 618 return -1;
619
b6546344 620 objc_free (condition->backend);
6319d58e 621 condition->backend = NULL;
622 }
623 return 0;
624}
625
626/* Wait on the condition */
627static inline int
b6546344 628__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
6319d58e 629{
630 if (__gthread_active_p ())
bfd7d80d 631 return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
b6546344 632 (pthread_mutex_t *) mutex->backend);
6319d58e 633 else
634 return 0;
635}
636
5a54c45e 637/* Wake up all threads waiting on this condition. */
6319d58e 638static inline int
b6546344 639__gthread_objc_condition_broadcast (objc_condition_t condition)
6319d58e 640{
641 if (__gthread_active_p ())
bfd7d80d 642 return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
6319d58e 643 else
644 return 0;
645}
646
5a54c45e 647/* Wake up one thread waiting on this condition. */
6319d58e 648static inline int
b6546344 649__gthread_objc_condition_signal (objc_condition_t condition)
6319d58e 650{
651 if (__gthread_active_p ())
bfd7d80d 652 return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
6319d58e 653 else
654 return 0;
655}
656
657#else /* _LIBOBJC */
658
3fbf11ef 659static inline int
320084b9 660__gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
661 void *__args)
3fbf11ef 662{
320084b9 663 return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
3fbf11ef 664}
665
666static inline int
320084b9 667__gthread_join (__gthread_t __threadid, void **__value_ptr)
3fbf11ef 668{
320084b9 669 return __gthrw_(pthread_join) (__threadid, __value_ptr);
3fbf11ef 670}
671
672static inline int
320084b9 673__gthread_detach (__gthread_t __threadid)
3fbf11ef 674{
320084b9 675 return __gthrw_(pthread_detach) (__threadid);
3fbf11ef 676}
677
678static inline int
320084b9 679__gthread_equal (__gthread_t __t1, __gthread_t __t2)
3fbf11ef 680{
320084b9 681 return __gthrw_(pthread_equal) (__t1, __t2);
3fbf11ef 682}
683
684static inline __gthread_t
685__gthread_self (void)
686{
687 return __gthrw_(pthread_self) ();
688}
689
690static inline int
691__gthread_yield (void)
692{
693 return __gthrw_(sched_yield) ();
694}
695
58febf9e 696static inline int
320084b9 697__gthread_once (__gthread_once_t *__once, void (*__func) (void))
58febf9e 698{
699 if (__gthread_active_p ())
320084b9 700 return __gthrw_(pthread_once) (__once, __func);
58febf9e 701 else
702 return -1;
703}
704
705static inline int
320084b9 706__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
58febf9e 707{
320084b9 708 return __gthrw_(pthread_key_create) (__key, __dtor);
58febf9e 709}
710
58febf9e 711static inline int
320084b9 712__gthread_key_delete (__gthread_key_t __key)
58febf9e 713{
320084b9 714 return __gthrw_(pthread_key_delete) (__key);
58febf9e 715}
716
717static inline void *
320084b9 718__gthread_getspecific (__gthread_key_t __key)
58febf9e 719{
320084b9 720 return __gthrw_(pthread_getspecific) (__key);
58febf9e 721}
722
723static inline int
320084b9 724__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
58febf9e 725{
320084b9 726 return __gthrw_(pthread_setspecific) (__key, __ptr);
58febf9e 727}
728
f47763a6 729static 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}
2e7d9be1 735
1cd3a344 736static inline int
320084b9 737__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
1cd3a344 738{
739 if (__gthread_active_p ())
320084b9 740 return __gthrw_(pthread_mutex_destroy) (__mutex);
1cd3a344 741 else
742 return 0;
743}
744
58febf9e 745static inline int
320084b9 746__gthread_mutex_lock (__gthread_mutex_t *__mutex)
58febf9e 747{
748 if (__gthread_active_p ())
320084b9 749 return __gthrw_(pthread_mutex_lock) (__mutex);
58febf9e 750 else
751 return 0;
752}
753
754static inline int
320084b9 755__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
58febf9e 756{
757 if (__gthread_active_p ())
320084b9 758 return __gthrw_(pthread_mutex_trylock) (__mutex);
58febf9e 759 else
760 return 0;
761}
762
24335a64 763#if _GTHREAD_USE_MUTEX_TIMEDLOCK
3fbf11ef 764static inline int
320084b9 765__gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
766 const __gthread_time_t *__abs_timeout)
3fbf11ef 767{
768 if (__gthread_active_p ())
320084b9 769 return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout);
3fbf11ef 770 else
771 return 0;
772}
773#endif
774
58febf9e 775static inline int
320084b9 776__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
58febf9e 777{
778 if (__gthread_active_p ())
320084b9 779 return __gthrw_(pthread_mutex_unlock) (__mutex);
58febf9e 780 else
781 return 0;
782}
783
f47763a6 784#if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \
785 || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
4813f5af 786static inline int
320084b9 787__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
4813f5af 788{
789 if (__gthread_active_p ())
790 {
320084b9 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;
4813f5af 803 }
fa7d6e96 804 return 0;
4813f5af 805}
806#endif
807
808static inline int
320084b9 809__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
4813f5af 810{
320084b9 811 return __gthread_mutex_lock (__mutex);
4813f5af 812}
813
814static inline int
320084b9 815__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
4813f5af 816{
320084b9 817 return __gthread_mutex_trylock (__mutex);
4813f5af 818}
819
24335a64 820#if _GTHREAD_USE_MUTEX_TIMEDLOCK
3fbf11ef 821static inline int
320084b9 822__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
823 const __gthread_time_t *__abs_timeout)
3fbf11ef 824{
320084b9 825 return __gthread_mutex_timedlock (__mutex, __abs_timeout);
3fbf11ef 826}
827#endif
828
4813f5af 829static inline int
320084b9 830__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
4813f5af 831{
320084b9 832 return __gthread_mutex_unlock (__mutex);
4813f5af 833}
834
4854adab 835static inline int
836__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
837{
838 return __gthread_mutex_destroy (__mutex);
839}
840
f47763a6 841#ifdef _GTHREAD_USE_COND_INIT_FUNC
842static 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
c0aa46db 850static inline int
320084b9 851__gthread_cond_broadcast (__gthread_cond_t *__cond)
c0aa46db 852{
320084b9 853 return __gthrw_(pthread_cond_broadcast) (__cond);
c0aa46db 854}
855
3fbf11ef 856static inline int
320084b9 857__gthread_cond_signal (__gthread_cond_t *__cond)
3fbf11ef 858{
320084b9 859 return __gthrw_(pthread_cond_signal) (__cond);
3fbf11ef 860}
861
c0aa46db 862static inline int
320084b9 863__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
c0aa46db 864{
320084b9 865 return __gthrw_(pthread_cond_wait) (__cond, __mutex);
c0aa46db 866}
867
3fbf11ef 868static inline int
320084b9 869__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
870 const __gthread_time_t *__abs_timeout)
3fbf11ef 871{
320084b9 872 return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
3fbf11ef 873}
874
c0aa46db 875static inline int
320084b9 876__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
877 __gthread_recursive_mutex_t *__mutex)
c0aa46db 878{
320084b9 879 return __gthread_cond_wait (__cond, __mutex);
c0aa46db 880}
881
3fbf11ef 882static inline int
320084b9 883__gthread_cond_destroy (__gthread_cond_t* __cond)
3fbf11ef 884{
320084b9 885 return __gthrw_(pthread_cond_destroy) (__cond);
3fbf11ef 886}
887
6319d58e 888#endif /* _LIBOBJC */
889
2a281353 890#endif /* ! GCC_GTHR_POSIX_H */