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