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