1 : /* Threads compatibility routines for libgcc2 and libobjc. */
2 : /* Compile this one with gcc. */
3 : /* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4 : Free Software Foundation, Inc.
5 :
6 : This file is part of GCC.
7 :
8 : GCC is free software; you can redistribute it and/or modify it under
9 : the terms of the GNU General Public License as published by the Free
10 : Software Foundation; either version 2, or (at your option) any later
11 : version.
12 :
13 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 : for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with GCC; see the file COPYING. If not, write to the Free
20 : Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21 : 02110-1301, USA. */
22 :
23 : /* As a special exception, if you link this library with other files,
24 : some of which are compiled with GCC, to produce an executable,
25 : this library does not by itself cause the resulting executable
26 : to be covered by the GNU General Public License.
27 : This exception does not however invalidate any other reasons why
28 : the executable file might be covered by the GNU General Public License. */
29 :
30 : #ifndef _GLIBCXX_GCC_GTHR_POSIX_H
31 : #define _GLIBCXX_GCC_GTHR_POSIX_H
32 :
33 : /* POSIX threads specific definitions.
34 : Easy, since the interface is just one-to-one mapping. */
35 :
36 : #define __GTHREADS 1
37 :
38 : /* Some implementations of <pthread.h> require this to be defined. */
39 : #if !defined(_REENTRANT) && defined(__osf__)
40 : #define _REENTRANT 1
41 : #endif
42 :
43 : #include <pthread.h>
44 : #include <unistd.h>
45 :
46 : typedef pthread_key_t __gthread_key_t;
47 : typedef pthread_once_t __gthread_once_t;
48 : typedef pthread_mutex_t __gthread_mutex_t;
49 : typedef pthread_mutex_t __gthread_recursive_mutex_t;
50 : typedef pthread_cond_t __gthread_cond_t;
51 :
52 : /* POSIX like conditional variables are supported. Please look at comments
53 : in gthr.h for details. */
54 : #define __GTHREAD_HAS_COND 1
55 :
56 : #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
57 : #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
58 : #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
59 : #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
60 : #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
61 : #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
62 : #else
63 : #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
64 : #endif
65 : #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
66 :
67 : #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
68 : # ifndef __gthrw_pragma
69 : # define __gthrw_pragma(pragma)
70 : # endif
71 : # define __gthrw2(name,name2,type) \
72 : static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
73 : __gthrw_pragma(weak type)
74 : # define __gthrw_(name) __gthrw_ ## name
75 : #else
76 : # define __gthrw2(name,name2,type)
77 : # define __gthrw_(name) name
78 : #endif
79 :
80 : /* Typically, __gthrw_foo is a weak reference to symbol foo. */
81 : #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
82 :
83 : /* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
84 : map a subset of the POSIX pthread API to mangled versions of their
85 : names. */
86 : #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
87 : #define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
88 : __gthrw3(pthread_once)
89 : __gthrw3(pthread_getspecific)
90 : __gthrw3(pthread_setspecific)
91 : __gthrw3(pthread_create)
92 : __gthrw3(pthread_cancel)
93 : __gthrw3(pthread_mutex_lock)
94 : __gthrw3(pthread_mutex_trylock)
95 : __gthrw3(pthread_mutex_unlock)
96 : __gthrw3(pthread_mutex_init)
97 : __gthrw3(pthread_cond_broadcast)
98 : __gthrw3(pthread_cond_wait)
99 : #else
100 : __gthrw(pthread_once)
101 : __gthrw(pthread_getspecific)
102 : __gthrw(pthread_setspecific)
103 : __gthrw(pthread_create)
104 : __gthrw(pthread_cancel)
105 : __gthrw(pthread_mutex_lock)
106 : __gthrw(pthread_mutex_trylock)
107 : __gthrw(pthread_mutex_unlock)
108 : __gthrw(pthread_mutex_init)
109 : __gthrw(pthread_cond_broadcast)
110 : __gthrw(pthread_cond_wait)
111 : #endif
112 :
113 : __gthrw(pthread_key_create)
114 : __gthrw(pthread_key_delete)
115 : __gthrw(pthread_mutexattr_init)
116 : __gthrw(pthread_mutexattr_settype)
117 : __gthrw(pthread_mutexattr_destroy)
118 :
119 :
120 : #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
121 : /* Objective-C. */
122 : #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
123 : __gthrw3(pthread_cond_destroy)
124 : __gthrw3(pthread_cond_init)
125 : __gthrw3(pthread_cond_signal)
126 : __gthrw3(pthread_exit)
127 : __gthrw3(pthread_mutex_destroy)
128 : __gthrw3(pthread_self)
129 : #else
130 : __gthrw(pthread_cond_destroy)
131 : __gthrw(pthread_cond_init)
132 : __gthrw(pthread_cond_signal)
133 : __gthrw(pthread_exit)
134 : __gthrw(pthread_mutex_destroy)
135 : __gthrw(pthread_self)
136 : #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
137 : #ifdef _POSIX_PRIORITY_SCHEDULING
138 : #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
139 : __gthrw(sched_get_priority_max)
140 : __gthrw(sched_get_priority_min)
141 : #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
142 : #endif /* _POSIX_PRIORITY_SCHEDULING */
143 : __gthrw(sched_yield)
144 : __gthrw(pthread_attr_destroy)
145 : __gthrw(pthread_attr_init)
146 : __gthrw(pthread_attr_setdetachstate)
147 : #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
148 : __gthrw(pthread_getschedparam)
149 : __gthrw(pthread_setschedparam)
150 : #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
151 : #endif /* _LIBOBJC || _LIBOBJC_WEAK */
152 :
153 : #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
154 :
155 : /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
156 : -pthreads is not specified. The functions are dummies and most return an
157 : error value. However pthread_once returns 0 without invoking the routine
158 : it is passed so we cannot pretend that the interface is active if -pthreads
159 : is not specified. On Solaris 2.5.1, the interface is not exposed at all so
160 : we need to play the usual game with weak symbols. On Solaris 10 and up, a
161 : working interface is always exposed. On FreeBSD 6 and later, libc also
162 : exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
163 : to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
164 : which means the alternate __gthread_active_p below cannot be used there. */
165 :
166 : #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
167 :
168 : static volatile int __gthread_active = -1;
169 :
170 : static void
171 : __gthread_trigger (void)
172 : {
173 : __gthread_active = 1;
174 : }
175 :
176 : static inline int
177 : __gthread_active_p (void)
178 : {
179 : static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
180 : static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
181 :
182 : /* Avoid reading __gthread_active twice on the main code path. */
183 : int __gthread_active_latest_value = __gthread_active;
184 :
185 : /* This test is not protected to avoid taking a lock on the main code
186 : path so every update of __gthread_active in a threaded program must
187 : be atomic with regard to the result of the test. */
188 : if (__builtin_expect (__gthread_active_latest_value < 0, 0))
189 : {
190 : if (__gthrw_(pthread_once))
191 : {
192 : /* If this really is a threaded program, then we must ensure that
193 : __gthread_active has been set to 1 before exiting this block. */
194 : __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
195 : __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
196 : __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
197 : }
198 :
199 : /* Make sure we'll never enter this block again. */
200 : if (__gthread_active < 0)
201 : __gthread_active = 0;
202 :
203 : __gthread_active_latest_value = __gthread_active;
204 : }
205 :
206 : return __gthread_active_latest_value != 0;
207 : }
208 :
209 : #else /* neither FreeBSD nor Solaris */
210 :
211 : static inline int
212 0 : __gthread_active_p (void)
213 : {
214 : static void *const __gthread_active_ptr
215 : = __extension__ (void *) &__gthrw_(pthread_cancel);
216 0 : return __gthread_active_ptr != 0;
217 : }
218 :
219 : #endif /* FreeBSD or Solaris */
220 :
221 : #else /* not __GXX_WEAK__ */
222 :
223 : /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
224 : calls in shared flavors of the HP-UX C library. Most of the stubs
225 : have no functionality. The details are described in the "libc cumulative
226 : patch" for each subversion of HP-UX 11. There are two special interfaces
227 : provided for checking whether an application is linked to a pthread
228 : library or not. However, these interfaces aren't available in early
229 : libc versions. We also can't use pthread_once as some libc versions
230 : call the init function. So, we use pthread_create to check whether it
231 : is possible to create a thread or not. The stub implementation returns
232 : the error number ENOSYS. */
233 :
234 : #if defined(__hppa__) && defined(__hpux__)
235 :
236 : #include <errno.h>
237 :
238 : static volatile int __gthread_active = -1;
239 :
240 : static void *
241 : __gthread_start (void *arg __attribute__((unused)))
242 : {
243 : return NULL;
244 : }
245 :
246 : static void __gthread_active_init (void) __attribute__((noinline));
247 : static void
248 : __gthread_active_init (void)
249 : {
250 : static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
251 : pthread_t t;
252 : pthread_attr_t a;
253 : int result;
254 :
255 : __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
256 : if (__gthread_active < 0)
257 : {
258 : __gthrw_(pthread_attr_init) (&a);
259 : __gthrw_(pthread_attr_setdetachstate) (&a, PTHREAD_CREATE_DETACHED);
260 : result = __gthrw_(pthread_create) (&t, &a, __gthread_start, NULL);
261 : if (result != ENOSYS)
262 : __gthread_active = 1;
263 : else
264 : __gthread_active = 0;
265 : __gthrw_(pthread_attr_destroy) (&a);
266 : }
267 : __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
268 : }
269 :
270 : static inline int
271 : __gthread_active_p (void)
272 : {
273 : /* Avoid reading __gthread_active twice on the main code path. */
274 : int __gthread_active_latest_value = __gthread_active;
275 :
276 : /* This test is not protected to avoid taking a lock on the main code
277 : path so every update of __gthread_active in a threaded program must
278 : be atomic with regard to the result of the test. */
279 : if (__builtin_expect (__gthread_active_latest_value < 0, 0))
280 : {
281 : __gthread_active_init ();
282 : __gthread_active_latest_value = __gthread_active;
283 : }
284 :
285 : return __gthread_active_latest_value != 0;
286 : }
287 :
288 : #else /* not hppa-hpux */
289 :
290 : static inline int
291 : __gthread_active_p (void)
292 : {
293 : return 1;
294 : }
295 :
296 : #endif /* hppa-hpux */
297 :
298 : #endif /* __GXX_WEAK__ */
299 :
300 : #ifdef _LIBOBJC
301 :
302 : /* This is the config.h file in libobjc/ */
303 : #include <config.h>
304 :
305 : #ifdef HAVE_SCHED_H
306 : # include <sched.h>
307 : #endif
308 :
309 : /* Key structure for maintaining thread specific storage */
310 : static pthread_key_t _objc_thread_storage;
311 : static pthread_attr_t _objc_thread_attribs;
312 :
313 : /* Thread local storage for a single thread */
314 : static void *thread_local_storage = NULL;
315 :
316 : /* Backend initialization functions */
317 :
318 : /* Initialize the threads subsystem. */
319 : static inline int
320 : __gthread_objc_init_thread_system (void)
321 : {
322 : if (__gthread_active_p ())
323 : {
324 : /* Initialize the thread storage key. */
325 : if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
326 : {
327 : /* The normal default detach state for threads is
328 : * PTHREAD_CREATE_JOINABLE which causes threads to not die
329 : * when you think they should. */
330 : if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
331 : && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
332 : PTHREAD_CREATE_DETACHED) == 0)
333 : return 0;
334 : }
335 : }
336 :
337 : return -1;
338 : }
339 :
340 : /* Close the threads subsystem. */
341 : static inline int
342 : __gthread_objc_close_thread_system (void)
343 : {
344 : if (__gthread_active_p ()
345 : && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
346 : && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
347 : return 0;
348 :
349 : return -1;
350 : }
351 :
352 : /* Backend thread functions */
353 :
354 : /* Create a new thread of execution. */
355 : static inline objc_thread_t
356 : __gthread_objc_thread_detach (void (*func)(void *), void *arg)
357 : {
358 : objc_thread_t thread_id;
359 : pthread_t new_thread_handle;
360 :
361 : if (!__gthread_active_p ())
362 : return NULL;
363 :
364 : if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
365 : thread_id = (objc_thread_t) new_thread_handle;
366 : else
367 : thread_id = NULL;
368 :
369 : return thread_id;
370 : }
371 :
372 : /* Set the current thread's priority. */
373 : static inline int
374 : __gthread_objc_thread_set_priority (int priority)
375 : {
376 : if (!__gthread_active_p ())
377 : return -1;
378 : else
379 : {
380 : #ifdef _POSIX_PRIORITY_SCHEDULING
381 : #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
382 : pthread_t thread_id = __gthrw_(pthread_self) ();
383 : int policy;
384 : struct sched_param params;
385 : int priority_min, priority_max;
386 :
387 : if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0)
388 : {
389 : if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
390 : return -1;
391 :
392 : if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
393 : return -1;
394 :
395 : if (priority > priority_max)
396 : priority = priority_max;
397 : else if (priority < priority_min)
398 : priority = priority_min;
399 : params.sched_priority = priority;
400 :
401 : /*
402 : * The solaris 7 and several other man pages incorrectly state that
403 : * this should be a pointer to policy but pthread.h is universally
404 : * at odds with this.
405 : */
406 : if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0)
407 : return 0;
408 : }
409 : #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
410 : #endif /* _POSIX_PRIORITY_SCHEDULING */
411 : return -1;
412 : }
413 : }
414 :
415 : /* Return the current thread's priority. */
416 : static inline int
417 : __gthread_objc_thread_get_priority (void)
418 : {
419 : #ifdef _POSIX_PRIORITY_SCHEDULING
420 : #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
421 : if (__gthread_active_p ())
422 : {
423 : int policy;
424 : struct sched_param params;
425 :
426 : if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0)
427 : return params.sched_priority;
428 : else
429 : return -1;
430 : }
431 : else
432 : #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
433 : #endif /* _POSIX_PRIORITY_SCHEDULING */
434 : return OBJC_THREAD_INTERACTIVE_PRIORITY;
435 : }
436 :
437 : /* Yield our process time to another thread. */
438 : static inline void
439 : __gthread_objc_thread_yield (void)
440 : {
441 : if (__gthread_active_p ())
442 : __gthrw_(sched_yield) ();
443 : }
444 :
445 : /* Terminate the current thread. */
446 : static inline int
447 : __gthread_objc_thread_exit (void)
448 : {
449 : if (__gthread_active_p ())
450 : /* exit the thread */
451 : __gthrw_(pthread_exit) (&__objc_thread_exit_status);
452 :
453 : /* Failed if we reached here */
454 : return -1;
455 : }
456 :
457 : /* Returns an integer value which uniquely describes a thread. */
458 : static inline objc_thread_t
459 : __gthread_objc_thread_id (void)
460 : {
461 : if (__gthread_active_p ())
462 : return (objc_thread_t) __gthrw_(pthread_self) ();
463 : else
464 : return (objc_thread_t) 1;
465 : }
466 :
467 : /* Sets the thread's local storage pointer. */
468 : static inline int
469 : __gthread_objc_thread_set_data (void *value)
470 : {
471 : if (__gthread_active_p ())
472 : return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
473 : else
474 : {
475 : thread_local_storage = value;
476 : return 0;
477 : }
478 : }
479 :
480 : /* Returns the thread's local storage pointer. */
481 : static inline void *
482 : __gthread_objc_thread_get_data (void)
483 : {
484 : if (__gthread_active_p ())
485 : return __gthrw_(pthread_getspecific) (_objc_thread_storage);
486 : else
487 : return thread_local_storage;
488 : }
489 :
490 : /* Backend mutex functions */
491 :
492 : /* Allocate a mutex. */
493 : static inline int
494 : __gthread_objc_mutex_allocate (objc_mutex_t mutex)
495 : {
496 : if (__gthread_active_p ())
497 : {
498 : mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
499 :
500 : if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
501 : {
502 : objc_free (mutex->backend);
503 : mutex->backend = NULL;
504 : return -1;
505 : }
506 : }
507 :
508 : return 0;
509 : }
510 :
511 : /* Deallocate a mutex. */
512 : static inline int
513 : __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
514 : {
515 : if (__gthread_active_p ())
516 : {
517 : int count;
518 :
519 : /*
520 : * Posix Threads specifically require that the thread be unlocked
521 : * for __gthrw_(pthread_mutex_destroy) to work.
522 : */
523 :
524 : do
525 : {
526 : count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
527 : if (count < 0)
528 : return -1;
529 : }
530 : while (count);
531 :
532 : if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
533 : return -1;
534 :
535 : objc_free (mutex->backend);
536 : mutex->backend = NULL;
537 : }
538 : return 0;
539 : }
540 :
541 : /* Grab a lock on a mutex. */
542 : static inline int
543 : __gthread_objc_mutex_lock (objc_mutex_t mutex)
544 : {
545 : if (__gthread_active_p ()
546 : && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
547 : {
548 : return -1;
549 : }
550 :
551 : return 0;
552 : }
553 :
554 : /* Try to grab a lock on a mutex. */
555 : static inline int
556 : __gthread_objc_mutex_trylock (objc_mutex_t mutex)
557 : {
558 : if (__gthread_active_p ()
559 : && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
560 : {
561 : return -1;
562 : }
563 :
564 : return 0;
565 : }
566 :
567 : /* Unlock the mutex */
568 : static inline int
569 : __gthread_objc_mutex_unlock (objc_mutex_t mutex)
570 : {
571 : if (__gthread_active_p ()
572 : && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
573 : {
574 : return -1;
575 : }
576 :
577 : return 0;
578 : }
579 :
580 : /* Backend condition mutex functions */
581 :
582 : /* Allocate a condition. */
583 : static inline int
584 : __gthread_objc_condition_allocate (objc_condition_t condition)
585 : {
586 : if (__gthread_active_p ())
587 : {
588 : condition->backend = objc_malloc (sizeof (pthread_cond_t));
589 :
590 : if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
591 : {
592 : objc_free (condition->backend);
593 : condition->backend = NULL;
594 : return -1;
595 : }
596 : }
597 :
598 : return 0;
599 : }
600 :
601 : /* Deallocate a condition. */
602 : static inline int
603 : __gthread_objc_condition_deallocate (objc_condition_t condition)
604 : {
605 : if (__gthread_active_p ())
606 : {
607 : if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
608 : return -1;
609 :
610 : objc_free (condition->backend);
611 : condition->backend = NULL;
612 : }
613 : return 0;
614 : }
615 :
616 : /* Wait on the condition */
617 : static inline int
618 : __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
619 : {
620 : if (__gthread_active_p ())
621 : return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
622 : (pthread_mutex_t *) mutex->backend);
623 : else
624 : return 0;
625 : }
626 :
627 : /* Wake up all threads waiting on this condition. */
628 : static inline int
629 : __gthread_objc_condition_broadcast (objc_condition_t condition)
630 : {
631 : if (__gthread_active_p ())
632 : return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
633 : else
634 : return 0;
635 : }
636 :
637 : /* Wake up one thread waiting on this condition. */
638 : static inline int
639 : __gthread_objc_condition_signal (objc_condition_t condition)
640 : {
641 : if (__gthread_active_p ())
642 : return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
643 : else
644 : return 0;
645 : }
646 :
647 : #else /* _LIBOBJC */
648 :
649 : static inline int
650 : __gthread_once (__gthread_once_t *once, void (*func) (void))
651 : {
652 : if (__gthread_active_p ())
653 : return __gthrw_(pthread_once) (once, func);
654 : else
655 : return -1;
656 : }
657 :
658 : static inline int
659 : __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
660 : {
661 : return __gthrw_(pthread_key_create) (key, dtor);
662 : }
663 :
664 : static inline int
665 : __gthread_key_delete (__gthread_key_t key)
666 : {
667 : return __gthrw_(pthread_key_delete) (key);
668 : }
669 :
670 : static inline void *
671 : __gthread_getspecific (__gthread_key_t key)
672 : {
673 : return __gthrw_(pthread_getspecific) (key);
674 : }
675 :
676 : static inline int
677 : __gthread_setspecific (__gthread_key_t key, const void *ptr)
678 : {
679 : return __gthrw_(pthread_setspecific) (key, ptr);
680 : }
681 :
682 : static inline int
683 : __gthread_mutex_lock (__gthread_mutex_t *mutex)
684 : {
685 : if (__gthread_active_p ())
686 : return __gthrw_(pthread_mutex_lock) (mutex);
687 : else
688 : return 0;
689 : }
690 :
691 : static inline int
692 : __gthread_mutex_trylock (__gthread_mutex_t *mutex)
693 : {
694 : if (__gthread_active_p ())
695 : return __gthrw_(pthread_mutex_trylock) (mutex);
696 : else
697 : return 0;
698 : }
699 :
700 : static inline int
701 : __gthread_mutex_unlock (__gthread_mutex_t *mutex)
702 : {
703 : if (__gthread_active_p ())
704 : return __gthrw_(pthread_mutex_unlock) (mutex);
705 : else
706 : return 0;
707 : }
708 :
709 : #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
710 : static inline int
711 : __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
712 : {
713 : if (__gthread_active_p ())
714 : {
715 : pthread_mutexattr_t attr;
716 : int r;
717 :
718 : r = __gthrw_(pthread_mutexattr_init) (&attr);
719 : if (!r)
720 : r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
721 : if (!r)
722 : r = __gthrw_(pthread_mutex_init) (mutex, &attr);
723 : if (!r)
724 : r = __gthrw_(pthread_mutexattr_destroy) (&attr);
725 : return r;
726 : }
727 : return 0;
728 : }
729 : #endif
730 :
731 : static inline int
732 : __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
733 : {
734 : return __gthread_mutex_lock (mutex);
735 : }
736 :
737 : static inline int
738 : __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
739 : {
740 : return __gthread_mutex_trylock (mutex);
741 : }
742 :
743 : static inline int
744 : __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
745 : {
746 : return __gthread_mutex_unlock (mutex);
747 : }
748 :
749 : static inline int
750 : __gthread_cond_broadcast (__gthread_cond_t *cond)
751 : {
752 : return __gthrw_(pthread_cond_broadcast) (cond);
753 : }
754 :
755 : static inline int
756 : __gthread_cond_wait (__gthread_cond_t *cond, __gthread_mutex_t *mutex)
757 : {
758 : return __gthrw_(pthread_cond_wait) (cond, mutex);
759 : }
760 :
761 : static inline int
762 : __gthread_cond_wait_recursive (__gthread_cond_t *cond,
763 : __gthread_recursive_mutex_t *mutex)
764 : {
765 : return __gthread_cond_wait (cond, mutex);
766 : }
767 :
768 : #endif /* _LIBOBJC */
769 :
770 : #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */
|