gthr-posix.h

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

Generated on Thu Feb 10 23:22:54 2005 for libstdc++-v3 Source by  doxygen 1.4.0