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