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
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, 59 Temple Place - Suite 330, Boston, MA
00021 02111-1307, 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 #ifndef _REENTRANT
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 
00050 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
00051 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
00052 
00053 #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
00054 
00055 #pragma weak pthread_once
00056 #pragma weak pthread_key_create
00057 #pragma weak pthread_key_delete
00058 #pragma weak pthread_getspecific
00059 #pragma weak pthread_setspecific
00060 #pragma weak pthread_create
00061 
00062 #pragma weak pthread_mutex_lock
00063 #pragma weak pthread_mutex_trylock
00064 #pragma weak pthread_mutex_unlock
00065 
00066 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
00067 /* Objective-C.  */
00068 #pragma weak pthread_cond_broadcast
00069 #pragma weak pthread_cond_destroy
00070 #pragma weak pthread_cond_init
00071 #pragma weak pthread_cond_signal
00072 #pragma weak pthread_cond_wait
00073 #pragma weak pthread_exit
00074 #pragma weak pthread_mutex_init
00075 #pragma weak pthread_mutex_destroy
00076 #pragma weak pthread_self
00077 /* These really should be protected by _POSIX_PRIORITY_SCHEDULING, but
00078    we use them inside a _POSIX_THREAD_PRIORITY_SCHEDULING block.  */
00079 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00080 #pragma weak sched_get_priority_max
00081 #pragma weak sched_get_priority_min
00082 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00083 #pragma weak sched_yield
00084 #pragma weak pthread_attr_destroy
00085 #pragma weak pthread_attr_init
00086 #pragma weak pthread_attr_setdetachstate
00087 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00088 #pragma weak pthread_getschedparam
00089 #pragma weak pthread_setschedparam
00090 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00091 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
00092 
00093 static inline int
00094 __gthread_active_p (void)
00095 {
00096   static void *const __gthread_active_ptr = (void *) &pthread_create;
00097   return __gthread_active_ptr != 0;
00098 }
00099 
00100 #else /* not __GXX_WEAK__ */
00101 
00102 static inline int
00103 __gthread_active_p (void)
00104 {
00105   return 1;
00106 }
00107 
00108 #endif /* __GXX_WEAK__ */
00109 
00110 #ifdef _LIBOBJC
00111 
00112 /* This is the config.h file in libobjc/ */
00113 #include <config.h>
00114 
00115 #ifdef HAVE_SCHED_H
00116 # include <sched.h>
00117 #endif
00118 
00119 /* Key structure for maintaining thread specific storage */
00120 static pthread_key_t _objc_thread_storage;
00121 static pthread_attr_t _objc_thread_attribs;
00122 
00123 /* Thread local storage for a single thread */
00124 static void *thread_local_storage = NULL;
00125 
00126 /* Backend initialization functions */
00127 
00128 /* Initialize the threads subsystem.  */
00129 static inline int
00130 __gthread_objc_init_thread_system (void)
00131 {
00132   if (__gthread_active_p ())
00133     {
00134       /* Initialize the thread storage key */
00135       if (pthread_key_create (&_objc_thread_storage, NULL) == 0)
00136     {
00137       /* The normal default detach state for threads is
00138        * PTHREAD_CREATE_JOINABLE which causes threads to not die
00139        * when you think they should.  */
00140       if (pthread_attr_init (&_objc_thread_attribs) == 0
00141           && pthread_attr_setdetachstate (&_objc_thread_attribs,
00142                           PTHREAD_CREATE_DETACHED) == 0)
00143         return 0;
00144     }
00145     }
00146 
00147   return -1;
00148 }
00149 
00150 /* Close the threads subsystem.  */
00151 static inline int
00152 __gthread_objc_close_thread_system (void)
00153 {
00154   if (__gthread_active_p ()
00155       && pthread_key_delete (_objc_thread_storage) == 0
00156       && pthread_attr_destroy (&_objc_thread_attribs) == 0)
00157     return 0;
00158 
00159   return -1;
00160 }
00161 
00162 /* Backend thread functions */
00163 
00164 /* Create a new thread of execution.  */
00165 static inline objc_thread_t
00166 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
00167 {
00168   objc_thread_t thread_id;
00169   pthread_t new_thread_handle;
00170 
00171   if (!__gthread_active_p ())
00172     return NULL;
00173 
00174   if (!(pthread_create (&new_thread_handle, NULL, (void *) func, arg)))
00175     thread_id = (objc_thread_t) new_thread_handle;
00176   else
00177     thread_id = NULL;
00178 
00179   return thread_id;
00180 }
00181 
00182 /* Set the current thread's priority.  */
00183 static inline int
00184 __gthread_objc_thread_set_priority (int priority)
00185 {
00186   if (!__gthread_active_p ())
00187     return -1;
00188   else
00189     {
00190 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00191       pthread_t thread_id = pthread_self ();
00192       int policy;
00193       struct sched_param params;
00194       int priority_min, priority_max;
00195 
00196       if (pthread_getschedparam (thread_id, &policy, &params) == 0)
00197     {
00198       if ((priority_max = sched_get_priority_max (policy)) == -1)
00199         return -1;
00200 
00201       if ((priority_min = sched_get_priority_min (policy)) == -1)
00202         return -1;
00203 
00204       if (priority > priority_max)
00205         priority = priority_max;
00206       else if (priority < priority_min)
00207         priority = priority_min;
00208       params.sched_priority = priority;
00209 
00210       /*
00211        * The solaris 7 and several other man pages incorrectly state that
00212        * this should be a pointer to policy but pthread.h is universally
00213        * at odds with this.
00214        */
00215       if (pthread_setschedparam (thread_id, policy, &params) == 0)
00216         return 0;
00217     }
00218 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00219       return -1;
00220     }
00221 }
00222 
00223 /* Return the current thread's priority.  */
00224 static inline int
00225 __gthread_objc_thread_get_priority (void)
00226 {
00227 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
00228   if (__gthread_active_p ())
00229     {
00230       int policy;
00231       struct sched_param params;
00232 
00233       if (pthread_getschedparam (pthread_self (), &policy, &params) == 0)
00234     return params.sched_priority;
00235       else
00236     return -1;
00237     }
00238   else
00239 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
00240     return OBJC_THREAD_INTERACTIVE_PRIORITY;
00241 }
00242 
00243 /* Yield our process time to another thread.  */
00244 static inline void
00245 __gthread_objc_thread_yield (void)
00246 {
00247   if (__gthread_active_p ())
00248     sched_yield ();
00249 }
00250 
00251 /* Terminate the current thread.  */
00252 static inline int
00253 __gthread_objc_thread_exit (void)
00254 {
00255   if (__gthread_active_p ())
00256     /* exit the thread */
00257     pthread_exit (&__objc_thread_exit_status);
00258 
00259   /* Failed if we reached here */
00260   return -1;
00261 }
00262 
00263 /* Returns an integer value which uniquely describes a thread.  */
00264 static inline objc_thread_t
00265 __gthread_objc_thread_id (void)
00266 {
00267   if (__gthread_active_p ())
00268     return (objc_thread_t) pthread_self ();
00269   else
00270     return (objc_thread_t) 1;
00271 }
00272 
00273 /* Sets the thread's local storage pointer.  */
00274 static inline int
00275 __gthread_objc_thread_set_data (void *value)
00276 {
00277   if (__gthread_active_p ())
00278     return pthread_setspecific (_objc_thread_storage, value);
00279   else
00280     {
00281       thread_local_storage = value;
00282       return 0;
00283     }
00284 }
00285 
00286 /* Returns the thread's local storage pointer.  */
00287 static inline void *
00288 __gthread_objc_thread_get_data (void)
00289 {
00290   if (__gthread_active_p ())
00291     return pthread_getspecific (_objc_thread_storage);
00292   else
00293     return thread_local_storage;
00294 }
00295 
00296 /* Backend mutex functions */
00297 
00298 /* Allocate a mutex.  */
00299 static inline int
00300 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
00301 {
00302   if (__gthread_active_p ())
00303     {
00304       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
00305 
00306       if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL))
00307     {
00308       objc_free (mutex->backend);
00309       mutex->backend = NULL;
00310       return -1;
00311     }
00312     }
00313 
00314   return 0;
00315 }
00316 
00317 /* Deallocate a mutex.  */
00318 static inline int
00319 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
00320 {
00321   if (__gthread_active_p ())
00322     {
00323       int count;
00324 
00325       /*
00326        * Posix Threads specifically require that the thread be unlocked
00327        * for pthread_mutex_destroy to work.
00328        */
00329 
00330       do
00331     {
00332       count = pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
00333       if (count < 0)
00334         return -1;
00335     }
00336       while (count);
00337 
00338       if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
00339     return -1;
00340 
00341       objc_free (mutex->backend);
00342       mutex->backend = NULL;
00343     }
00344   return 0;
00345 }
00346 
00347 /* Grab a lock on a mutex.  */
00348 static inline int
00349 __gthread_objc_mutex_lock (objc_mutex_t mutex)
00350 {
00351   if (__gthread_active_p ()
00352       && pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0)
00353     {
00354       return -1;
00355     }
00356 
00357   return 0;
00358 }
00359 
00360 /* Try to grab a lock on a mutex.  */
00361 static inline int
00362 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
00363 {
00364   if (__gthread_active_p ()
00365       && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0)
00366     {
00367       return -1;
00368     }
00369 
00370   return 0;
00371 }
00372 
00373 /* Unlock the mutex */
00374 static inline int
00375 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
00376 {
00377   if (__gthread_active_p ()
00378       && pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0)
00379     {
00380       return -1;
00381     }
00382 
00383   return 0;
00384 }
00385 
00386 /* Backend condition mutex functions */
00387 
00388 /* Allocate a condition.  */
00389 static inline int
00390 __gthread_objc_condition_allocate (objc_condition_t condition)
00391 {
00392   if (__gthread_active_p ())
00393     {
00394       condition->backend = objc_malloc (sizeof (pthread_cond_t));
00395 
00396       if (pthread_cond_init ((pthread_cond_t *) condition->backend, NULL))
00397     {
00398       objc_free (condition->backend);
00399       condition->backend = NULL;
00400       return -1;
00401     }
00402     }
00403 
00404   return 0;
00405 }
00406 
00407 /* Deallocate a condition.  */
00408 static inline int
00409 __gthread_objc_condition_deallocate (objc_condition_t condition)
00410 {
00411   if (__gthread_active_p ())
00412     {
00413       if (pthread_cond_destroy ((pthread_cond_t *) condition->backend))
00414     return -1;
00415 
00416       objc_free (condition->backend);
00417       condition->backend = NULL;
00418     }
00419   return 0;
00420 }
00421 
00422 /* Wait on the condition */
00423 static inline int
00424 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
00425 {
00426   if (__gthread_active_p ())
00427     return pthread_cond_wait ((pthread_cond_t *) condition->backend,
00428                   (pthread_mutex_t *) mutex->backend);
00429   else
00430     return 0;
00431 }
00432 
00433 /* Wake up all threads waiting on this condition.  */
00434 static inline int
00435 __gthread_objc_condition_broadcast (objc_condition_t condition)
00436 {
00437   if (__gthread_active_p ())
00438     return pthread_cond_broadcast ((pthread_cond_t *) condition->backend);
00439   else
00440     return 0;
00441 }
00442 
00443 /* Wake up one thread waiting on this condition.  */
00444 static inline int
00445 __gthread_objc_condition_signal (objc_condition_t condition)
00446 {
00447   if (__gthread_active_p ())
00448     return pthread_cond_signal ((pthread_cond_t *) condition->backend);
00449   else
00450     return 0;
00451 }
00452 
00453 #else /* _LIBOBJC */
00454 
00455 static inline int
00456 __gthread_once (__gthread_once_t *once, void (*func) (void))
00457 {
00458   if (__gthread_active_p ())
00459     return pthread_once (once, func);
00460   else
00461     return -1;
00462 }
00463 
00464 static inline int
00465 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
00466 {
00467   return pthread_key_create (key, dtor);
00468 }
00469 
00470 static inline int
00471 __gthread_key_delete (__gthread_key_t key)
00472 {
00473   return pthread_key_delete (key);
00474 }
00475 
00476 static inline void *
00477 __gthread_getspecific (__gthread_key_t key)
00478 {
00479   return pthread_getspecific (key);
00480 }
00481 
00482 static inline int
00483 __gthread_setspecific (__gthread_key_t key, const void *ptr)
00484 {
00485   return pthread_setspecific (key, ptr);
00486 }
00487 
00488 static inline int
00489 __gthread_mutex_lock (__gthread_mutex_t *mutex)
00490 {
00491   if (__gthread_active_p ())
00492     return pthread_mutex_lock (mutex);
00493   else
00494     return 0;
00495 }
00496 
00497 static inline int
00498 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
00499 {
00500   if (__gthread_active_p ())
00501     return pthread_mutex_trylock (mutex);
00502   else
00503     return 0;
00504 }
00505 
00506 static inline int
00507 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
00508 {
00509   if (__gthread_active_p ())
00510     return pthread_mutex_unlock (mutex);
00511   else
00512     return 0;
00513 }
00514 
00515 #endif /* _LIBOBJC */
00516 
00517 #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */

Generated on Fri May 6 01:08:56 2005 for libstdc++-v3 Source by  doxygen 1.4.2