gthr-default.h

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

Generated on Tue Feb 2 16:55:58 2010 for GNU C++ STL by  doxygen 1.4.7