Line data Source code
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 3334 : __gthread_active_p (void)
249 : {
250 3334 : static void *const __gthread_active_ptr
251 : = __extension__ (void *) >HR_ACTIVE_PROXY;
252 3334 : 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 712 : __gthread_mutex_lock (__gthread_mutex_t *__mutex)
747 : {
748 712 : if (__gthread_active_p ())
749 712 : 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 712 : __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
777 : {
778 712 : if (__gthread_active_p ())
779 712 : 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 */
|