# 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
    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 #ifdef _POSIX_PRIORITY_SCHEDULING
    00078 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
    00079 #pragma weak sched_get_priority_max
    00080 #pragma weak sched_get_priority_min
    00081 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
    00082 #endif /* _POSIX_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_PRIORITY_SCHEDULING
    00191 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
    00192       pthread_t thread_id = pthread_self ();
    00193       int policy;
    00194       struct sched_param params;
    00195       int priority_min, priority_max;
    00196
    00197       if (pthread_getschedparam (thread_id, &policy, &params) == 0)
    00198     {
    00199       if ((priority_max = sched_get_priority_max (policy)) == -1)
    00200         return -1;
    00201
    00202       if ((priority_min = sched_get_priority_min (policy)) == -1)
    00203         return -1;
    00204
    00205       if (priority > priority_max)
    00206         priority = priority_max;
    00207       else if (priority < priority_min)
    00208         priority = priority_min;
    00209       params.sched_priority = priority;
    00210
    00211       /*
    00212        * The solaris 7 and several other man pages incorrectly state that
    00213        * this should be a pointer to policy but pthread.h is universally
    00214        * at odds with this.
    00215        */
    00216       if (pthread_setschedparam (thread_id, policy, &params) == 0)
    00217         return 0;
    00218     }
    00219 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
    00220 #endif /* _POSIX_PRIORITY_SCHEDULING */
    00221       return -1;
    00222     }
    00223 }
    00224
    00225 /* Return the current thread's priority.  */
    00226 static inline int
    00227 __gthread_objc_thread_get_priority (void)
    00228 {
    00229 #ifdef _POSIX_PRIORITY_SCHEDULING
    00230 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
    00231   if (__gthread_active_p ())
    00232     {
    00233       int policy;
    00234       struct sched_param params;
    00235
    00236       if (pthread_getschedparam (pthread_self (), &policy, &params) == 0)
    00237     return params.sched_priority;
    00238       else
    00239     return -1;
    00240     }
    00241   else
    00242 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
    00243 #endif /* _POSIX_PRIORITY_SCHEDULING */
    00244     return OBJC_THREAD_INTERACTIVE_PRIORITY;
    00245 }
    00246
    00247 /* Yield our process time to another thread.  */
    00248 static inline void
    00249 __gthread_objc_thread_yield (void)
    00250 {
    00251   if (__gthread_active_p ())
    00252     sched_yield ();
    00253 }
    00254
    00255 /* Terminate the current thread.  */
    00256 static inline int
    00257 __gthread_objc_thread_exit (void)
    00258 {
    00259   if (__gthread_active_p ())
    00260     /* exit the thread */
    00261     pthread_exit (&__objc_thread_exit_status);
    00262
    00263   /* Failed if we reached here */
    00264   return -1;
    00265 }
    00266
    00267 /* Returns an integer value which uniquely describes a thread.  */
    00268 static inline objc_thread_t
    00269 __gthread_objc_thread_id (void)
    00270 {
    00271   if (__gthread_active_p ())
    00272     return (objc_thread_t) pthread_self ();
    00273   else
    00274     return (objc_thread_t) 1;
    00275 }
    00276
    00277 /* Sets the thread's local storage pointer.  */
    00278 static inline int
    00279 __gthread_objc_thread_set_data (void *value)
    00280 {
    00281   if (__gthread_active_p ())
    00282     return pthread_setspecific (_objc_thread_storage, value);
    00283   else
    00284     {
    00285       thread_local_storage = value;
    00286       return 0;
    00287     }
    00288 }
    00289
    00290 /* Returns the thread's local storage pointer.  */
    00291 static inline void *
    00292 __gthread_objc_thread_get_data (void)
    00293 {
    00294   if (__gthread_active_p ())
    00295     return pthread_getspecific (_objc_thread_storage);
    00296   else
    00297     return thread_local_storage;
    00298 }
    00299
    00300 /* Backend mutex functions */
    00301
    00302 /* Allocate a mutex.  */
    00303 static inline int
    00304 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
    00305 {
    00306   if (__gthread_active_p ())
    00307     {
    00308       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
    00309
    00310       if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL))
    00311     {
    00312       objc_free (mutex->backend);
    00313       mutex->backend = NULL;
    00314       return -1;
    00315     }
    00316     }
    00317
    00318   return 0;
    00319 }
    00320
    00321 /* Deallocate a mutex.  */
    00322 static inline int
    00323 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
    00324 {
    00325   if (__gthread_active_p ())
    00326     {
    00327       int count;
    00328
    00329       /*
    00330        * Posix Threads specifically require that the thread be unlocked
    00331        * for pthread_mutex_destroy to work.
    00332        */
    00333
    00334       do
    00335     {
    00336       count = pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
    00337       if (count < 0)
    00338         return -1;
    00339     }
    00340       while (count);
    00341
    00342       if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
    00343     return -1;
    00344
    00345       objc_free (mutex->backend);
    00346       mutex->backend = NULL;
    00347     }
    00348   return 0;
    00349 }
    00350
    00351 /* Grab a lock on a mutex.  */
    00352 static inline int
    00353 __gthread_objc_mutex_lock (objc_mutex_t mutex)
    00354 {
    00355   if (__gthread_active_p ()
    00356       && pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0)
    00357     {
    00358       return -1;
    00359     }
    00360
    00361   return 0;
    00362 }
    00363
    00364 /* Try to grab a lock on a mutex.  */
    00365 static inline int
    00366 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
    00367 {
    00368   if (__gthread_active_p ()
    00369       && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0)
    00370     {
    00371       return -1;
    00372     }
    00373
    00374   return 0;
    00375 }
    00376
    00377 /* Unlock the mutex */
    00378 static inline int
    00379 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
    00380 {
    00381   if (__gthread_active_p ()
    00382       && pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0)
    00383     {
    00384       return -1;
    00385     }
    00386
    00387   return 0;
    00388 }
    00389
    00390 /* Backend condition mutex functions */
    00391
    00392 /* Allocate a condition.  */
    00393 static inline int
    00394 __gthread_objc_condition_allocate (objc_condition_t condition)
    00395 {
    00396   if (__gthread_active_p ())
    00397     {
    00398       condition->backend = objc_malloc (sizeof (pthread_cond_t));
    00399
    00400       if (pthread_cond_init ((pthread_cond_t *) condition->backend, NULL))
    00401     {
    00402       objc_free (condition->backend);
    00403       condition->backend = NULL;
    00404       return -1;
    00405     }
    00406     }
    00407
    00408   return 0;
    00409 }
    00410
    00411 /* Deallocate a condition.  */
    00412 static inline int
    00413 __gthread_objc_condition_deallocate (objc_condition_t condition)
    00414 {
    00415   if (__gthread_active_p ())
    00416     {
    00417       if (pthread_cond_destroy ((pthread_cond_t *) condition->backend))
    00418     return -1;
    00419
    00420       objc_free (condition->backend);
    00421       condition->backend = NULL;
    00422     }
    00423   return 0;
    00424 }
    00425
    00426 /* Wait on the condition */
    00427 static inline int
    00428 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
    00429 {
    00430   if (__gthread_active_p ())
    00431     return pthread_cond_wait ((pthread_cond_t *) condition->backend,
    00432                   (pthread_mutex_t *) mutex->backend);
    00433   else
    00434     return 0;
    00435 }
    00436
    00437 /* Wake up all threads waiting on this condition.  */
    00438 static inline int
    00439 __gthread_objc_condition_broadcast (objc_condition_t condition)
    00440 {
    00441   if (__gthread_active_p ())
    00442     return pthread_cond_broadcast ((pthread_cond_t *) condition->backend);
    00443   else
    00444     return 0;
    00445 }
    00446
    00447 /* Wake up one thread waiting on this condition.  */
    00448 static inline int
    00449 __gthread_objc_condition_signal (objc_condition_t condition)
    00450 {
    00451   if (__gthread_active_p ())
    00452     return pthread_cond_signal ((pthread_cond_t *) condition->backend);
    00453   else
    00454     return 0;
    00455 }
    00456
    00457 #else /* _LIBOBJC */
    00458
    00459 static inline int
    00460 __gthread_once (__gthread_once_t *once, void (*func) (void))
    00461 {
    00462   if (__gthread_active_p ())
    00463     return pthread_once (once, func);
    00464   else
    00465     return -1;
    00466 }
    00467
    00468 static inline int
    00469 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
    00470 {
    00471   return pthread_key_create (key, dtor);
    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 /* ! _GLIBCXX_GCC_GTHR_POSIX_H */