gthr-default.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
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 # define __gthrw2(name,name2,type) \
00063   extern __typeof(type) name __attribute__ ((__weakref__(#name2)));
00064 # define __gthrw_(name) __gthrw_ ## name
00065 #else
00066 # define __gthrw2(name,name2,type)
00067 # define __gthrw_(name) name
00068 #endif
00069 
00070 /* Typically, __gthrw_foo is a weak reference to symbol foo.  */
00071 #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
00072 
00073 /* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
00074    map a subset of the POSIX pthread API to mangled versions of their
00075    names.  */
00076 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
00077 #define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
00078 __gthrw3(pthread_once)
00079 __gthrw3(pthread_getspecific)
00080 __gthrw3(pthread_setspecific)
00081 __gthrw3(pthread_create)
00082 __gthrw3(pthread_cancel)
00083 __gthrw3(pthread_mutex_lock)
00084 __gthrw3(pthread_mutex_trylock)
00085 __gthrw3(pthread_mutex_unlock)
00086 __gthrw3(pthread_mutex_init)
00087 #else
00088 __gthrw(pthread_once)
00089 __gthrw(pthread_getspecific)
00090 __gthrw(pthread_setspecific)
00091 __gthrw(pthread_create)
00092 __gthrw(pthread_cancel)
00093 __gthrw(pthread_mutex_lock)
00094 __gthrw(pthread_mutex_trylock)
00095 __gthrw(pthread_mutex_unlock)
00096 __gthrw(pthread_mutex_init)
00097 #endif
00098 
00099 __gthrw(pthread_key_create)
00100 __gthrw(pthread_key_delete)
00101 __gthrw(pthread_mutexattr_init)
00102 __gthrw(pthread_mutexattr_settype)
00103 __gthrw(pthread_mutexattr_destroy)
00104 
00105 
00106 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
00107 /* Objective-C.  */
00108 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
00109 __gthrw3(pthread_cond_broadcast)
00110 __gthrw3(pthread_cond_destroy)
00111 __gthrw3(pthread_cond_init)
00112 __gthrw3(pthread_cond_signal)
00113 __gthrw3(pthread_cond_wait)
00114 __gthrw3(pthread_exit)
00115 __gthrw3(pthread_mutex_destroy)
00116 __gthrw3(pthread_self)
00117 #else
00118 __gthrw(pthread_cond_broadcast)
00119 __gthrw(pthread_cond_destroy)
00120 __gthrw(pthread_cond_init)
00121 __gthrw(pthread_cond_signal)
00122 __gthrw(pthread_cond_wait)
00123 __gthrw(pthread_exit)
00124 __gthrw(pthread_mutex_destroy)
00125 __gthrw(pthread_self)
00126 #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
00127 #ifdef _POSIX_PRIORITY_SCHEDULING
00128 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00129 __gthrw(sched_get_priority_max)
00130 __gthrw(sched_get_priority_min)
00131 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00132 #endif /* _POSIX_PRIORITY_SCHEDULING */
00133 __gthrw(sched_yield)
00134 __gthrw(pthread_attr_destroy)
00135 __gthrw(pthread_attr_init)
00136 __gthrw(pthread_attr_setdetachstate)
00137 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00138 __gthrw(pthread_getschedparam)
00139 __gthrw(pthread_setschedparam)
00140 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00141 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
00142 
00143 #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
00144 
00145 static inline int
00146 __gthread_active_p (void)
00147 {
00148   static void *const __gthread_active_ptr 
00149     = __extension__ (void *) &__gthrw_(pthread_cancel);
00150   return __gthread_active_ptr != 0;
00151 }
00152 
00153 #else /* not __GXX_WEAK__ */
00154 
00155 static inline int
00156 __gthread_active_p (void)
00157 {
00158   return 1;
00159 }
00160 
00161 #endif /* __GXX_WEAK__ */
00162 
00163 #ifdef _LIBOBJC
00164 
00165 /* This is the config.h file in libobjc/ */
00166 #include <config.h>
00167 
00168 #ifdef HAVE_SCHED_H
00169 # include <sched.h>
00170 #endif
00171 
00172 /* Key structure for maintaining thread specific storage */
00173 static pthread_key_t _objc_thread_storage;
00174 static pthread_attr_t _objc_thread_attribs;
00175 
00176 /* Thread local storage for a single thread */
00177 static void *thread_local_storage = NULL;
00178 
00179 /* Backend initialization functions */
00180 
00181 /* Initialize the threads subsystem.  */
00182 static inline int
00183 __gthread_objc_init_thread_system (void)
00184 {
00185   if (__gthread_active_p ())
00186     {
00187       /* Initialize the thread storage key.  */
00188       if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
00189     {
00190       /* The normal default detach state for threads is
00191        * PTHREAD_CREATE_JOINABLE which causes threads to not die
00192        * when you think they should.  */
00193       if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
00194           && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
00195                           PTHREAD_CREATE_DETACHED) == 0)
00196         return 0;
00197     }
00198     }
00199 
00200   return -1;
00201 }
00202 
00203 /* Close the threads subsystem.  */
00204 static inline int
00205 __gthread_objc_close_thread_system (void)
00206 {
00207   if (__gthread_active_p ()
00208       && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
00209       && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
00210     return 0;
00211 
00212   return -1;
00213 }
00214 
00215 /* Backend thread functions */
00216 
00217 /* Create a new thread of execution.  */
00218 static inline objc_thread_t
00219 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
00220 {
00221   objc_thread_t thread_id;
00222   pthread_t new_thread_handle;
00223 
00224   if (!__gthread_active_p ())
00225     return NULL;
00226 
00227   if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
00228     thread_id = (objc_thread_t) new_thread_handle;
00229   else
00230     thread_id = NULL;
00231 
00232   return thread_id;
00233 }
00234 
00235 /* Set the current thread's priority.  */
00236 static inline int
00237 __gthread_objc_thread_set_priority (int priority)
00238 {
00239   if (!__gthread_active_p ())
00240     return -1;
00241   else
00242     {
00243 #ifdef _POSIX_PRIORITY_SCHEDULING
00244 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00245       pthread_t thread_id = __gthrw_(pthread_self) ();
00246       int policy;
00247       struct sched_param params;
00248       int priority_min, priority_max;
00249 
00250       if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
00251     {
00252       if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
00253         return -1;
00254 
00255       if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
00256         return -1;
00257 
00258       if (priority > priority_max)
00259         priority = priority_max;
00260       else if (priority < priority_min)
00261         priority = priority_min;
00262       params.sched_priority = priority;
00263 
00264       /*
00265        * The solaris 7 and several other man pages incorrectly state that
00266        * this should be a pointer to policy but pthread.h is universally
00267        * at odds with this.
00268        */
00269       if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
00270         return 0;
00271     }
00272 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00273 #endif /* _POSIX_PRIORITY_SCHEDULING */
00274       return -1;
00275     }
00276 }
00277 
00278 /* Return the current thread's priority.  */
00279 static inline int
00280 __gthread_objc_thread_get_priority (void)
00281 {
00282 #ifdef _POSIX_PRIORITY_SCHEDULING
00283 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00284   if (__gthread_active_p ())
00285     {
00286       int policy;
00287       struct sched_param params;
00288 
00289       if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
00290     return params.sched_priority;
00291       else
00292     return -1;
00293     }
00294   else
00295 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00296 #endif /* _POSIX_PRIORITY_SCHEDULING */
00297     return OBJC_THREAD_INTERACTIVE_PRIORITY;
00298 }
00299 
00300 /* Yield our process time to another thread.  */
00301 static inline void
00302 __gthread_objc_thread_yield (void)
00303 {
00304   if (__gthread_active_p ())
00305     __gthrw_(sched_yield) ();
00306 }
00307 
00308 /* Terminate the current thread.  */
00309 static inline int
00310 __gthread_objc_thread_exit (void)
00311 {
00312   if (__gthread_active_p ())
00313     /* exit the thread */
00314     __gthrw_(pthread_exit) (&__objc_thread_exit_status);
00315 
00316   /* Failed if we reached here */
00317   return -1;
00318 }
00319 
00320 /* Returns an integer value which uniquely describes a thread.  */
00321 static inline objc_thread_t
00322 __gthread_objc_thread_id (void)
00323 {
00324   if (__gthread_active_p ())
00325     return (objc_thread_t) __gthrw_(pthread_self) ();
00326   else
00327     return (objc_thread_t) 1;
00328 }
00329 
00330 /* Sets the thread's local storage pointer.  */
00331 static inline int
00332 __gthread_objc_thread_set_data (void *value)
00333 {
00334   if (__gthread_active_p ())
00335     return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
00336   else
00337     {
00338       thread_local_storage = value;
00339       return 0;
00340     }
00341 }
00342 
00343 /* Returns the thread's local storage pointer.  */
00344 static inline void *
00345 __gthread_objc_thread_get_data (void)
00346 {
00347   if (__gthread_active_p ())
00348     return __gthrw_(pthread_getspecific) (_objc_thread_storage);
00349   else
00350     return thread_local_storage;
00351 }
00352 
00353 /* Backend mutex functions */
00354 
00355 /* Allocate a mutex.  */
00356 static inline int
00357 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
00358 {
00359   if (__gthread_active_p ())
00360     {
00361       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
00362 
00363       if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
00364     {
00365       objc_free (mutex->backend);
00366       mutex->backend = NULL;
00367       return -1;
00368     }
00369     }
00370 
00371   return 0;
00372 }
00373 
00374 /* Deallocate a mutex.  */
00375 static inline int
00376 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
00377 {
00378   if (__gthread_active_p ())
00379     {
00380       int count;
00381 
00382       /*
00383        * Posix Threads specifically require that the thread be unlocked
00384        * for __gthrw_(pthread_mutex_destroy) to work.
00385        */
00386 
00387       do
00388     {
00389       count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
00390       if (count < 0)
00391         return -1;
00392     }
00393       while (count);
00394 
00395       if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
00396     return -1;
00397 
00398       objc_free (mutex->backend);
00399       mutex->backend = NULL;
00400     }
00401   return 0;
00402 }
00403 
00404 /* Grab a lock on a mutex.  */
00405 static inline int
00406 __gthread_objc_mutex_lock (objc_mutex_t mutex)
00407 {
00408   if (__gthread_active_p ()
00409       && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
00410     {
00411       return -1;
00412     }
00413 
00414   return 0;
00415 }
00416 
00417 /* Try to grab a lock on a mutex.  */
00418 static inline int
00419 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
00420 {
00421   if (__gthread_active_p ()
00422       && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
00423     {
00424       return -1;
00425     }
00426 
00427   return 0;
00428 }
00429 
00430 /* Unlock the mutex */
00431 static inline int
00432 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
00433 {
00434   if (__gthread_active_p ()
00435       && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
00436     {
00437       return -1;
00438     }
00439 
00440   return 0;
00441 }
00442 
00443 /* Backend condition mutex functions */
00444 
00445 /* Allocate a condition.  */
00446 static inline int
00447 __gthread_objc_condition_allocate (objc_condition_t condition)
00448 {
00449   if (__gthread_active_p ())
00450     {
00451       condition->backend = objc_malloc (sizeof (pthread_cond_t));
00452 
00453       if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
00454     {
00455       objc_free (condition->backend);
00456       condition->backend = NULL;
00457       return -1;
00458     }
00459     }
00460 
00461   return 0;
00462 }
00463 
00464 /* Deallocate a condition.  */
00465 static inline int
00466 __gthread_objc_condition_deallocate (objc_condition_t condition)
00467 {
00468   if (__gthread_active_p ())
00469     {
00470       if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
00471     return -1;
00472 
00473       objc_free (condition->backend);
00474       condition->backend = NULL;
00475     }
00476   return 0;
00477 }
00478 
00479 /* Wait on the condition */
00480 static inline int
00481 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
00482 {
00483   if (__gthread_active_p ())
00484     return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
00485                   (pthread_mutex_t *) mutex->backend);
00486   else
00487     return 0;
00488 }
00489 
00490 /* Wake up all threads waiting on this condition.  */
00491 static inline int
00492 __gthread_objc_condition_broadcast (objc_condition_t condition)
00493 {
00494   if (__gthread_active_p ())
00495     return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
00496   else
00497     return 0;
00498 }
00499 
00500 /* Wake up one thread waiting on this condition.  */
00501 static inline int
00502 __gthread_objc_condition_signal (objc_condition_t condition)
00503 {
00504   if (__gthread_active_p ())
00505     return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
00506   else
00507     return 0;
00508 }
00509 
00510 #else /* _LIBOBJC */
00511 
00512 static inline int
00513 __gthread_once (__gthread_once_t *once, void (*func) (void))
00514 {
00515   if (__gthread_active_p ())
00516     return __gthrw_(pthread_once) (once, func);
00517   else
00518     return -1;
00519 }
00520 
00521 static inline int
00522 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
00523 {
00524   return __gthrw_(pthread_key_create) (key, dtor);
00525 }
00526 
00527 static inline int
00528 __gthread_key_delete (__gthread_key_t key)
00529 {
00530   return __gthrw_(pthread_key_delete) (key);
00531 }
00532 
00533 static inline void *
00534 __gthread_getspecific (__gthread_key_t key)
00535 {
00536   return __gthrw_(pthread_getspecific) (key);
00537 }
00538 
00539 static inline int
00540 __gthread_setspecific (__gthread_key_t key, const void *ptr)
00541 {
00542   return __gthrw_(pthread_setspecific) (key, ptr);
00543 }
00544 
00545 static inline int
00546 __gthread_mutex_lock (__gthread_mutex_t *mutex)
00547 {
00548   if (__gthread_active_p ())
00549     return __gthrw_(pthread_mutex_lock) (mutex);
00550   else
00551     return 0;
00552 }
00553 
00554 static inline int
00555 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
00556 {
00557   if (__gthread_active_p ())
00558     return __gthrw_(pthread_mutex_trylock) (mutex);
00559   else
00560     return 0;
00561 }
00562 
00563 static inline int
00564 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
00565 {
00566   if (__gthread_active_p ())
00567     return __gthrw_(pthread_mutex_unlock) (mutex);
00568   else
00569     return 0;
00570 }
00571 
00572 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00573 static inline int
00574 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
00575 {
00576   if (__gthread_active_p ())
00577     {
00578       pthread_mutexattr_t attr;
00579       int r;
00580 
00581       r = __gthrw_(pthread_mutexattr_init) (&attr);
00582       if (!r)
00583     r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
00584       if (!r)
00585     r = __gthrw_(pthread_mutex_init) (mutex, &attr);
00586       if (!r)
00587     r = __gthrw_(pthread_mutexattr_destroy) (&attr);
00588       return r;
00589     }
00590   return 0;
00591 }
00592 #endif
00593 
00594 static inline int
00595 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
00596 {
00597   return __gthread_mutex_lock (mutex);
00598 }
00599 
00600 static inline int
00601 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
00602 {
00603   return __gthread_mutex_trylock (mutex);
00604 }
00605 
00606 static inline int
00607 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
00608 {
00609   return __gthread_mutex_unlock (mutex);
00610 }
00611 
00612 #endif /* _LIBOBJC */
00613 
00614 #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */

Generated on Sat Mar 3 02:48:02 2007 for libstdc++ by  doxygen 1.5.1