1/* Threads compatibility routines for libgcc2 and libobjc. */ 2/* Compile this one with gcc. */ 3/* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 4 Free Software Foundation, Inc. 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING. If not, write to the Free 20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2102110-1301, USA. */ 22 23/* As a special exception, if you link this library with other files, 24 some of which are compiled with GCC, to produce an executable, 25 this library does not by itself cause the resulting executable 26 to be covered by the GNU General Public License. 27 This exception does not however invalidate any other reasons why 28 the executable file might be covered by the GNU General Public License. */ 29 30#ifndef GCC_GTHR_POSIX_H 31#define GCC_GTHR_POSIX_H 32 33/* POSIX threads specific definitions. 34 Easy, since the interface is just one-to-one mapping. */ 35 36#define __GTHREADS 1 37 38/* Some implementations of <pthread.h> require this to be defined. */ 39#if !defined(_REENTRANT) && defined(__osf__) 40#define _REENTRANT 1 41#endif 42 43#include <pthread.h> 44#include <unistd.h> 45 46typedef pthread_key_t __gthread_key_t; 47typedef pthread_once_t __gthread_once_t; 48typedef pthread_mutex_t __gthread_mutex_t; 49typedef pthread_mutex_t __gthread_recursive_mutex_t; 50 51#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER 52#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT 53#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER) 54#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER 55#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) 56#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 57#else 58#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 59#endif 60 61#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 62# ifndef __gthrw_pragma 63# define __gthrw_pragma(pragma) 64# endif 65# ifdef __clang__ 66# define __gthrw2(name,name2,type) \ 67 static __typeof(type) name __attribute__ ((__weakref__(#name2))); \ 68 __gthrw_pragma(weak type) 69# else 70# define __gthrw2(name,name2,type) \ 71 extern __typeof(type) name __attribute__ ((__weakref__(#name2))); \ 72 __gthrw_pragma(weak type) 73# endif 74# define __gthrw_(name) __gthrw_ ## name 75#else 76# define __gthrw2(name,name2,type) 77# define __gthrw_(name) name 78#endif 79 80/* Typically, __gthrw_foo is a weak reference to symbol foo. */ 81#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name) 82 83/* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to 84 map a subset of the POSIX pthread API to mangled versions of their 85 names. */ 86#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_) 87#define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name) 88__gthrw3(pthread_once) 89__gthrw3(pthread_getspecific) 90__gthrw3(pthread_setspecific) 91__gthrw3(pthread_create) 92__gthrw3(pthread_cancel) 93__gthrw3(pthread_mutex_lock) 94__gthrw3(pthread_mutex_trylock) 95__gthrw3(pthread_mutex_unlock) 96__gthrw3(pthread_mutex_init) 97#else 98__gthrw(pthread_once) 99__gthrw(pthread_getspecific) 100__gthrw(pthread_setspecific) 101__gthrw(pthread_create) 102__gthrw(pthread_cancel) 103__gthrw(pthread_mutex_lock) 104__gthrw(pthread_mutex_trylock) 105__gthrw(pthread_mutex_unlock) 106__gthrw(pthread_mutex_init) 107#endif 108 109__gthrw(pthread_key_create) 110__gthrw(pthread_key_delete) 111__gthrw(pthread_mutexattr_init) 112__gthrw(pthread_mutexattr_settype) 113__gthrw(pthread_mutexattr_destroy) 114 115 116#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) 117/* Objective-C. */ 118#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_) 119__gthrw3(pthread_cond_broadcast) 120__gthrw3(pthread_cond_destroy) 121__gthrw3(pthread_cond_init) 122__gthrw3(pthread_cond_signal) 123__gthrw3(pthread_cond_wait) 124__gthrw3(pthread_exit) 125__gthrw3(pthread_mutex_destroy) 126__gthrw3(pthread_self) 127#else 128__gthrw(pthread_cond_broadcast) 129__gthrw(pthread_cond_destroy) 130__gthrw(pthread_cond_init) 131__gthrw(pthread_cond_signal) 132__gthrw(pthread_cond_wait) 133__gthrw(pthread_exit) 134__gthrw(pthread_mutex_destroy) 135__gthrw(pthread_self) 136#endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */ 137#ifdef _POSIX_PRIORITY_SCHEDULING 138#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 139__gthrw(sched_get_priority_max) 140__gthrw(sched_get_priority_min) 141#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 142#endif /* _POSIX_PRIORITY_SCHEDULING */ 143__gthrw(sched_yield) 144__gthrw(pthread_attr_destroy) 145__gthrw(pthread_attr_init) 146__gthrw(pthread_attr_setdetachstate) 147#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 148__gthrw(pthread_getschedparam) 149__gthrw(pthread_setschedparam) 150#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 151#endif /* _LIBOBJC || _LIBOBJC_WEAK */ 152 153#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 154 155static inline int 156__gthread_active_p (void) 157{ 158 static void *const __gthread_active_ptr 159 = __extension__ (void *) &__gthrw_(pthread_cancel); 160 return __gthread_active_ptr != 0; 161} 162 163#else /* not SUPPORTS_WEAK */ 164 165static inline int 166__gthread_active_p (void) 167{ 168 return 1; 169} 170 171#endif /* SUPPORTS_WEAK */ 172 173#ifdef _LIBOBJC 174 175/* This is the config.h file in libobjc/ */ 176#include <config.h> 177 178#ifdef HAVE_SCHED_H 179# include <sched.h> 180#endif 181 182/* Key structure for maintaining thread specific storage */ 183static pthread_key_t _objc_thread_storage; 184static pthread_attr_t _objc_thread_attribs; 185 186/* Thread local storage for a single thread */ 187static void *thread_local_storage = NULL; 188 189/* Backend initialization functions */ 190 191/* Initialize the threads subsystem. */ 192static inline int 193__gthread_objc_init_thread_system (void) 194{ 195 if (__gthread_active_p ()) 196 { 197 /* Initialize the thread storage key. */ 198 if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0) 199 { 200 /* The normal default detach state for threads is 201 * PTHREAD_CREATE_JOINABLE which causes threads to not die 202 * when you think they should. */ 203 if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0 204 && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs, 205 PTHREAD_CREATE_DETACHED) == 0) 206 return 0; 207 } 208 } 209 210 return -1; 211} 212 213/* Close the threads subsystem. */ 214static inline int 215__gthread_objc_close_thread_system (void) 216{ 217 if (__gthread_active_p () 218 && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0 219 && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0) 220 return 0; 221 222 return -1; 223} 224 225/* Backend thread functions */ 226 227/* Create a new thread of execution. */ 228static inline objc_thread_t 229__gthread_objc_thread_detach (void (*func)(void *), void *arg) 230{ 231 objc_thread_t thread_id; 232 pthread_t new_thread_handle; 233 234 if (!__gthread_active_p ()) 235 return NULL; 236 237 if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg))) 238 thread_id = (objc_thread_t) new_thread_handle; 239 else 240 thread_id = NULL; 241 242 return thread_id; 243} 244 245/* Set the current thread's priority. */ 246static inline int 247__gthread_objc_thread_set_priority (int priority) 248{ 249 if (!__gthread_active_p ()) 250 return -1; 251 else 252 { 253#ifdef _POSIX_PRIORITY_SCHEDULING 254#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 255 pthread_t thread_id = __gthrw_(pthread_self) (); 256 int policy; 257 struct sched_param params; 258 int priority_min, priority_max; 259 260 if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0) 261 { 262 if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1) 263 return -1; 264 265 if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1) 266 return -1; 267 268 if (priority > priority_max) 269 priority = priority_max; 270 else if (priority < priority_min) 271 priority = priority_min; 272 params.sched_priority = priority; 273 274 /* 275 * The solaris 7 and several other man pages incorrectly state that 276 * this should be a pointer to policy but pthread.h is universally 277 * at odds with this. 278 */ 279 if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0) 280 return 0; 281 } 282#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 283#endif /* _POSIX_PRIORITY_SCHEDULING */ 284 return -1; 285 } 286} 287 288/* Return the current thread's priority. */ 289static inline int 290__gthread_objc_thread_get_priority (void) 291{ 292#ifdef _POSIX_PRIORITY_SCHEDULING 293#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 294 if (__gthread_active_p ()) 295 { 296 int policy; 297 struct sched_param params; 298 299 if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0) 300 return params.sched_priority; 301 else 302 return -1; 303 } 304 else 305#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 306#endif /* _POSIX_PRIORITY_SCHEDULING */ 307 return OBJC_THREAD_INTERACTIVE_PRIORITY; 308} 309 310/* Yield our process time to another thread. */ 311static inline void 312__gthread_objc_thread_yield (void) 313{ 314 if (__gthread_active_p ()) 315 __gthrw_(sched_yield) (); 316} 317 318/* Terminate the current thread. */ 319static inline int 320__gthread_objc_thread_exit (void) 321{ 322 if (__gthread_active_p ()) 323 /* exit the thread */ 324 __gthrw_(pthread_exit) (&__objc_thread_exit_status); 325 326 /* Failed if we reached here */ 327 return -1; 328} 329 330/* Returns an integer value which uniquely describes a thread. */ 331static inline objc_thread_t 332__gthread_objc_thread_id (void) 333{ 334 if (__gthread_active_p ()) 335 return (objc_thread_t) __gthrw_(pthread_self) (); 336 else 337 return (objc_thread_t) 1; 338} 339 340/* Sets the thread's local storage pointer. */ 341static inline int 342__gthread_objc_thread_set_data (void *value) 343{ 344 if (__gthread_active_p ()) 345 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); 346 else 347 { 348 thread_local_storage = value; 349 return 0; 350 } 351} 352 353/* Returns the thread's local storage pointer. */ 354static inline void * 355__gthread_objc_thread_get_data (void) 356{ 357 if (__gthread_active_p ()) 358 return __gthrw_(pthread_getspecific) (_objc_thread_storage); 359 else 360 return thread_local_storage; 361} 362 363/* Backend mutex functions */ 364 365/* Allocate a mutex. */ 366static inline int 367__gthread_objc_mutex_allocate (objc_mutex_t mutex) 368{ 369 if (__gthread_active_p ()) 370 { 371 mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); 372 373 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL)) 374 { 375 objc_free (mutex->backend); 376 mutex->backend = NULL; 377 return -1; 378 } 379 } 380 381 return 0; 382} 383 384/* Deallocate a mutex. */ 385static inline int 386__gthread_objc_mutex_deallocate (objc_mutex_t mutex) 387{ 388 if (__gthread_active_p ()) 389 { 390 int count; 391 392 /* 393 * Posix Threads specifically require that the thread be unlocked 394 * for __gthrw_(pthread_mutex_destroy) to work. 395 */ 396 397 do 398 { 399 count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); 400 if (count < 0) 401 return -1; 402 } 403 while (count); 404 405 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) 406 return -1; 407 408 objc_free (mutex->backend); 409 mutex->backend = NULL; 410 } 411 return 0; 412} 413 414/* Grab a lock on a mutex. */ 415static inline int 416__gthread_objc_mutex_lock (objc_mutex_t mutex) 417{ 418 if (__gthread_active_p () 419 && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0) 420 { 421 return -1; 422 } 423 424 return 0; 425} 426 427/* Try to grab a lock on a mutex. */ 428static inline int 429__gthread_objc_mutex_trylock (objc_mutex_t mutex) 430{ 431 if (__gthread_active_p () 432 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0) 433 { 434 return -1; 435 } 436 437 return 0; 438} 439 440/* Unlock the mutex */ 441static inline int 442__gthread_objc_mutex_unlock (objc_mutex_t mutex) 443{ 444 if (__gthread_active_p () 445 && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0) 446 { 447 return -1; 448 } 449 450 return 0; 451} 452 453/* Backend condition mutex functions */ 454 455/* Allocate a condition. */ 456static inline int 457__gthread_objc_condition_allocate (objc_condition_t condition) 458{ 459 if (__gthread_active_p ()) 460 { 461 condition->backend = objc_malloc (sizeof (pthread_cond_t)); 462 463 if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL)) 464 { 465 objc_free (condition->backend); 466 condition->backend = NULL; 467 return -1; 468 } 469 } 470 471 return 0; 472} 473 474/* Deallocate a condition. */ 475static inline int 476__gthread_objc_condition_deallocate (objc_condition_t condition) 477{ 478 if (__gthread_active_p ()) 479 { 480 if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend)) 481 return -1; 482 483 objc_free (condition->backend); 484 condition->backend = NULL; 485 } 486 return 0; 487} 488 489/* Wait on the condition */ 490static inline int 491__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) 492{ 493 if (__gthread_active_p ()) 494 return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend, 495 (pthread_mutex_t *) mutex->backend); 496 else 497 return 0; 498} 499 500/* Wake up all threads waiting on this condition. */ 501static inline int 502__gthread_objc_condition_broadcast (objc_condition_t condition) 503{ 504 if (__gthread_active_p ()) 505 return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend); 506 else 507 return 0; 508} 509 510/* Wake up one thread waiting on this condition. */ 511static inline int 512__gthread_objc_condition_signal (objc_condition_t condition) 513{ 514 if (__gthread_active_p ()) 515 return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend); 516 else 517 return 0; 518} 519 520#else /* _LIBOBJC */ 521 522static inline int 523__gthread_once (__gthread_once_t *once, void (*func) (void)) 524{ 525 if (__gthread_active_p ()) 526 return __gthrw_(pthread_once) (once, func); 527 else 528 return -1; 529} 530 531static inline int 532__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) 533{ 534 return __gthrw_(pthread_key_create) (key, dtor); 535} 536 537static inline int 538__gthread_key_delete (__gthread_key_t key) 539{ 540 return __gthrw_(pthread_key_delete) (key); 541} 542 543static inline void * 544__gthread_getspecific (__gthread_key_t key) 545{ 546 return __gthrw_(pthread_getspecific) (key); 547} 548 549static inline int 550__gthread_setspecific (__gthread_key_t key, const void *ptr) 551{ 552 return __gthrw_(pthread_setspecific) (key, ptr); 553} 554 555static inline int 556__gthread_mutex_lock (__gthread_mutex_t *mutex) 557{ 558 if (__gthread_active_p ()) 559 return __gthrw_(pthread_mutex_lock) (mutex); 560 else 561 return 0; 562} 563 564static inline int 565__gthread_mutex_trylock (__gthread_mutex_t *mutex) 566{ 567 if (__gthread_active_p ()) 568 return __gthrw_(pthread_mutex_trylock) (mutex); 569 else 570 return 0; 571} 572 573static inline int 574__gthread_mutex_unlock (__gthread_mutex_t *mutex) 575{ 576 if (__gthread_active_p ()) 577 return __gthrw_(pthread_mutex_unlock) (mutex); 578 else 579 return 0; 580} 581 582#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 583static inline int 584__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) 585{ 586 if (__gthread_active_p ()) 587 { 588 pthread_mutexattr_t attr; 589 int r; 590 591 r = __gthrw_(pthread_mutexattr_init) (&attr); 592 if (!r) 593 r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE); 594 if (!r) 595 r = __gthrw_(pthread_mutex_init) (mutex, &attr); 596 if (!r) 597 r = __gthrw_(pthread_mutexattr_destroy) (&attr); 598 return r; 599 } 600 return 0; 601} 602#endif 603 604static inline int 605__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) 606{ 607 return __gthread_mutex_lock (mutex); 608} 609 610static inline int 611__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) 612{ 613 return __gthread_mutex_trylock (mutex); 614} 615 616static inline int 617__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) 618{ 619 return __gthread_mutex_unlock (mutex); 620} 621 622#endif /* _LIBOBJC */ 623 624#endif /* ! GCC_GTHR_POSIX_H */ 625