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

Generated on Sun Sep 12 15:49:57 2004 for libstdc++ source by doxygen 1.3.8