OSDN Git Service

PR c/35652
[pf3gnuchains/gcc-fork.git] / gcc / gthr-posix.h
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 GCC_GTHR_POSIX_H
31 #define 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 SUPPORTS_WEAK && 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_mutex_destroy)
98 __gthrw3(pthread_cond_broadcast)
99 __gthrw3(pthread_cond_wait)
100 #else
101 __gthrw(pthread_once)
102 __gthrw(pthread_getspecific)
103 __gthrw(pthread_setspecific)
104 __gthrw(pthread_create)
105 __gthrw(pthread_cancel)
106 __gthrw(pthread_mutex_lock)
107 __gthrw(pthread_mutex_trylock)
108 __gthrw(pthread_mutex_unlock)
109 __gthrw(pthread_mutex_init)
110 __gthrw(pthread_mutex_destroy)
111 __gthrw(pthread_cond_broadcast)
112 __gthrw(pthread_cond_wait)
113 #endif
114
115 __gthrw(pthread_key_create)
116 __gthrw(pthread_key_delete)
117 __gthrw(pthread_mutexattr_init)
118 __gthrw(pthread_mutexattr_settype)
119 __gthrw(pthread_mutexattr_destroy)
120
121
122 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
123 /* Objective-C.  */
124 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
125 __gthrw3(pthread_cond_destroy)
126 __gthrw3(pthread_cond_init)
127 __gthrw3(pthread_cond_signal)
128 __gthrw3(pthread_exit)
129 __gthrw3(pthread_self)
130 #else
131 __gthrw(pthread_cond_destroy)
132 __gthrw(pthread_cond_init)
133 __gthrw(pthread_cond_signal)
134 __gthrw(pthread_exit)
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 SUPPORTS_WEAK && 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 __gthread_active_p (void)
213 {
214   static void *const __gthread_active_ptr 
215     = __extension__ (void *) &__gthrw_(pthread_cancel);
216   return __gthread_active_ptr != 0;
217 }
218
219 #endif /* FreeBSD or Solaris */
220
221 #else /* not SUPPORTS_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 /* SUPPORTS_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, &params) == 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, &params) == 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, &params) == 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_destroy (__gthread_mutex_t *mutex)
684 {
685   if (__gthread_active_p ())
686     return __gthrw_(pthread_mutex_destroy) (mutex);
687   else
688     return 0;
689 }
690
691 static inline int
692 __gthread_mutex_lock (__gthread_mutex_t *mutex)
693 {
694   if (__gthread_active_p ())
695     return __gthrw_(pthread_mutex_lock) (mutex);
696   else
697     return 0;
698 }
699
700 static inline int
701 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
702 {
703   if (__gthread_active_p ())
704     return __gthrw_(pthread_mutex_trylock) (mutex);
705   else
706     return 0;
707 }
708
709 static inline int
710 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
711 {
712   if (__gthread_active_p ())
713     return __gthrw_(pthread_mutex_unlock) (mutex);
714   else
715     return 0;
716 }
717
718 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
719 static inline int
720 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
721 {
722   if (__gthread_active_p ())
723     {
724       pthread_mutexattr_t attr;
725       int r;
726
727       r = __gthrw_(pthread_mutexattr_init) (&attr);
728       if (!r)
729         r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
730       if (!r)
731         r = __gthrw_(pthread_mutex_init) (mutex, &attr);
732       if (!r)
733         r = __gthrw_(pthread_mutexattr_destroy) (&attr);
734       return r;
735     }
736   return 0;
737 }
738 #endif
739
740 static inline int
741 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
742 {
743   return __gthread_mutex_lock (mutex);
744 }
745
746 static inline int
747 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
748 {
749   return __gthread_mutex_trylock (mutex);
750 }
751
752 static inline int
753 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
754 {
755   return __gthread_mutex_unlock (mutex);
756 }
757
758 static inline int
759 __gthread_cond_broadcast (__gthread_cond_t *cond)
760 {
761   return __gthrw_(pthread_cond_broadcast) (cond);
762 }
763
764 static inline int
765 __gthread_cond_wait (__gthread_cond_t *cond, __gthread_mutex_t *mutex)
766 {
767   return __gthrw_(pthread_cond_wait) (cond, mutex);
768 }
769
770 static inline int
771 __gthread_cond_wait_recursive (__gthread_cond_t *cond,
772                                __gthread_recursive_mutex_t *mutex)
773 {
774   return __gthread_cond_wait (cond, mutex);
775 }
776
777 #endif /* _LIBOBJC */
778
779 #endif /* ! GCC_GTHR_POSIX_H */