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