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

Generated on Tue Dec 2 03:59:25 2008 for libstdc++ by  doxygen 1.5.7.1