190075Sobrien/* Threads compatibility routines for libgcc2 and libobjc. */ 250397Sobrien/* Compile this one with gcc. */ 3171825Skan/* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 4132718Skan Free Software Foundation, Inc. 550397Sobrien 690075SobrienThis file is part of GCC. 750397Sobrien 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1250397Sobrien 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1750397Sobrien 1850397SobrienYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2250397Sobrien 2350397Sobrien/* As a special exception, if you link this library with other files, 2450397Sobrien some of which are compiled with GCC, to produce an executable, 2550397Sobrien this library does not by itself cause the resulting executable 2650397Sobrien to be covered by the GNU General Public License. 2750397Sobrien This exception does not however invalidate any other reasons why 2850397Sobrien the executable file might be covered by the GNU General Public License. */ 2950397Sobrien 3090075Sobrien#ifndef GCC_GTHR_POSIX_H 3190075Sobrien#define GCC_GTHR_POSIX_H 3250397Sobrien 3350397Sobrien/* POSIX threads specific definitions. 3490075Sobrien Easy, since the interface is just one-to-one mapping. */ 3550397Sobrien 3650397Sobrien#define __GTHREADS 1 3750397Sobrien 38132718Skan/* Some implementations of <pthread.h> require this to be defined. */ 39169689Skan#if !defined(_REENTRANT) && defined(__osf__) 40132718Skan#define _REENTRANT 1 41132718Skan#endif 42132718Skan 4350397Sobrien#include <pthread.h> 44117395Skan#include <unistd.h> 4550397Sobrien 4650397Sobrientypedef pthread_key_t __gthread_key_t; 4750397Sobrientypedef pthread_once_t __gthread_once_t; 4850397Sobrientypedef pthread_mutex_t __gthread_mutex_t; 49169689Skantypedef pthread_mutex_t __gthread_recursive_mutex_t; 5050397Sobrien 5150397Sobrien#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER 5250397Sobrien#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT 53169689Skan#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER) 54169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER 55169689Skan#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) 56169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 57169689Skan#else 58169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 59169689Skan#endif 6050397Sobrien 6150397Sobrien#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 62171825Skan# ifndef __gthrw_pragma 63171825Skan# define __gthrw_pragma(pragma) 64171825Skan# endif 65169689Skan# define __gthrw2(name,name2,type) \ 66171825Skan static __typeof(type) name __attribute__ ((__weakref__(#name2))); \ 67171825Skan __gthrw_pragma(weak type) 68169689Skan# define __gthrw_(name) __gthrw_ ## name 69169689Skan#else 70169689Skan# define __gthrw2(name,name2,type) 71169689Skan# define __gthrw_(name) name 72169689Skan#endif 7350397Sobrien 74169689Skan/* Typically, __gthrw_foo is a weak reference to symbol foo. */ 75169689Skan#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name) 7650397Sobrien 77169689Skan/* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to 78169689Skan map a subset of the POSIX pthread API to mangled versions of their 79169689Skan names. */ 80169689Skan#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_) 81169689Skan#define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name) 82169689Skan__gthrw3(pthread_once) 83169689Skan__gthrw3(pthread_getspecific) 84169689Skan__gthrw3(pthread_setspecific) 85169689Skan__gthrw3(pthread_create) 86169689Skan__gthrw3(pthread_cancel) 87169689Skan__gthrw3(pthread_mutex_lock) 88169689Skan__gthrw3(pthread_mutex_trylock) 89169689Skan__gthrw3(pthread_mutex_unlock) 90169689Skan__gthrw3(pthread_mutex_init) 91169689Skan#else 92169689Skan__gthrw(pthread_once) 93169689Skan__gthrw(pthread_getspecific) 94169689Skan__gthrw(pthread_setspecific) 95169689Skan__gthrw(pthread_create) 96169689Skan__gthrw(pthread_cancel) 97169689Skan__gthrw(pthread_mutex_lock) 98169689Skan__gthrw(pthread_mutex_trylock) 99169689Skan__gthrw(pthread_mutex_unlock) 100169689Skan__gthrw(pthread_mutex_init) 101169689Skan#endif 10250397Sobrien 103169689Skan__gthrw(pthread_key_create) 104169689Skan__gthrw(pthread_key_delete) 105169689Skan__gthrw(pthread_mutexattr_init) 106169689Skan__gthrw(pthread_mutexattr_settype) 107169689Skan__gthrw(pthread_mutexattr_destroy) 108169689Skan 109169689Skan 110132718Skan#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) 111117395Skan/* Objective-C. */ 112169689Skan#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_) 113169689Skan__gthrw3(pthread_cond_broadcast) 114169689Skan__gthrw3(pthread_cond_destroy) 115169689Skan__gthrw3(pthread_cond_init) 116169689Skan__gthrw3(pthread_cond_signal) 117169689Skan__gthrw3(pthread_cond_wait) 118169689Skan__gthrw3(pthread_exit) 119169689Skan__gthrw3(pthread_mutex_destroy) 120169689Skan__gthrw3(pthread_self) 121169689Skan#else 122169689Skan__gthrw(pthread_cond_broadcast) 123169689Skan__gthrw(pthread_cond_destroy) 124169689Skan__gthrw(pthread_cond_init) 125169689Skan__gthrw(pthread_cond_signal) 126169689Skan__gthrw(pthread_cond_wait) 127169689Skan__gthrw(pthread_exit) 128169689Skan__gthrw(pthread_mutex_destroy) 129169689Skan__gthrw(pthread_self) 130169689Skan#endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */ 131169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING 132117395Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 133169689Skan__gthrw(sched_get_priority_max) 134169689Skan__gthrw(sched_get_priority_min) 135117395Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 136169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */ 137169689Skan__gthrw(sched_yield) 138169689Skan__gthrw(pthread_attr_destroy) 139169689Skan__gthrw(pthread_attr_init) 140169689Skan__gthrw(pthread_attr_setdetachstate) 141117395Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 142169689Skan__gthrw(pthread_getschedparam) 143169689Skan__gthrw(pthread_setschedparam) 144117395Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 145132718Skan#endif /* _LIBOBJC || _LIBOBJC_WEAK */ 14650397Sobrien 147169689Skan#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 148169689Skan 149169689Skan/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if 150169689Skan -pthreads is not specified. The functions are dummies and most return an 151169689Skan error value. However pthread_once returns 0 without invoking the routine 152169689Skan it is passed so we cannot pretend that the interface is active if -pthreads 153169689Skan is not specified. On Solaris 2.5.1, the interface is not exposed at all so 154169689Skan we need to play the usual game with weak symbols. On Solaris 10 and up, a 155178388Smarius working interface is always exposed. On FreeBSD 6 and later, libc also 156178388Smarius exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up 157178388Smarius to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc, 158178388Smarius which means the alternate __gthread_active_p below cannot be used there. */ 159169689Skan 160178388Smarius#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__)) 161169689Skan 162169689Skanstatic volatile int __gthread_active = -1; 163169689Skan 164169689Skanstatic void 165169689Skan__gthread_trigger (void) 166169689Skan{ 167169689Skan __gthread_active = 1; 168169689Skan} 169169689Skan 17050397Sobrienstatic inline int 17190075Sobrien__gthread_active_p (void) 17250397Sobrien{ 173169689Skan static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; 174169689Skan static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT; 175169689Skan 176169689Skan /* Avoid reading __gthread_active twice on the main code path. */ 177169689Skan int __gthread_active_latest_value = __gthread_active; 178169689Skan 179169689Skan /* This test is not protected to avoid taking a lock on the main code 180169689Skan path so every update of __gthread_active in a threaded program must 181169689Skan be atomic with regard to the result of the test. */ 182169689Skan if (__builtin_expect (__gthread_active_latest_value < 0, 0)) 183169689Skan { 184169689Skan if (__gthrw_(pthread_once)) 185169689Skan { 186169689Skan /* If this really is a threaded program, then we must ensure that 187169689Skan __gthread_active has been set to 1 before exiting this block. */ 188169689Skan __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); 189169689Skan __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger); 190169689Skan __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); 191169689Skan } 192169689Skan 193169689Skan /* Make sure we'll never enter this block again. */ 194169689Skan if (__gthread_active < 0) 195169689Skan __gthread_active = 0; 196169689Skan 197169689Skan __gthread_active_latest_value = __gthread_active; 198169689Skan } 199169689Skan 200169689Skan return __gthread_active_latest_value != 0; 201169689Skan} 202169689Skan 203178388Smarius#else /* neither FreeBSD nor Solaris */ 204169689Skan 205169689Skanstatic inline int 206169689Skan__gthread_active_p (void) 207169689Skan{ 208169689Skan static void *const __gthread_active_ptr 209169689Skan = __extension__ (void *) &__gthrw_(pthread_cancel); 21050397Sobrien return __gthread_active_ptr != 0; 21150397Sobrien} 21250397Sobrien 213178388Smarius#endif /* FreeBSD or Solaris */ 214169689Skan 21550397Sobrien#else /* not SUPPORTS_WEAK */ 21650397Sobrien 21750397Sobrienstatic inline int 21890075Sobrien__gthread_active_p (void) 21950397Sobrien{ 22050397Sobrien return 1; 22150397Sobrien} 22250397Sobrien 22350397Sobrien#endif /* SUPPORTS_WEAK */ 22450397Sobrien 22590075Sobrien#ifdef _LIBOBJC 22690075Sobrien 22790075Sobrien/* This is the config.h file in libobjc/ */ 22890075Sobrien#include <config.h> 22990075Sobrien 23090075Sobrien#ifdef HAVE_SCHED_H 23190075Sobrien# include <sched.h> 23290075Sobrien#endif 23390075Sobrien 23490075Sobrien/* Key structure for maintaining thread specific storage */ 23590075Sobrienstatic pthread_key_t _objc_thread_storage; 23690075Sobrienstatic pthread_attr_t _objc_thread_attribs; 23790075Sobrien 23890075Sobrien/* Thread local storage for a single thread */ 23990075Sobrienstatic void *thread_local_storage = NULL; 24090075Sobrien 24190075Sobrien/* Backend initialization functions */ 24290075Sobrien 24390075Sobrien/* Initialize the threads subsystem. */ 24450397Sobrienstatic inline int 245117395Skan__gthread_objc_init_thread_system (void) 24650397Sobrien{ 24750397Sobrien if (__gthread_active_p ()) 24890075Sobrien { 249169689Skan /* Initialize the thread storage key. */ 250169689Skan if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0) 251117395Skan { 252117395Skan /* The normal default detach state for threads is 253117395Skan * PTHREAD_CREATE_JOINABLE which causes threads to not die 254117395Skan * when you think they should. */ 255169689Skan if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0 256169689Skan && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs, 257117395Skan PTHREAD_CREATE_DETACHED) == 0) 258117395Skan return 0; 259117395Skan } 26090075Sobrien } 26190075Sobrien 26290075Sobrien return -1; 26390075Sobrien} 26490075Sobrien 26590075Sobrien/* Close the threads subsystem. */ 26690075Sobrienstatic inline int 267117395Skan__gthread_objc_close_thread_system (void) 26890075Sobrien{ 26990075Sobrien if (__gthread_active_p () 270169689Skan && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0 271169689Skan && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0) 27290075Sobrien return 0; 27390075Sobrien 27490075Sobrien return -1; 27590075Sobrien} 27690075Sobrien 27790075Sobrien/* Backend thread functions */ 27890075Sobrien 27990075Sobrien/* Create a new thread of execution. */ 28090075Sobrienstatic inline objc_thread_t 281117395Skan__gthread_objc_thread_detach (void (*func)(void *), void *arg) 28290075Sobrien{ 28390075Sobrien objc_thread_t thread_id; 28490075Sobrien pthread_t new_thread_handle; 28590075Sobrien 28690075Sobrien if (!__gthread_active_p ()) 28790075Sobrien return NULL; 288117395Skan 289169689Skan if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg))) 29090075Sobrien thread_id = (objc_thread_t) new_thread_handle; 29190075Sobrien else 29290075Sobrien thread_id = NULL; 293117395Skan 29490075Sobrien return thread_id; 29590075Sobrien} 29690075Sobrien 29790075Sobrien/* Set the current thread's priority. */ 29890075Sobrienstatic inline int 299117395Skan__gthread_objc_thread_set_priority (int priority) 30090075Sobrien{ 301117395Skan if (!__gthread_active_p ()) 30290075Sobrien return -1; 303117395Skan else 304117395Skan { 305169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING 306117395Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 307169689Skan pthread_t thread_id = __gthrw_(pthread_self) (); 308117395Skan int policy; 309117395Skan struct sched_param params; 310117395Skan int priority_min, priority_max; 31190075Sobrien 312169689Skan if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0) 313117395Skan { 314169689Skan if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1) 315117395Skan return -1; 31690075Sobrien 317169689Skan if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1) 318117395Skan return -1; 31990075Sobrien 320117395Skan if (priority > priority_max) 321117395Skan priority = priority_max; 322117395Skan else if (priority < priority_min) 323117395Skan priority = priority_min; 324117395Skan params.sched_priority = priority; 32590075Sobrien 326117395Skan /* 327117395Skan * The solaris 7 and several other man pages incorrectly state that 328117395Skan * this should be a pointer to policy but pthread.h is universally 329117395Skan * at odds with this. 330117395Skan */ 331169689Skan if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0) 332117395Skan return 0; 333117395Skan } 334117395Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 335169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */ 336117395Skan return -1; 337117395Skan } 33890075Sobrien} 33990075Sobrien 34090075Sobrien/* Return the current thread's priority. */ 34190075Sobrienstatic inline int 342117395Skan__gthread_objc_thread_get_priority (void) 34390075Sobrien{ 344169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING 345117395Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 34690075Sobrien if (__gthread_active_p ()) 34790075Sobrien { 34890075Sobrien int policy; 34990075Sobrien struct sched_param params; 35090075Sobrien 351169689Skan if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0) 352117395Skan return params.sched_priority; 35390075Sobrien else 354117395Skan return -1; 35590075Sobrien } 35690075Sobrien else 357117395Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 358169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */ 35990075Sobrien return OBJC_THREAD_INTERACTIVE_PRIORITY; 36090075Sobrien} 36190075Sobrien 36290075Sobrien/* Yield our process time to another thread. */ 36390075Sobrienstatic inline void 364117395Skan__gthread_objc_thread_yield (void) 36590075Sobrien{ 36690075Sobrien if (__gthread_active_p ()) 367169689Skan __gthrw_(sched_yield) (); 36890075Sobrien} 36990075Sobrien 37090075Sobrien/* Terminate the current thread. */ 37190075Sobrienstatic inline int 372117395Skan__gthread_objc_thread_exit (void) 37390075Sobrien{ 37490075Sobrien if (__gthread_active_p ()) 37590075Sobrien /* exit the thread */ 376169689Skan __gthrw_(pthread_exit) (&__objc_thread_exit_status); 37790075Sobrien 37890075Sobrien /* Failed if we reached here */ 37990075Sobrien return -1; 38090075Sobrien} 38190075Sobrien 38290075Sobrien/* Returns an integer value which uniquely describes a thread. */ 38390075Sobrienstatic inline objc_thread_t 384117395Skan__gthread_objc_thread_id (void) 38590075Sobrien{ 38690075Sobrien if (__gthread_active_p ()) 387169689Skan return (objc_thread_t) __gthrw_(pthread_self) (); 38890075Sobrien else 38990075Sobrien return (objc_thread_t) 1; 39090075Sobrien} 39190075Sobrien 39290075Sobrien/* Sets the thread's local storage pointer. */ 39390075Sobrienstatic inline int 394117395Skan__gthread_objc_thread_set_data (void *value) 39590075Sobrien{ 39690075Sobrien if (__gthread_active_p ()) 397169689Skan return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); 39890075Sobrien else 39990075Sobrien { 40090075Sobrien thread_local_storage = value; 40190075Sobrien return 0; 40290075Sobrien } 40390075Sobrien} 40490075Sobrien 40590075Sobrien/* Returns the thread's local storage pointer. */ 40690075Sobrienstatic inline void * 407117395Skan__gthread_objc_thread_get_data (void) 40890075Sobrien{ 40990075Sobrien if (__gthread_active_p ()) 410169689Skan return __gthrw_(pthread_getspecific) (_objc_thread_storage); 41190075Sobrien else 41290075Sobrien return thread_local_storage; 41390075Sobrien} 41490075Sobrien 41590075Sobrien/* Backend mutex functions */ 41690075Sobrien 41790075Sobrien/* Allocate a mutex. */ 41890075Sobrienstatic inline int 419117395Skan__gthread_objc_mutex_allocate (objc_mutex_t mutex) 42090075Sobrien{ 42190075Sobrien if (__gthread_active_p ()) 42290075Sobrien { 423117395Skan mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); 42490075Sobrien 425169689Skan if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL)) 42690075Sobrien { 427117395Skan objc_free (mutex->backend); 42890075Sobrien mutex->backend = NULL; 42990075Sobrien return -1; 43090075Sobrien } 43190075Sobrien } 43290075Sobrien 43390075Sobrien return 0; 43490075Sobrien} 43590075Sobrien 43690075Sobrien/* Deallocate a mutex. */ 43790075Sobrienstatic inline int 438117395Skan__gthread_objc_mutex_deallocate (objc_mutex_t mutex) 43990075Sobrien{ 44090075Sobrien if (__gthread_active_p ()) 44190075Sobrien { 44290075Sobrien int count; 44390075Sobrien 44490075Sobrien /* 44590075Sobrien * Posix Threads specifically require that the thread be unlocked 446169689Skan * for __gthrw_(pthread_mutex_destroy) to work. 44790075Sobrien */ 44890075Sobrien 44990075Sobrien do 45090075Sobrien { 451169689Skan count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); 45290075Sobrien if (count < 0) 45390075Sobrien return -1; 45490075Sobrien } 45590075Sobrien while (count); 45690075Sobrien 457169689Skan if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) 45890075Sobrien return -1; 45990075Sobrien 460117395Skan objc_free (mutex->backend); 46190075Sobrien mutex->backend = NULL; 46290075Sobrien } 46390075Sobrien return 0; 46490075Sobrien} 46590075Sobrien 46690075Sobrien/* Grab a lock on a mutex. */ 46790075Sobrienstatic inline int 468117395Skan__gthread_objc_mutex_lock (objc_mutex_t mutex) 46990075Sobrien{ 470117395Skan if (__gthread_active_p () 471169689Skan && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0) 47290075Sobrien { 47390075Sobrien return -1; 47490075Sobrien } 47590075Sobrien 47690075Sobrien return 0; 47790075Sobrien} 47890075Sobrien 47990075Sobrien/* Try to grab a lock on a mutex. */ 48090075Sobrienstatic inline int 481117395Skan__gthread_objc_mutex_trylock (objc_mutex_t mutex) 48290075Sobrien{ 483117395Skan if (__gthread_active_p () 484169689Skan && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0) 48590075Sobrien { 48690075Sobrien return -1; 48790075Sobrien } 48890075Sobrien 48990075Sobrien return 0; 49090075Sobrien} 49190075Sobrien 49290075Sobrien/* Unlock the mutex */ 49390075Sobrienstatic inline int 494117395Skan__gthread_objc_mutex_unlock (objc_mutex_t mutex) 49590075Sobrien{ 496117395Skan if (__gthread_active_p () 497169689Skan && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0) 49890075Sobrien { 49990075Sobrien return -1; 50090075Sobrien } 50190075Sobrien 50290075Sobrien return 0; 50390075Sobrien} 50490075Sobrien 50590075Sobrien/* Backend condition mutex functions */ 50690075Sobrien 50790075Sobrien/* Allocate a condition. */ 50890075Sobrienstatic inline int 509117395Skan__gthread_objc_condition_allocate (objc_condition_t condition) 51090075Sobrien{ 51190075Sobrien if (__gthread_active_p ()) 51290075Sobrien { 513117395Skan condition->backend = objc_malloc (sizeof (pthread_cond_t)); 51490075Sobrien 515169689Skan if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL)) 51690075Sobrien { 517117395Skan objc_free (condition->backend); 51890075Sobrien condition->backend = NULL; 51990075Sobrien return -1; 52090075Sobrien } 52190075Sobrien } 52290075Sobrien 52390075Sobrien return 0; 52490075Sobrien} 52590075Sobrien 52690075Sobrien/* Deallocate a condition. */ 52790075Sobrienstatic inline int 528117395Skan__gthread_objc_condition_deallocate (objc_condition_t condition) 52990075Sobrien{ 53090075Sobrien if (__gthread_active_p ()) 53190075Sobrien { 532169689Skan if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend)) 53390075Sobrien return -1; 53490075Sobrien 535117395Skan objc_free (condition->backend); 53690075Sobrien condition->backend = NULL; 53790075Sobrien } 53890075Sobrien return 0; 53990075Sobrien} 54090075Sobrien 54190075Sobrien/* Wait on the condition */ 54290075Sobrienstatic inline int 543117395Skan__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) 54490075Sobrien{ 54590075Sobrien if (__gthread_active_p ()) 546169689Skan return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend, 547117395Skan (pthread_mutex_t *) mutex->backend); 54890075Sobrien else 54990075Sobrien return 0; 55090075Sobrien} 55190075Sobrien 55290075Sobrien/* Wake up all threads waiting on this condition. */ 55390075Sobrienstatic inline int 554117395Skan__gthread_objc_condition_broadcast (objc_condition_t condition) 55590075Sobrien{ 55690075Sobrien if (__gthread_active_p ()) 557169689Skan return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend); 55890075Sobrien else 55990075Sobrien return 0; 56090075Sobrien} 56190075Sobrien 56290075Sobrien/* Wake up one thread waiting on this condition. */ 56390075Sobrienstatic inline int 564117395Skan__gthread_objc_condition_signal (objc_condition_t condition) 56590075Sobrien{ 56690075Sobrien if (__gthread_active_p ()) 567169689Skan return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend); 56890075Sobrien else 56990075Sobrien return 0; 57090075Sobrien} 57190075Sobrien 57290075Sobrien#else /* _LIBOBJC */ 57390075Sobrien 57490075Sobrienstatic inline int 57590075Sobrien__gthread_once (__gthread_once_t *once, void (*func) (void)) 57690075Sobrien{ 57790075Sobrien if (__gthread_active_p ()) 578169689Skan return __gthrw_(pthread_once) (once, func); 57950397Sobrien else 58050397Sobrien return -1; 58150397Sobrien} 58250397Sobrien 58350397Sobrienstatic inline int 58450397Sobrien__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) 58550397Sobrien{ 586169689Skan return __gthrw_(pthread_key_create) (key, dtor); 58750397Sobrien} 58850397Sobrien 58950397Sobrienstatic inline int 59050397Sobrien__gthread_key_delete (__gthread_key_t key) 59150397Sobrien{ 592169689Skan return __gthrw_(pthread_key_delete) (key); 59350397Sobrien} 59450397Sobrien 59550397Sobrienstatic inline void * 59650397Sobrien__gthread_getspecific (__gthread_key_t key) 59750397Sobrien{ 598169689Skan return __gthrw_(pthread_getspecific) (key); 59950397Sobrien} 60050397Sobrien 60150397Sobrienstatic inline int 60250397Sobrien__gthread_setspecific (__gthread_key_t key, const void *ptr) 60350397Sobrien{ 604169689Skan return __gthrw_(pthread_setspecific) (key, ptr); 60550397Sobrien} 60650397Sobrien 60750397Sobrienstatic inline int 60850397Sobrien__gthread_mutex_lock (__gthread_mutex_t *mutex) 60950397Sobrien{ 61050397Sobrien if (__gthread_active_p ()) 611169689Skan return __gthrw_(pthread_mutex_lock) (mutex); 61250397Sobrien else 61350397Sobrien return 0; 61450397Sobrien} 61550397Sobrien 61650397Sobrienstatic inline int 61750397Sobrien__gthread_mutex_trylock (__gthread_mutex_t *mutex) 61850397Sobrien{ 61950397Sobrien if (__gthread_active_p ()) 620169689Skan return __gthrw_(pthread_mutex_trylock) (mutex); 62150397Sobrien else 62250397Sobrien return 0; 62350397Sobrien} 62450397Sobrien 62550397Sobrienstatic inline int 62650397Sobrien__gthread_mutex_unlock (__gthread_mutex_t *mutex) 62750397Sobrien{ 62850397Sobrien if (__gthread_active_p ()) 629169689Skan return __gthrw_(pthread_mutex_unlock) (mutex); 63050397Sobrien else 63150397Sobrien return 0; 63250397Sobrien} 63350397Sobrien 634169689Skan#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 635169689Skanstatic inline int 636169689Skan__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) 637169689Skan{ 638169689Skan if (__gthread_active_p ()) 639169689Skan { 640169689Skan pthread_mutexattr_t attr; 641169689Skan int r; 642169689Skan 643169689Skan r = __gthrw_(pthread_mutexattr_init) (&attr); 644169689Skan if (!r) 645169689Skan r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE); 646169689Skan if (!r) 647169689Skan r = __gthrw_(pthread_mutex_init) (mutex, &attr); 648169689Skan if (!r) 649169689Skan r = __gthrw_(pthread_mutexattr_destroy) (&attr); 650169689Skan return r; 651169689Skan } 652169689Skan return 0; 653169689Skan} 654169689Skan#endif 655169689Skan 656169689Skanstatic inline int 657169689Skan__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) 658169689Skan{ 659169689Skan return __gthread_mutex_lock (mutex); 660169689Skan} 661169689Skan 662169689Skanstatic inline int 663169689Skan__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) 664169689Skan{ 665169689Skan return __gthread_mutex_trylock (mutex); 666169689Skan} 667169689Skan 668169689Skanstatic inline int 669169689Skan__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) 670169689Skan{ 671169689Skan return __gthread_mutex_unlock (mutex); 672169689Skan} 673169689Skan 67490075Sobrien#endif /* _LIBOBJC */ 67590075Sobrien 67690075Sobrien#endif /* ! GCC_GTHR_POSIX_H */ 677