]>
Commit | Line | Data |
---|---|---|
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 | 5 | This file is part of GCC. |
f24af81b | 6 | |
1322177d LB |
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 | |
748086b7 | 9 | Software Foundation; either version 3, or (at your option) any later |
1322177d | 10 | version. |
f24af81b | 11 | |
1322177d LB |
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. | |
f24af81b | 16 | |
748086b7 JJ |
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/>. */ | |
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 | 62 | typedef pthread_t __gthread_t; |
f24af81b TT |
63 | typedef pthread_key_t __gthread_key_t; |
64 | typedef pthread_once_t __gthread_once_t; | |
65 | typedef pthread_mutex_t __gthread_mutex_t; | |
b806c88f LZ |
66 | #ifndef __cplusplus |
67 | typedef pthread_rwlock_t __gthread_rwlock_t; | |
68 | #endif | |
40aac948 | 69 | typedef pthread_mutex_t __gthread_recursive_mutex_t; |
afd82ef5 | 70 | typedef pthread_cond_t __gthread_cond_t; |
a75150ae | 71 | typedef 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 *) >HR_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 */ |
365 | static pthread_key_t _objc_thread_storage; | |
447c11a5 | 366 | static pthread_attr_t _objc_thread_attribs; |
15794a95 L |
367 | |
368 | /* Thread local storage for a single thread */ | |
369 | static void *thread_local_storage = NULL; | |
370 | ||
371 | /* Backend initialization functions */ | |
372 | ||
71287280 | 373 | /* Initialize the threads subsystem. */ |
15794a95 | 374 | static 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 | 396 | static 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 | 410 | static 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 | 429 | static 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, ¶ms) == 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, ¶ms) == 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 | 472 | static 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, ¶ms) == 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 | 494 | static 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 | 502 | static 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 | 514 | static 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 | 524 | static 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 | 537 | static 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 | 549 | static 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 | 568 | static 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 | 598 | static 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 | 611 | static 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 */ | |
624 | static 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 | 639 | static 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 | 658 | static 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 */ | |
673 | static 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 | 684 | static 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 | 694 | static 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 */ |