1169689Skan/* Threads compatibility routines for libgcc2 and libobjc. */ 2169689Skan/* Compile this one with gcc. */ 3169689Skan/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. 4169689Skan 5169689SkanThis file is part of GCC. 6169689Skan 7169689SkanGCC is free software; you can redistribute it and/or modify it under 8169689Skanthe terms of the GNU General Public License as published by the Free 9169689SkanSoftware Foundation; either version 2, or (at your option) any later 10169689Skanversion. 11169689Skan 12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 14169689SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15169689Skanfor more details. 16169689Skan 17169689SkanYou should have received a copy of the GNU General Public License 18169689Skanalong with GCC; see the file COPYING. If not, write to the Free 19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169689Skan02110-1301, USA. */ 21169689Skan 22169689Skan/* As a special exception, if you link this library with other files, 23169689Skan some of which are compiled with GCC, to produce an executable, 24169689Skan this library does not by itself cause the resulting executable 25169689Skan to be covered by the GNU General Public License. 26169689Skan This exception does not however invalidate any other reasons why 27169689Skan the executable file might be covered by the GNU General Public License. */ 28169689Skan 29169689Skan#ifndef GCC_GTHR_POSIX_H 30169689Skan#define GCC_GTHR_POSIX_H 31169689Skan 32169689Skan/* POSIX threads specific definitions. 33169689Skan Easy, since the interface is just one-to-one mapping. */ 34169689Skan 35169689Skan#define __GTHREADS 1 36169689Skan 37169689Skan/* Some implementations of <pthread.h> require this to be defined. */ 38169689Skan#ifndef _REENTRANT 39169689Skan#define _REENTRANT 1 40169689Skan#endif 41169689Skan 42169689Skan#include <pthread.h> 43169689Skan#include <unistd.h> 44169689Skan 45169689Skantypedef pthread_key_t __gthread_key_t; 46169689Skantypedef pthread_once_t __gthread_once_t; 47169689Skantypedef pthread_mutex_t __gthread_mutex_t; 48169689Skan 49169689Skantypedef struct { 50169689Skan long depth; 51169689Skan pthread_t owner; 52169689Skan pthread_mutex_t actual; 53169689Skan} __gthread_recursive_mutex_t; 54169689Skan 55169689Skan#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER 56169689Skan#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT 57169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 58169689Skan 59169689Skan#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 60169689Skan# define __gthrw(name) \ 61169689Skan static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))); 62169689Skan# define __gthrw_(name) __gthrw_ ## name 63169689Skan#else 64169689Skan# define __gthrw(name) 65169689Skan# define __gthrw_(name) name 66169689Skan#endif 67169689Skan 68169689Skan__gthrw(pthread_once) 69169689Skan__gthrw(pthread_key_create) 70169689Skan__gthrw(pthread_key_delete) 71169689Skan__gthrw(pthread_getspecific) 72169689Skan__gthrw(pthread_setspecific) 73169689Skan__gthrw(pthread_create) 74169689Skan__gthrw(pthread_cancel) 75169689Skan__gthrw(pthread_self) 76169689Skan 77169689Skan__gthrw(pthread_mutex_lock) 78169689Skan__gthrw(pthread_mutex_trylock) 79169689Skan__gthrw(pthread_mutex_unlock) 80169689Skan__gthrw(pthread_mutexattr_init) 81169689Skan__gthrw(pthread_mutexattr_destroy) 82169689Skan 83169689Skan__gthrw(pthread_mutex_init) 84169689Skan 85169689Skan#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) 86169689Skan/* Objective-C. */ 87169689Skan__gthrw(pthread_cond_broadcast) 88169689Skan__gthrw(pthread_cond_destroy) 89169689Skan__gthrw(pthread_cond_init) 90169689Skan__gthrw(pthread_cond_signal) 91169689Skan__gthrw(pthread_cond_wait) 92169689Skan__gthrw(pthread_exit) 93169689Skan__gthrw(pthread_mutex_destroy) 94169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING 95169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 96169689Skan__gthrw(sched_get_priority_max) 97169689Skan__gthrw(sched_get_priority_min) 98169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 99169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */ 100169689Skan__gthrw(sched_yield) 101169689Skan__gthrw(pthread_attr_destroy) 102169689Skan__gthrw(pthread_attr_init) 103169689Skan__gthrw(pthread_attr_setdetachstate) 104169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 105169689Skan__gthrw(pthread_getschedparam) 106169689Skan__gthrw(pthread_setschedparam) 107169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 108169689Skan#endif /* _LIBOBJC || _LIBOBJC_WEAK */ 109169689Skan 110169689Skan#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 111169689Skan 112169689Skan/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if 113169689Skan -pthreads is not specified. The functions are dummies and most return an 114169689Skan error value. However pthread_once returns 0 without invoking the routine 115169689Skan it is passed so we cannot pretend that the interface is active if -pthreads 116169689Skan is not specified. On Solaris 2.5.1, the interface is not exposed at all so 117169689Skan we need to play the usual game with weak symbols. On Solaris 10 and up, a 118252176Spfg working interface is always exposed. On FreeBSD 6 and later, libc also 119252176Spfg exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up 120252176Spfg to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc, 121252176Spfg which means the alternate __gthread_active_p below cannot be used there. */ 122169689Skan 123169689Skan 124252176Spfg */ 125252176Spfg 126252176Spfg#if defined(__FreeBSD__) || defined(__sun) && defined(__svr4__) 127252176Spfg 128169689Skanstatic volatile int __gthread_active = -1; 129169689Skan 130169689Skanstatic void 131169689Skan__gthread_trigger (void) 132169689Skan{ 133169689Skan __gthread_active = 1; 134169689Skan} 135169689Skan 136169689Skanstatic inline int 137169689Skan__gthread_active_p (void) 138169689Skan{ 139169689Skan static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; 140169689Skan static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT; 141169689Skan 142169689Skan /* Avoid reading __gthread_active twice on the main code path. */ 143169689Skan int __gthread_active_latest_value = __gthread_active; 144169689Skan 145169689Skan /* This test is not protected to avoid taking a lock on the main code 146169689Skan path so every update of __gthread_active in a threaded program must 147169689Skan be atomic with regard to the result of the test. */ 148169689Skan if (__builtin_expect (__gthread_active_latest_value < 0, 0)) 149169689Skan { 150169689Skan if (__gthrw_(pthread_once)) 151169689Skan { 152169689Skan /* If this really is a threaded program, then we must ensure that 153169689Skan __gthread_active has been set to 1 before exiting this block. */ 154169689Skan __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); 155169689Skan __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger); 156169689Skan __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); 157169689Skan } 158169689Skan 159169689Skan /* Make sure we'll never enter this block again. */ 160169689Skan if (__gthread_active < 0) 161169689Skan __gthread_active = 0; 162169689Skan 163169689Skan __gthread_active_latest_value = __gthread_active; 164169689Skan } 165169689Skan 166169689Skan return __gthread_active_latest_value != 0; 167169689Skan} 168169689Skan 169252176Spfg#else /* neither FreeBSD nor Solaris */ 170169689Skan 171169689Skanstatic inline int 172169689Skan__gthread_active_p (void) 173169689Skan{ 174169689Skan static void *const __gthread_active_ptr 175169689Skan = __extension__ (void *) &__gthrw_(pthread_cancel); 176169689Skan return __gthread_active_ptr != 0; 177169689Skan} 178169689Skan 179252176Spfg#endif /* FreeBSD or Solaris */ 180169689Skan 181169689Skan#else /* not SUPPORTS_WEAK */ 182169689Skan 183169689Skanstatic inline int 184169689Skan__gthread_active_p (void) 185169689Skan{ 186169689Skan return 1; 187169689Skan} 188169689Skan 189169689Skan#endif /* SUPPORTS_WEAK */ 190169689Skan 191169689Skan#ifdef _LIBOBJC 192169689Skan 193169689Skan/* This is the config.h file in libobjc/ */ 194169689Skan#include <config.h> 195169689Skan 196169689Skan#ifdef HAVE_SCHED_H 197169689Skan# include <sched.h> 198169689Skan#endif 199169689Skan 200169689Skan/* Key structure for maintaining thread specific storage */ 201169689Skanstatic pthread_key_t _objc_thread_storage; 202169689Skanstatic pthread_attr_t _objc_thread_attribs; 203169689Skan 204169689Skan/* Thread local storage for a single thread */ 205169689Skanstatic void *thread_local_storage = NULL; 206169689Skan 207169689Skan/* Backend initialization functions */ 208169689Skan 209169689Skan/* Initialize the threads subsystem. */ 210169689Skanstatic inline int 211169689Skan__gthread_objc_init_thread_system (void) 212169689Skan{ 213169689Skan if (__gthread_active_p ()) 214169689Skan { 215169689Skan /* Initialize the thread storage key. */ 216169689Skan if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0) 217169689Skan { 218169689Skan /* The normal default detach state for threads is 219169689Skan * PTHREAD_CREATE_JOINABLE which causes threads to not die 220169689Skan * when you think they should. */ 221169689Skan if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0 222169689Skan && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs, 223169689Skan PTHREAD_CREATE_DETACHED) == 0) 224169689Skan return 0; 225169689Skan } 226169689Skan } 227169689Skan 228169689Skan return -1; 229169689Skan} 230169689Skan 231169689Skan/* Close the threads subsystem. */ 232169689Skanstatic inline int 233169689Skan__gthread_objc_close_thread_system (void) 234169689Skan{ 235169689Skan if (__gthread_active_p () 236169689Skan && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0 237169689Skan && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0) 238169689Skan return 0; 239169689Skan 240169689Skan return -1; 241169689Skan} 242169689Skan 243169689Skan/* Backend thread functions */ 244169689Skan 245169689Skan/* Create a new thread of execution. */ 246169689Skanstatic inline objc_thread_t 247169689Skan__gthread_objc_thread_detach (void (*func)(void *), void *arg) 248169689Skan{ 249169689Skan objc_thread_t thread_id; 250169689Skan pthread_t new_thread_handle; 251169689Skan 252169689Skan if (!__gthread_active_p ()) 253169689Skan return NULL; 254169689Skan 255169689Skan if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg))) 256169689Skan thread_id = (objc_thread_t) new_thread_handle; 257169689Skan else 258169689Skan thread_id = NULL; 259169689Skan 260169689Skan return thread_id; 261169689Skan} 262169689Skan 263169689Skan/* Set the current thread's priority. */ 264169689Skanstatic inline int 265169689Skan__gthread_objc_thread_set_priority (int priority) 266169689Skan{ 267169689Skan if (!__gthread_active_p ()) 268169689Skan return -1; 269169689Skan else 270169689Skan { 271169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING 272169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 273169689Skan pthread_t thread_id = __gthrw_(pthread_self) (); 274169689Skan int policy; 275169689Skan struct sched_param params; 276169689Skan int priority_min, priority_max; 277169689Skan 278169689Skan if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0) 279169689Skan { 280169689Skan if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1) 281169689Skan return -1; 282169689Skan 283169689Skan if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1) 284169689Skan return -1; 285169689Skan 286169689Skan if (priority > priority_max) 287169689Skan priority = priority_max; 288169689Skan else if (priority < priority_min) 289169689Skan priority = priority_min; 290169689Skan params.sched_priority = priority; 291169689Skan 292169689Skan /* 293169689Skan * The solaris 7 and several other man pages incorrectly state that 294169689Skan * this should be a pointer to policy but pthread.h is universally 295169689Skan * at odds with this. 296169689Skan */ 297169689Skan if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0) 298169689Skan return 0; 299169689Skan } 300169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 301169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */ 302169689Skan return -1; 303169689Skan } 304169689Skan} 305169689Skan 306169689Skan/* Return the current thread's priority. */ 307169689Skanstatic inline int 308169689Skan__gthread_objc_thread_get_priority (void) 309169689Skan{ 310169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING 311169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 312169689Skan if (__gthread_active_p ()) 313169689Skan { 314169689Skan int policy; 315169689Skan struct sched_param params; 316169689Skan 317169689Skan if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0) 318169689Skan return params.sched_priority; 319169689Skan else 320169689Skan return -1; 321169689Skan } 322169689Skan else 323169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 324169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */ 325169689Skan return OBJC_THREAD_INTERACTIVE_PRIORITY; 326169689Skan} 327169689Skan 328169689Skan/* Yield our process time to another thread. */ 329169689Skanstatic inline void 330169689Skan__gthread_objc_thread_yield (void) 331169689Skan{ 332169689Skan if (__gthread_active_p ()) 333169689Skan __gthrw_(sched_yield) (); 334169689Skan} 335169689Skan 336169689Skan/* Terminate the current thread. */ 337169689Skanstatic inline int 338169689Skan__gthread_objc_thread_exit (void) 339169689Skan{ 340169689Skan if (__gthread_active_p ()) 341169689Skan /* exit the thread */ 342169689Skan __gthrw_(pthread_exit) (&__objc_thread_exit_status); 343169689Skan 344169689Skan /* Failed if we reached here */ 345169689Skan return -1; 346169689Skan} 347169689Skan 348169689Skan/* Returns an integer value which uniquely describes a thread. */ 349169689Skanstatic inline objc_thread_t 350169689Skan__gthread_objc_thread_id (void) 351169689Skan{ 352169689Skan if (__gthread_active_p ()) 353169689Skan return (objc_thread_t) __gthrw_(pthread_self) (); 354169689Skan else 355169689Skan return (objc_thread_t) 1; 356169689Skan} 357169689Skan 358169689Skan/* Sets the thread's local storage pointer. */ 359169689Skanstatic inline int 360169689Skan__gthread_objc_thread_set_data (void *value) 361169689Skan{ 362169689Skan if (__gthread_active_p ()) 363169689Skan return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); 364169689Skan else 365169689Skan { 366169689Skan thread_local_storage = value; 367169689Skan return 0; 368169689Skan } 369169689Skan} 370169689Skan 371169689Skan/* Returns the thread's local storage pointer. */ 372169689Skanstatic inline void * 373169689Skan__gthread_objc_thread_get_data (void) 374169689Skan{ 375169689Skan if (__gthread_active_p ()) 376169689Skan return __gthrw_(pthread_getspecific) (_objc_thread_storage); 377169689Skan else 378169689Skan return thread_local_storage; 379169689Skan} 380169689Skan 381169689Skan/* Backend mutex functions */ 382169689Skan 383169689Skan/* Allocate a mutex. */ 384169689Skanstatic inline int 385169689Skan__gthread_objc_mutex_allocate (objc_mutex_t mutex) 386169689Skan{ 387169689Skan if (__gthread_active_p ()) 388169689Skan { 389169689Skan mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); 390169689Skan 391169689Skan if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL)) 392169689Skan { 393169689Skan objc_free (mutex->backend); 394169689Skan mutex->backend = NULL; 395169689Skan return -1; 396169689Skan } 397169689Skan } 398169689Skan 399169689Skan return 0; 400169689Skan} 401169689Skan 402169689Skan/* Deallocate a mutex. */ 403169689Skanstatic inline int 404169689Skan__gthread_objc_mutex_deallocate (objc_mutex_t mutex) 405169689Skan{ 406169689Skan if (__gthread_active_p ()) 407169689Skan { 408169689Skan int count; 409169689Skan 410169689Skan /* 411169689Skan * Posix Threads specifically require that the thread be unlocked 412169689Skan * for __gthrw_(pthread_mutex_destroy) to work. 413169689Skan */ 414169689Skan 415169689Skan do 416169689Skan { 417169689Skan count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); 418169689Skan if (count < 0) 419169689Skan return -1; 420169689Skan } 421169689Skan while (count); 422169689Skan 423169689Skan if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) 424169689Skan return -1; 425169689Skan 426169689Skan objc_free (mutex->backend); 427169689Skan mutex->backend = NULL; 428169689Skan } 429169689Skan return 0; 430169689Skan} 431169689Skan 432169689Skan/* Grab a lock on a mutex. */ 433169689Skanstatic inline int 434169689Skan__gthread_objc_mutex_lock (objc_mutex_t mutex) 435169689Skan{ 436169689Skan if (__gthread_active_p () 437169689Skan && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0) 438169689Skan { 439169689Skan return -1; 440169689Skan } 441169689Skan 442169689Skan return 0; 443169689Skan} 444169689Skan 445169689Skan/* Try to grab a lock on a mutex. */ 446169689Skanstatic inline int 447169689Skan__gthread_objc_mutex_trylock (objc_mutex_t mutex) 448169689Skan{ 449169689Skan if (__gthread_active_p () 450169689Skan && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0) 451169689Skan { 452169689Skan return -1; 453169689Skan } 454169689Skan 455169689Skan return 0; 456169689Skan} 457169689Skan 458169689Skan/* Unlock the mutex */ 459169689Skanstatic inline int 460169689Skan__gthread_objc_mutex_unlock (objc_mutex_t mutex) 461169689Skan{ 462169689Skan if (__gthread_active_p () 463169689Skan && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0) 464169689Skan { 465169689Skan return -1; 466169689Skan } 467169689Skan 468169689Skan return 0; 469169689Skan} 470169689Skan 471169689Skan/* Backend condition mutex functions */ 472169689Skan 473169689Skan/* Allocate a condition. */ 474169689Skanstatic inline int 475169689Skan__gthread_objc_condition_allocate (objc_condition_t condition) 476169689Skan{ 477169689Skan if (__gthread_active_p ()) 478169689Skan { 479169689Skan condition->backend = objc_malloc (sizeof (pthread_cond_t)); 480169689Skan 481169689Skan if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL)) 482169689Skan { 483169689Skan objc_free (condition->backend); 484169689Skan condition->backend = NULL; 485169689Skan return -1; 486169689Skan } 487169689Skan } 488169689Skan 489169689Skan return 0; 490169689Skan} 491169689Skan 492169689Skan/* Deallocate a condition. */ 493169689Skanstatic inline int 494169689Skan__gthread_objc_condition_deallocate (objc_condition_t condition) 495169689Skan{ 496169689Skan if (__gthread_active_p ()) 497169689Skan { 498169689Skan if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend)) 499169689Skan return -1; 500169689Skan 501169689Skan objc_free (condition->backend); 502169689Skan condition->backend = NULL; 503169689Skan } 504169689Skan return 0; 505169689Skan} 506169689Skan 507169689Skan/* Wait on the condition */ 508169689Skanstatic inline int 509169689Skan__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) 510169689Skan{ 511169689Skan if (__gthread_active_p ()) 512169689Skan return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend, 513169689Skan (pthread_mutex_t *) mutex->backend); 514169689Skan else 515169689Skan return 0; 516169689Skan} 517169689Skan 518169689Skan/* Wake up all threads waiting on this condition. */ 519169689Skanstatic inline int 520169689Skan__gthread_objc_condition_broadcast (objc_condition_t condition) 521169689Skan{ 522169689Skan if (__gthread_active_p ()) 523169689Skan return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend); 524169689Skan else 525169689Skan return 0; 526169689Skan} 527169689Skan 528169689Skan/* Wake up one thread waiting on this condition. */ 529169689Skanstatic inline int 530169689Skan__gthread_objc_condition_signal (objc_condition_t condition) 531169689Skan{ 532169689Skan if (__gthread_active_p ()) 533169689Skan return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend); 534169689Skan else 535169689Skan return 0; 536169689Skan} 537169689Skan 538169689Skan#else /* _LIBOBJC */ 539169689Skan 540169689Skanstatic inline int 541169689Skan__gthread_once (__gthread_once_t *once, void (*func) (void)) 542169689Skan{ 543169689Skan if (__gthread_active_p ()) 544169689Skan return __gthrw_(pthread_once) (once, func); 545169689Skan else 546169689Skan return -1; 547169689Skan} 548169689Skan 549169689Skanstatic inline int 550169689Skan__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) 551169689Skan{ 552169689Skan return __gthrw_(pthread_key_create) (key, dtor); 553169689Skan} 554169689Skan 555169689Skanstatic inline int 556169689Skan__gthread_key_delete (__gthread_key_t key) 557169689Skan{ 558169689Skan return __gthrw_(pthread_key_delete) (key); 559169689Skan} 560169689Skan 561169689Skanstatic inline void * 562169689Skan__gthread_getspecific (__gthread_key_t key) 563169689Skan{ 564169689Skan return __gthrw_(pthread_getspecific) (key); 565169689Skan} 566169689Skan 567169689Skanstatic inline int 568169689Skan__gthread_setspecific (__gthread_key_t key, const void *ptr) 569169689Skan{ 570169689Skan return __gthrw_(pthread_setspecific) (key, ptr); 571169689Skan} 572169689Skan 573169689Skanstatic inline int 574169689Skan__gthread_mutex_lock (__gthread_mutex_t *mutex) 575169689Skan{ 576169689Skan if (__gthread_active_p ()) 577169689Skan return __gthrw_(pthread_mutex_lock) (mutex); 578169689Skan else 579169689Skan return 0; 580169689Skan} 581169689Skan 582169689Skanstatic inline int 583169689Skan__gthread_mutex_trylock (__gthread_mutex_t *mutex) 584169689Skan{ 585169689Skan if (__gthread_active_p ()) 586169689Skan return __gthrw_(pthread_mutex_trylock) (mutex); 587169689Skan else 588169689Skan return 0; 589169689Skan} 590169689Skan 591169689Skanstatic inline int 592169689Skan__gthread_mutex_unlock (__gthread_mutex_t *mutex) 593169689Skan{ 594169689Skan if (__gthread_active_p ()) 595169689Skan return __gthrw_(pthread_mutex_unlock) (mutex); 596169689Skan else 597169689Skan return 0; 598169689Skan} 599169689Skan 600169689Skanstatic inline int 601169689Skan__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) 602169689Skan{ 603169689Skan mutex->depth = 0; 604169689Skan mutex->owner = (pthread_t) 0; 605169689Skan return __gthrw_(pthread_mutex_init) (&mutex->actual, NULL); 606169689Skan} 607169689Skan 608169689Skanstatic inline int 609169689Skan__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) 610169689Skan{ 611169689Skan if (__gthread_active_p ()) 612169689Skan { 613169689Skan pthread_t me = __gthrw_(pthread_self) (); 614169689Skan 615169689Skan if (mutex->owner != me) 616169689Skan { 617169689Skan __gthrw_(pthread_mutex_lock) (&mutex->actual); 618169689Skan mutex->owner = me; 619169689Skan } 620169689Skan 621169689Skan mutex->depth++; 622169689Skan } 623169689Skan return 0; 624169689Skan} 625169689Skan 626169689Skanstatic inline int 627169689Skan__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) 628169689Skan{ 629169689Skan if (__gthread_active_p ()) 630169689Skan { 631169689Skan pthread_t me = __gthrw_(pthread_self) (); 632169689Skan 633169689Skan if (mutex->owner != me) 634169689Skan { 635169689Skan if (__gthrw_(pthread_mutex_trylock) (&mutex->actual)) 636169689Skan return 1; 637169689Skan mutex->owner = me; 638169689Skan } 639169689Skan 640169689Skan mutex->depth++; 641169689Skan } 642169689Skan return 0; 643169689Skan} 644169689Skan 645169689Skanstatic inline int 646169689Skan__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) 647169689Skan{ 648169689Skan if (__gthread_active_p ()) 649169689Skan { 650169689Skan if (--mutex->depth == 0) 651169689Skan { 652169689Skan mutex->owner = (pthread_t) 0; 653169689Skan __gthrw_(pthread_mutex_unlock) (&mutex->actual); 654169689Skan } 655169689Skan } 656169689Skan return 0; 657169689Skan} 658169689Skan 659169689Skan#endif /* _LIBOBJC */ 660169689Skan 661169689Skan#endif /* ! GCC_GTHR_POSIX_H */ 662