OSDN Git Service

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