1/* Threads compatibility routines for libgcc2 and libobjc. */ 2/* Compile this one with gcc. */ 3/* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011 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 3, 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 18Under Section 7 of GPL version 3, you are granted additional 19permissions described in the GCC Runtime Library Exception, version 203.1, as published by the Free Software Foundation. 21 22You should have received a copy of the GNU General Public License and 23a copy of the GCC Runtime Library Exception along with this program; 24see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 25<http://www.gnu.org/licenses/>. */ 26 27#ifndef GCC_GTHR_POSIX_H 28#define GCC_GTHR_POSIX_H 29 30/* POSIX threads specific definitions. 31 Easy, since the interface is just one-to-one mapping. */ 32 33#define __GTHREADS 1 34 35/* Some implementations of <pthread.h> require this to be defined. */ 36#ifndef _REENTRANT 37#define _REENTRANT 1 38#endif 39 40#include <pthread.h> 41#include <unistd.h> 42 43typedef pthread_key_t __gthread_key_t; 44typedef pthread_once_t __gthread_once_t; 45typedef pthread_mutex_t __gthread_mutex_t; 46typedef pthread_cond_t __gthread_cond_t; 47 48/* POSIX like conditional variables are supported. Please look at comments 49 in gthr.h for details. */ 50#define __GTHREAD_HAS_COND 1 51 52typedef struct { 53 long depth; 54 pthread_t owner; 55 pthread_mutex_t actual; 56} __gthread_recursive_mutex_t; 57 58#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER 59#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT 60#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 61#define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER 62 63#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 64# define __gthrw(name) \ 65 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))); 66# define __gthrw_(name) __gthrw_ ## name 67#else 68# define __gthrw(name) 69# define __gthrw_(name) name 70#endif 71 72__gthrw(pthread_once) 73__gthrw(pthread_key_create) 74__gthrw(pthread_key_delete) 75__gthrw(pthread_getspecific) 76__gthrw(pthread_setspecific) 77__gthrw(pthread_create) 78__gthrw(pthread_cancel) 79__gthrw(pthread_self) 80 81__gthrw(pthread_mutex_init) 82__gthrw(pthread_mutex_destroy) 83__gthrw(pthread_mutex_lock) 84__gthrw(pthread_mutex_trylock) 85__gthrw(pthread_mutex_unlock) 86__gthrw(pthread_mutexattr_init) 87__gthrw(pthread_mutexattr_destroy) 88 89__gthrw(pthread_cond_broadcast) 90__gthrw(pthread_cond_wait) 91 92#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) 93/* Objective-C. */ 94__gthrw(pthread_cond_destroy) 95__gthrw(pthread_cond_init) 96__gthrw(pthread_cond_signal) 97__gthrw(pthread_exit) 98#ifdef _POSIX_PRIORITY_SCHEDULING 99#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 100__gthrw(sched_get_priority_max) 101__gthrw(sched_get_priority_min) 102#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 103#endif /* _POSIX_PRIORITY_SCHEDULING */ 104__gthrw(sched_yield) 105__gthrw(pthread_attr_destroy) 106__gthrw(pthread_attr_init) 107__gthrw(pthread_attr_setdetachstate) 108#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 109__gthrw(pthread_getschedparam) 110__gthrw(pthread_setschedparam) 111#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 112#endif /* _LIBOBJC || _LIBOBJC_WEAK */ 113 114#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 115 116/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if 117 -pthreads is not specified. The functions are dummies and most return an 118 error value. However pthread_once returns 0 without invoking the routine 119 it is passed so we cannot pretend that the interface is active if -pthreads 120 is not specified. On Solaris 2.5.1, the interface is not exposed at all so 121 we need to play the usual game with weak symbols. On Solaris 10 and up, a 122 working interface is always exposed. On FreeBSD 6 and later, libc also 123 exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up 124 to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc, 125 which means the alternate __gthread_active_p below cannot be used there. */ 126 127#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__)) 128 129static volatile int __gthread_active = -1; 130 131static void 132__gthread_trigger (void) 133{ 134 __gthread_active = 1; 135} 136 137static inline int 138__gthread_active_p (void) 139{ 140 static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; 141 static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT; 142 143 /* Avoid reading __gthread_active twice on the main code path. */ 144 int __gthread_active_latest_value = __gthread_active; 145 146 /* This test is not protected to avoid taking a lock on the main code 147 path so every update of __gthread_active in a threaded program must 148 be atomic with regard to the result of the test. */ 149 if (__builtin_expect (__gthread_active_latest_value < 0, 0)) 150 { 151 if (__gthrw_(pthread_once)) 152 { 153 /* If this really is a threaded program, then we must ensure that 154 __gthread_active has been set to 1 before exiting this block. */ 155 __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); 156 __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger); 157 __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); 158 } 159 160 /* Make sure we'll never enter this block again. */ 161 if (__gthread_active < 0) 162 __gthread_active = 0; 163 164 __gthread_active_latest_value = __gthread_active; 165 } 166 167 return __gthread_active_latest_value != 0; 168} 169 170#else /* neither FreeBSD nor Solaris */ 171 172static inline int 173__gthread_active_p (void) 174{ 175 static void *const __gthread_active_ptr 176 = __extension__ (void *) &__gthrw_(pthread_cancel); 177 return __gthread_active_ptr != 0; 178} 179 180#endif /* FreeBSD or Solaris */ 181 182#else /* not SUPPORTS_WEAK */ 183 184/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread 185 calls in shared flavors of the HP-UX C library. Most of the stubs 186 have no functionality. The details are described in the "libc cumulative 187 patch" for each subversion of HP-UX 11. There are two special interfaces 188 provided for checking whether an application is linked to a shared pthread 189 library or not. However, these interfaces aren't available in early 190 pthread libraries. We also need a test that works for archive 191 libraries. We can't use pthread_once as some libc versions call the 192 init function. We also can't use pthread_create or pthread_attr_init 193 as these create a thread and thereby prevent changing the default stack 194 size. The function pthread_default_stacksize_np is available in both 195 the archive and shared versions of libpthread. It can be used to 196 determine the default pthread stack size. There is a stub in some 197 shared libc versions which returns a zero size if pthreads are not 198 active. We provide an equivalent stub to handle cases where libc 199 doesn't provide one. */ 200 201#if defined(__hppa__) && defined(__hpux__) 202 203static volatile int __gthread_active = -1; 204 205static inline int 206__gthread_active_p (void) 207{ 208 /* Avoid reading __gthread_active twice on the main code path. */ 209 int __gthread_active_latest_value = __gthread_active; 210 size_t __s; 211 212 if (__builtin_expect (__gthread_active_latest_value < 0, 0)) 213 { 214 pthread_default_stacksize_np (0, &__s); 215 __gthread_active = __s ? 1 : 0; 216 __gthread_active_latest_value = __gthread_active; 217 } 218 219 return __gthread_active_latest_value != 0; 220} 221 222#else /* not hppa-hpux */ 223 224static inline int 225__gthread_active_p (void) 226{ 227 return 1; 228} 229 230#endif /* hppa-hpux */ 231 232#endif /* SUPPORTS_WEAK */ 233 234#ifdef _LIBOBJC 235 236/* This is the config.h file in libobjc/ */ 237#include <config.h> 238 239#ifdef HAVE_SCHED_H 240# include <sched.h> 241#endif 242 243/* Key structure for maintaining thread specific storage */ 244static pthread_key_t _objc_thread_storage; 245static pthread_attr_t _objc_thread_attribs; 246 247/* Thread local storage for a single thread */ 248static void *thread_local_storage = NULL; 249 250/* Backend initialization functions */ 251 252/* Initialize the threads subsystem. */ 253static inline int 254__gthread_objc_init_thread_system (void) 255{ 256 if (__gthread_active_p ()) 257 { 258 /* Initialize the thread storage key. */ 259 if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0) 260 { 261 /* The normal default detach state for threads is 262 * PTHREAD_CREATE_JOINABLE which causes threads to not die 263 * when you think they should. */ 264 if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0 265 && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs, 266 PTHREAD_CREATE_DETACHED) == 0) 267 return 0; 268 } 269 } 270 271 return -1; 272} 273 274/* Close the threads subsystem. */ 275static inline int 276__gthread_objc_close_thread_system (void) 277{ 278 if (__gthread_active_p () 279 && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0 280 && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0) 281 return 0; 282 283 return -1; 284} 285 286/* Backend thread functions */ 287 288/* Create a new thread of execution. */ 289static inline objc_thread_t 290__gthread_objc_thread_detach (void (*func)(void *), void *arg) 291{ 292 objc_thread_t thread_id; 293 pthread_t new_thread_handle; 294 295 if (!__gthread_active_p ()) 296 return NULL; 297 298 if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg))) 299 thread_id = (objc_thread_t) new_thread_handle; 300 else 301 thread_id = NULL; 302 303 return thread_id; 304} 305 306/* Set the current thread's priority. */ 307static inline int 308__gthread_objc_thread_set_priority (int priority) 309{ 310 if (!__gthread_active_p ()) 311 return -1; 312 else 313 { 314#ifdef _POSIX_PRIORITY_SCHEDULING 315#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 316 pthread_t thread_id = __gthrw_(pthread_self) (); 317 int policy; 318 struct sched_param params; 319 int priority_min, priority_max; 320 321 if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0) 322 { 323 if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1) 324 return -1; 325 326 if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1) 327 return -1; 328 329 if (priority > priority_max) 330 priority = priority_max; 331 else if (priority < priority_min) 332 priority = priority_min; 333 params.sched_priority = priority; 334 335 /* 336 * The solaris 7 and several other man pages incorrectly state that 337 * this should be a pointer to policy but pthread.h is universally 338 * at odds with this. 339 */ 340 if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0) 341 return 0; 342 } 343#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 344#endif /* _POSIX_PRIORITY_SCHEDULING */ 345 return -1; 346 } 347} 348 349/* Return the current thread's priority. */ 350static inline int 351__gthread_objc_thread_get_priority (void) 352{ 353#ifdef _POSIX_PRIORITY_SCHEDULING 354#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING 355 if (__gthread_active_p ()) 356 { 357 int policy; 358 struct sched_param params; 359 360 if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0) 361 return params.sched_priority; 362 else 363 return -1; 364 } 365 else 366#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ 367#endif /* _POSIX_PRIORITY_SCHEDULING */ 368 return OBJC_THREAD_INTERACTIVE_PRIORITY; 369} 370 371/* Yield our process time to another thread. */ 372static inline void 373__gthread_objc_thread_yield (void) 374{ 375 if (__gthread_active_p ()) 376 __gthrw_(sched_yield) (); 377} 378 379/* Terminate the current thread. */ 380static inline int 381__gthread_objc_thread_exit (void) 382{ 383 if (__gthread_active_p ()) 384 /* exit the thread */ 385 __gthrw_(pthread_exit) (&__objc_thread_exit_status); 386 387 /* Failed if we reached here */ 388 return -1; 389} 390 391/* Returns an integer value which uniquely describes a thread. */ 392static inline objc_thread_t 393__gthread_objc_thread_id (void) 394{ 395 if (__gthread_active_p ()) 396 return (objc_thread_t) __gthrw_(pthread_self) (); 397 else 398 return (objc_thread_t) 1; 399} 400 401/* Sets the thread's local storage pointer. */ 402static inline int 403__gthread_objc_thread_set_data (void *value) 404{ 405 if (__gthread_active_p ()) 406 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); 407 else 408 { 409 thread_local_storage = value; 410 return 0; 411 } 412} 413 414/* Returns the thread's local storage pointer. */ 415static inline void * 416__gthread_objc_thread_get_data (void) 417{ 418 if (__gthread_active_p ()) 419 return __gthrw_(pthread_getspecific) (_objc_thread_storage); 420 else 421 return thread_local_storage; 422} 423 424/* Backend mutex functions */ 425 426/* Allocate a mutex. */ 427static inline int 428__gthread_objc_mutex_allocate (objc_mutex_t mutex) 429{ 430 if (__gthread_active_p ()) 431 { 432 mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); 433 434 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL)) 435 { 436 objc_free (mutex->backend); 437 mutex->backend = NULL; 438 return -1; 439 } 440 } 441 442 return 0; 443} 444 445/* Deallocate a mutex. */ 446static inline int 447__gthread_objc_mutex_deallocate (objc_mutex_t mutex) 448{ 449 if (__gthread_active_p ()) 450 { 451 int count; 452 453 /* 454 * Posix Threads specifically require that the thread be unlocked 455 * for __gthrw_(pthread_mutex_destroy) to work. 456 */ 457 458 do 459 { 460 count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); 461 if (count < 0) 462 return -1; 463 } 464 while (count); 465 466 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) 467 return -1; 468 469 objc_free (mutex->backend); 470 mutex->backend = NULL; 471 } 472 return 0; 473} 474 475/* Grab a lock on a mutex. */ 476static inline int 477__gthread_objc_mutex_lock (objc_mutex_t mutex) 478{ 479 if (__gthread_active_p () 480 && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0) 481 { 482 return -1; 483 } 484 485 return 0; 486} 487 488/* Try to grab a lock on a mutex. */ 489static inline int 490__gthread_objc_mutex_trylock (objc_mutex_t mutex) 491{ 492 if (__gthread_active_p () 493 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0) 494 { 495 return -1; 496 } 497 498 return 0; 499} 500 501/* Unlock the mutex */ 502static inline int 503__gthread_objc_mutex_unlock (objc_mutex_t mutex) 504{ 505 if (__gthread_active_p () 506 && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0) 507 { 508 return -1; 509 } 510 511 return 0; 512} 513 514/* Backend condition mutex functions */ 515 516/* Allocate a condition. */ 517static inline int 518__gthread_objc_condition_allocate (objc_condition_t condition) 519{ 520 if (__gthread_active_p ()) 521 { 522 condition->backend = objc_malloc (sizeof (pthread_cond_t)); 523 524 if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL)) 525 { 526 objc_free (condition->backend); 527 condition->backend = NULL; 528 return -1; 529 } 530 } 531 532 return 0; 533} 534 535/* Deallocate a condition. */ 536static inline int 537__gthread_objc_condition_deallocate (objc_condition_t condition) 538{ 539 if (__gthread_active_p ()) 540 { 541 if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend)) 542 return -1; 543 544 objc_free (condition->backend); 545 condition->backend = NULL; 546 } 547 return 0; 548} 549 550/* Wait on the condition */ 551static inline int 552__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) 553{ 554 if (__gthread_active_p ()) 555 return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend, 556 (pthread_mutex_t *) mutex->backend); 557 else 558 return 0; 559} 560 561/* Wake up all threads waiting on this condition. */ 562static inline int 563__gthread_objc_condition_broadcast (objc_condition_t condition) 564{ 565 if (__gthread_active_p ()) 566 return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend); 567 else 568 return 0; 569} 570 571/* Wake up one thread waiting on this condition. */ 572static inline int 573__gthread_objc_condition_signal (objc_condition_t condition) 574{ 575 if (__gthread_active_p ()) 576 return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend); 577 else 578 return 0; 579} 580 581#else /* _LIBOBJC */ 582 583static inline int 584__gthread_once (__gthread_once_t *__once, void (*__func) (void)) 585{ 586 if (__gthread_active_p ()) 587 return __gthrw_(pthread_once) (__once, __func); 588 else 589 return -1; 590} 591 592static inline int 593__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) 594{ 595 return __gthrw_(pthread_key_create) (__key, __dtor); 596} 597 598static inline int 599__gthread_key_delete (__gthread_key_t __key) 600{ 601 return __gthrw_(pthread_key_delete) (__key); 602} 603 604static inline void * 605__gthread_getspecific (__gthread_key_t __key) 606{ 607 return __gthrw_(pthread_getspecific) (__key); 608} 609 610static inline int 611__gthread_setspecific (__gthread_key_t __key, const void *__ptr) 612{ 613 return __gthrw_(pthread_setspecific) (__key, __ptr); 614} 615 616static inline int 617__gthread_mutex_destroy (__gthread_mutex_t *__mutex) 618{ 619 if (__gthread_active_p ()) 620 return __gthrw_(pthread_mutex_destroy) (__mutex); 621 else 622 return 0; 623} 624 625static inline int 626__gthread_mutex_lock (__gthread_mutex_t *__mutex) 627{ 628 if (__gthread_active_p ()) 629 return __gthrw_(pthread_mutex_lock) (__mutex); 630 else 631 return 0; 632} 633 634static inline int 635__gthread_mutex_trylock (__gthread_mutex_t *__mutex) 636{ 637 if (__gthread_active_p ()) 638 return __gthrw_(pthread_mutex_trylock) (__mutex); 639 else 640 return 0; 641} 642 643static inline int 644__gthread_mutex_unlock (__gthread_mutex_t *__mutex) 645{ 646 if (__gthread_active_p ()) 647 return __gthrw_(pthread_mutex_unlock) (__mutex); 648 else 649 return 0; 650} 651 652static inline int 653__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) 654{ 655 __mutex->depth = 0; 656 __mutex->owner = (pthread_t) 0; 657 return __gthrw_(pthread_mutex_init) (&__mutex->actual, NULL); 658} 659 660static inline int 661__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) 662{ 663 if (__gthread_active_p ()) 664 { 665 pthread_t __me = __gthrw_(pthread_self) (); 666 667 if (__mutex->owner != __me) 668 { 669 __gthrw_(pthread_mutex_lock) (&__mutex->actual); 670 __mutex->owner = __me; 671 } 672 673 __mutex->depth++; 674 } 675 return 0; 676} 677 678static inline int 679__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) 680{ 681 if (__gthread_active_p ()) 682 { 683 pthread_t __me = __gthrw_(pthread_self) (); 684 685 if (__mutex->owner != __me) 686 { 687 if (__gthrw_(pthread_mutex_trylock) (&__mutex->actual)) 688 return 1; 689 __mutex->owner = __me; 690 } 691 692 __mutex->depth++; 693 } 694 return 0; 695} 696 697static inline int 698__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) 699{ 700 if (__gthread_active_p ()) 701 { 702 if (--__mutex->depth == 0) 703 { 704 __mutex->owner = (pthread_t) 0; 705 __gthrw_(pthread_mutex_unlock) (&__mutex->actual); 706 } 707 } 708 return 0; 709} 710 711static inline int 712__gthread_cond_broadcast (__gthread_cond_t *__cond) 713{ 714 return __gthrw_(pthread_cond_broadcast) (__cond); 715} 716 717static inline int 718__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex) 719{ 720 return __gthrw_(pthread_cond_wait) (__cond, __mutex); 721} 722 723static inline int 724__gthread_cond_wait_recursive (__gthread_cond_t *__cond, 725 __gthread_recursive_mutex_t *__mutex) 726{ 727 return __gthrw_(pthread_cond_wait) (__cond, &__mutex->actual); 728} 729 730#endif /* _LIBOBJC */ 731 732#endif /* ! GCC_GTHR_POSIX_H */ 733