gthr-posix.h

00001 /* Threads compatibility routines for libgcc2 and libobjc.  */
00002 /* Compile this one with gcc.  */
00003 /* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00004    Free Software Foundation, Inc.
00005 
00006 This file is part of GCC.
00007 
00008 GCC is free software; you can redistribute it and/or modify it under
00009 the terms of the GNU General Public License as published by the Free
00010 Software Foundation; either version 2, or (at your option) any later
00011 version.
00012 
00013 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
00014 WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with GCC; see the file COPYING.  If not, write to the Free
00020 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
00021 02110-1301, USA.  */
00022 
00023 /* As a special exception, if you link this library with other files,
00024    some of which are compiled with GCC, to produce an executable,
00025    this library does not by itself cause the resulting executable
00026    to be covered by the GNU General Public License.
00027    This exception does not however invalidate any other reasons why
00028    the executable file might be covered by the GNU General Public License.  */
00029 
00030 #ifndef _GLIBCXX_GCC_GTHR_POSIX_H
00031 #define _GLIBCXX_GCC_GTHR_POSIX_H
00032 
00033 /* POSIX threads specific definitions.
00034    Easy, since the interface is just one-to-one mapping.  */
00035 
00036 #define __GTHREADS 1
00037 
00038 /* Some implementations of <pthread.h> require this to be defined.  */
00039 #if !defined(_REENTRANT) && defined(__osf__)
00040 #define _REENTRANT 1
00041 #endif
00042 
00043 #include <pthread.h>
00044 #include <unistd.h>
00045 
00046 typedef pthread_key_t __gthread_key_t;
00047 typedef pthread_once_t __gthread_once_t;
00048 typedef pthread_mutex_t __gthread_mutex_t;
00049 typedef pthread_mutex_t __gthread_recursive_mutex_t;
00050 
00051 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
00052 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
00053 #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
00054 #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
00055 #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
00056 #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00057 #else
00058 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
00059 #endif
00060 
00061 #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
00062 # ifndef __gthrw_pragma
00063 #  define __gthrw_pragma(pragma)
00064 # endif
00065 # define __gthrw2(name,name2,type) \
00066   static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
00067   __gthrw_pragma(weak type)
00068 # define __gthrw_(name) __gthrw_ ## name
00069 #else
00070 # define __gthrw2(name,name2,type)
00071 # define __gthrw_(name) name
00072 #endif
00073 
00074 /* Typically, __gthrw_foo is a weak reference to symbol foo.  */
00075 #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
00076 
00077 /* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
00078    map a subset of the POSIX pthread API to mangled versions of their
00079    names.  */
00080 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
00081 #define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
00082 __gthrw3(pthread_once)
00083 __gthrw3(pthread_getspecific)
00084 __gthrw3(pthread_setspecific)
00085 __gthrw3(pthread_create)
00086 __gthrw3(pthread_cancel)
00087 __gthrw3(pthread_mutex_lock)
00088 __gthrw3(pthread_mutex_trylock)
00089 __gthrw3(pthread_mutex_unlock)
00090 __gthrw3(pthread_mutex_init)
00091 #else
00092 __gthrw(pthread_once)
00093 __gthrw(pthread_getspecific)
00094 __gthrw(pthread_setspecific)
00095 __gthrw(pthread_create)
00096 __gthrw(pthread_cancel)
00097 __gthrw(pthread_mutex_lock)
00098 __gthrw(pthread_mutex_trylock)
00099 __gthrw(pthread_mutex_unlock)
00100 __gthrw(pthread_mutex_init)
00101 #endif
00102 
00103 __gthrw(pthread_key_create)
00104 __gthrw(pthread_key_delete)
00105 __gthrw(pthread_mutexattr_init)
00106 __gthrw(pthread_mutexattr_settype)
00107 __gthrw(pthread_mutexattr_destroy)
00108 
00109 
00110 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
00111 /* Objective-C.  */
00112 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
00113 __gthrw3(pthread_cond_broadcast)
00114 __gthrw3(pthread_cond_destroy)
00115 __gthrw3(pthread_cond_init)
00116 __gthrw3(pthread_cond_signal)
00117 __gthrw3(pthread_cond_wait)
00118 __gthrw3(pthread_exit)
00119 __gthrw3(pthread_mutex_destroy)
00120 __gthrw3(pthread_self)
00121 #else
00122 __gthrw(pthread_cond_broadcast)
00123 __gthrw(pthread_cond_destroy)
00124 __gthrw(pthread_cond_init)
00125 __gthrw(pthread_cond_signal)
00126 __gthrw(pthread_cond_wait)
00127 __gthrw(pthread_exit)
00128 __gthrw(pthread_mutex_destroy)
00129 __gthrw(pthread_self)
00130 #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
00131 #ifdef _POSIX_PRIORITY_SCHEDULING
00132 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00133 __gthrw(sched_get_priority_max)
00134 __gthrw(sched_get_priority_min)
00135 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00136 #endif /* _POSIX_PRIORITY_SCHEDULING */
00137 __gthrw(sched_yield)
00138 __gthrw(pthread_attr_destroy)
00139 __gthrw(pthread_attr_init)
00140 __gthrw(pthread_attr_setdetachstate)
00141 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00142 __gthrw(pthread_getschedparam)
00143 __gthrw(pthread_setschedparam)
00144 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00145 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
00146 
00147 #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
00148 
00149 /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
00150    -pthreads is not specified.  The functions are dummies and most return an
00151    error value.  However pthread_once returns 0 without invoking the routine
00152    it is passed so we cannot pretend that the interface is active if -pthreads
00153    is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
00154    we need to play the usual game with weak symbols.  On Solaris 10 and up, a
00155    working interface is always exposed.  */
00156 
00157 #if defined(__sun) && defined(__svr4__)
00158 
00159 static volatile int __gthread_active = -1;
00160 
00161 static void
00162 __gthread_trigger (void)
00163 {
00164   __gthread_active = 1;
00165 }
00166 
00167 static inline int
00168 __gthread_active_p (void)
00169 {
00170   static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
00171   static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
00172 
00173   /* Avoid reading __gthread_active twice on the main code path.  */
00174   int __gthread_active_latest_value = __gthread_active;
00175 
00176   /* This test is not protected to avoid taking a lock on the main code
00177      path so every update of __gthread_active in a threaded program must
00178      be atomic with regard to the result of the test.  */
00179   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
00180     {
00181       if (__gthrw_(pthread_once))
00182     {
00183       /* If this really is a threaded program, then we must ensure that
00184          __gthread_active has been set to 1 before exiting this block.  */
00185       __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
00186       __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
00187       __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
00188     }
00189 
00190       /* Make sure we'll never enter this block again.  */
00191       if (__gthread_active < 0)
00192     __gthread_active = 0;
00193 
00194       __gthread_active_latest_value = __gthread_active;
00195     }
00196 
00197   return __gthread_active_latest_value != 0;
00198 }
00199 
00200 #else /* not Solaris */
00201 
00202 static inline int
00203 __gthread_active_p (void)
00204 {
00205   static void *const __gthread_active_ptr 
00206     = __extension__ (void *) &__gthrw_(pthread_cancel);
00207   return __gthread_active_ptr != 0;
00208 }
00209 
00210 #endif /* Solaris */
00211 
00212 #else /* not __GXX_WEAK__ */
00213 
00214 static inline int
00215 __gthread_active_p (void)
00216 {
00217   return 1;
00218 }
00219 
00220 #endif /* __GXX_WEAK__ */
00221 
00222 #ifdef _LIBOBJC
00223 
00224 /* This is the config.h file in libobjc/ */
00225 #include <config.h>
00226 
00227 #ifdef HAVE_SCHED_H
00228 # include <sched.h>
00229 #endif
00230 
00231 /* Key structure for maintaining thread specific storage */
00232 static pthread_key_t _objc_thread_storage;
00233 static pthread_attr_t _objc_thread_attribs;
00234 
00235 /* Thread local storage for a single thread */
00236 static void *thread_local_storage = NULL;
00237 
00238 /* Backend initialization functions */
00239 
00240 /* Initialize the threads subsystem.  */
00241 static inline int
00242 __gthread_objc_init_thread_system (void)
00243 {
00244   if (__gthread_active_p ())
00245     {
00246       /* Initialize the thread storage key.  */
00247       if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
00248     {
00249       /* The normal default detach state for threads is
00250        * PTHREAD_CREATE_JOINABLE which causes threads to not die
00251        * when you think they should.  */
00252       if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
00253           && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
00254                           PTHREAD_CREATE_DETACHED) == 0)
00255         return 0;
00256     }
00257     }
00258 
00259   return -1;
00260 }
00261 
00262 /* Close the threads subsystem.  */
00263 static inline int
00264 __gthread_objc_close_thread_system (void)
00265 {
00266   if (__gthread_active_p ()
00267       && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
00268       && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
00269     return 0;
00270 
00271   return -1;
00272 }
00273 
00274 /* Backend thread functions */
00275 
00276 /* Create a new thread of execution.  */
00277 static inline objc_thread_t
00278 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
00279 {
00280   objc_thread_t thread_id;
00281   pthread_t new_thread_handle;
00282 
00283   if (!__gthread_active_p ())
00284     return NULL;
00285 
00286   if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
00287     thread_id = (objc_thread_t) new_thread_handle;
00288   else
00289     thread_id = NULL;
00290 
00291   return thread_id;
00292 }
00293 
00294 /* Set the current thread's priority.  */
00295 static inline int
00296 __gthread_objc_thread_set_priority (int priority)
00297 {
00298   if (!__gthread_active_p ())
00299     return -1;
00300   else
00301     {
00302 #ifdef _POSIX_PRIORITY_SCHEDULING
00303 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00304       pthread_t thread_id = __gthrw_(pthread_self) ();
00305       int policy;
00306       struct sched_param params;
00307       int priority_min, priority_max;
00308 
00309       if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
00310     {
00311       if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
00312         return -1;
00313 
00314       if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
00315         return -1;
00316 
00317       if (priority > priority_max)
00318         priority = priority_max;
00319       else if (priority < priority_min)
00320         priority = priority_min;
00321       params.sched_priority = priority;
00322 
00323       /*
00324        * The solaris 7 and several other man pages incorrectly state that
00325        * this should be a pointer to policy but pthread.h is universally
00326        * at odds with this.
00327        */
00328       if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
00329         return 0;
00330     }
00331 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00332 #endif /* _POSIX_PRIORITY_SCHEDULING */
00333       return -1;
00334     }
00335 }
00336 
00337 /* Return the current thread's priority.  */
00338 static inline int
00339 __gthread_objc_thread_get_priority (void)
00340 {
00341 #ifdef _POSIX_PRIORITY_SCHEDULING
00342 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00343   if (__gthread_active_p ())
00344     {
00345       int policy;
00346       struct sched_param params;
00347 
00348       if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
00349     return params.sched_priority;
00350       else
00351     return -1;
00352     }
00353   else
00354 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00355 #endif /* _POSIX_PRIORITY_SCHEDULING */
00356     return OBJC_THREAD_INTERACTIVE_PRIORITY;
00357 }
00358 
00359 /* Yield our process time to another thread.  */
00360 static inline void
00361 __gthread_objc_thread_yield (void)
00362 {
00363   if (__gthread_active_p ())
00364     __gthrw_(sched_yield) ();
00365 }
00366 
00367 /* Terminate the current thread.  */
00368 static inline int
00369 __gthread_objc_thread_exit (void)
00370 {
00371   if (__gthread_active_p ())
00372     /* exit the thread */
00373     __gthrw_(pthread_exit) (&__objc_thread_exit_status);
00374 
00375   /* Failed if we reached here */
00376   return -1;
00377 }
00378 
00379 /* Returns an integer value which uniquely describes a thread.  */
00380 static inline objc_thread_t
00381 __gthread_objc_thread_id (void)
00382 {
00383   if (__gthread_active_p ())
00384     return (objc_thread_t) __gthrw_(pthread_self) ();
00385   else
00386     return (objc_thread_t) 1;
00387 }
00388 
00389 /* Sets the thread's local storage pointer.  */
00390 static inline int
00391 __gthread_objc_thread_set_data (void *value)
00392 {
00393   if (__gthread_active_p ())
00394     return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
00395   else
00396     {
00397       thread_local_storage = value;
00398       return 0;
00399     }
00400 }
00401 
00402 /* Returns the thread's local storage pointer.  */
00403 static inline void *
00404 __gthread_objc_thread_get_data (void)
00405 {
00406   if (__gthread_active_p ())
00407     return __gthrw_(pthread_getspecific) (_objc_thread_storage);
00408   else
00409     return thread_local_storage;
00410 }
00411 
00412 /* Backend mutex functions */
00413 
00414 /* Allocate a mutex.  */
00415 static inline int
00416 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
00417 {
00418   if (__gthread_active_p ())
00419     {
00420       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
00421 
00422       if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
00423     {
00424       objc_free (mutex->backend);
00425       mutex->backend = NULL;
00426       return -1;
00427     }
00428     }
00429 
00430   return 0;
00431 }
00432 
00433 /* Deallocate a mutex.  */
00434 static inline int
00435 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
00436 {
00437   if (__gthread_active_p ())
00438     {
00439       int count;
00440 
00441       /*
00442        * Posix Threads specifically require that the thread be unlocked
00443        * for __gthrw_(pthread_mutex_destroy) to work.
00444        */
00445 
00446       do
00447     {
00448       count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
00449       if (count < 0)
00450         return -1;
00451     }
00452       while (count);
00453 
00454       if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
00455     return -1;
00456 
00457       objc_free (mutex->backend);
00458       mutex->backend = NULL;
00459     }
00460   return 0;
00461 }
00462 
00463 /* Grab a lock on a mutex.  */
00464 static inline int
00465 __gthread_objc_mutex_lock (objc_mutex_t mutex)
00466 {
00467   if (__gthread_active_p ()
00468       && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
00469     {
00470       return -1;
00471     }
00472 
00473   return 0;
00474 }
00475 
00476 /* Try to grab a lock on a mutex.  */
00477 static inline int
00478 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
00479 {
00480   if (__gthread_active_p ()
00481       && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
00482     {
00483       return -1;
00484     }
00485 
00486   return 0;
00487 }
00488 
00489 /* Unlock the mutex */
00490 static inline int
00491 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
00492 {
00493   if (__gthread_active_p ()
00494       && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
00495     {
00496       return -1;
00497     }
00498 
00499   return 0;
00500 }
00501 
00502 /* Backend condition mutex functions */
00503 
00504 /* Allocate a condition.  */
00505 static inline int
00506 __gthread_objc_condition_allocate (objc_condition_t condition)
00507 {
00508   if (__gthread_active_p ())
00509     {
00510       condition->backend = objc_malloc (sizeof (pthread_cond_t));
00511 
00512       if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
00513     {
00514       objc_free (condition->backend);
00515       condition->backend = NULL;
00516       return -1;
00517     }
00518     }
00519 
00520   return 0;
00521 }
00522 
00523 /* Deallocate a condition.  */
00524 static inline int
00525 __gthread_objc_condition_deallocate (objc_condition_t condition)
00526 {
00527   if (__gthread_active_p ())
00528     {
00529       if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
00530     return -1;
00531 
00532       objc_free (condition->backend);
00533       condition->backend = NULL;
00534     }
00535   return 0;
00536 }
00537 
00538 /* Wait on the condition */
00539 static inline int
00540 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
00541 {
00542   if (__gthread_active_p ())
00543     return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
00544                   (pthread_mutex_t *) mutex->backend);
00545   else
00546     return 0;
00547 }
00548 
00549 /* Wake up all threads waiting on this condition.  */
00550 static inline int
00551 __gthread_objc_condition_broadcast (objc_condition_t condition)
00552 {
00553   if (__gthread_active_p ())
00554     return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
00555   else
00556     return 0;
00557 }
00558 
00559 /* Wake up one thread waiting on this condition.  */
00560 static inline int
00561 __gthread_objc_condition_signal (objc_condition_t condition)
00562 {
00563   if (__gthread_active_p ())
00564     return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
00565   else
00566     return 0;
00567 }
00568 
00569 #else /* _LIBOBJC */
00570 
00571 static inline int
00572 __gthread_once (__gthread_once_t *once, void (*func) (void))
00573 {
00574   if (__gthread_active_p ())
00575     return __gthrw_(pthread_once) (once, func);
00576   else
00577     return -1;
00578 }
00579 
00580 static inline int
00581 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
00582 {
00583   return __gthrw_(pthread_key_create) (key, dtor);
00584 }
00585 
00586 static inline int
00587 __gthread_key_delete (__gthread_key_t key)
00588 {
00589   return __gthrw_(pthread_key_delete) (key);
00590 }
00591 
00592 static inline void *
00593 __gthread_getspecific (__gthread_key_t key)
00594 {
00595   return __gthrw_(pthread_getspecific) (key);
00596 }
00597 
00598 static inline int
00599 __gthread_setspecific (__gthread_key_t key, const void *ptr)
00600 {
00601   return __gthrw_(pthread_setspecific) (key, ptr);
00602 }
00603 
00604 static inline int
00605 __gthread_mutex_lock (__gthread_mutex_t *mutex)
00606 {
00607   if (__gthread_active_p ())
00608     return __gthrw_(pthread_mutex_lock) (mutex);
00609   else
00610     return 0;
00611 }
00612 
00613 static inline int
00614 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
00615 {
00616   if (__gthread_active_p ())
00617     return __gthrw_(pthread_mutex_trylock) (mutex);
00618   else
00619     return 0;
00620 }
00621 
00622 static inline int
00623 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
00624 {
00625   if (__gthread_active_p ())
00626     return __gthrw_(pthread_mutex_unlock) (mutex);
00627   else
00628     return 0;
00629 }
00630 
00631 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00632 static inline int
00633 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
00634 {
00635   if (__gthread_active_p ())
00636     {
00637       pthread_mutexattr_t attr;
00638       int r;
00639 
00640       r = __gthrw_(pthread_mutexattr_init) (&attr);
00641       if (!r)
00642     r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
00643       if (!r)
00644     r = __gthrw_(pthread_mutex_init) (mutex, &attr);
00645       if (!r)
00646     r = __gthrw_(pthread_mutexattr_destroy) (&attr);
00647       return r;
00648     }
00649   return 0;
00650 }
00651 #endif
00652 
00653 static inline int
00654 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
00655 {
00656   return __gthread_mutex_lock (mutex);
00657 }
00658 
00659 static inline int
00660 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
00661 {
00662   return __gthread_mutex_trylock (mutex);
00663 }
00664 
00665 static inline int
00666 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
00667 {
00668   return __gthread_mutex_unlock (mutex);
00669 }
00670 
00671 #endif /* _LIBOBJC */
00672 
00673 #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */

Generated on Thu Nov 1 13:11:30 2007 for libstdc++ by  doxygen 1.5.1