# 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 */