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