1/* Threads compatibility routines for libgcc2 and libobjc. */ 2/* Compile this one with gcc. */ 3/* Copyright (C) 1997, 1999, 2000, 2001, 2004, 2005, 2008, 2009 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_DCE_H 28#define GCC_GTHR_DCE_H 29 30/* If _DCE_THREADS is not defined, then we're building the single 31 threaded version of the libraries and do not want to reference 32 anything related to pthreads or dce. */ 33#ifndef _DCE_THREADS 34#include "gthr-single.h" 35#else 36/* DCE threads interface. 37 DCE threads are based on POSIX threads draft 4, and many things 38 have changed since then. */ 39 40/* Make sure CONST_CAST2 (original in system.h) is defined. */ 41#ifndef CONST_CAST2 42#ifdef __cplusplus 43#define CONST_CAST2(TOTYPE,FROMTYPE,X) (const_cast<TOTYPE> (X)) 44#else 45#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq) 46#endif 47#endif 48 49#define __GTHREADS 1 50 51#include <pthread.h> 52 53typedef pthread_key_t __gthread_key_t; 54typedef pthread_once_t __gthread_once_t; 55typedef pthread_mutex_t __gthread_mutex_t; 56typedef pthread_mutex_t __gthread_recursive_mutex_t; 57 58#define __GTHREAD_ONCE_INIT pthread_once_init 59 60#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function 61#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 62 63#define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init 64 65#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 66# define __gthrw(name) \ 67 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))); 68# define __gthrw_(name) __gthrw_ ## name 69#else 70# define __gthrw(name) 71# define __gthrw_(name) name 72#endif 73 74__gthrw(pthread_once) 75__gthrw(pthread_keycreate) 76__gthrw(pthread_getspecific) 77__gthrw(pthread_setspecific) 78__gthrw(pthread_create) 79__gthrw(pthread_mutex_init) 80__gthrw(pthread_mutex_destroy) 81__gthrw(pthread_mutex_lock) 82__gthrw(pthread_mutex_trylock) 83__gthrw(pthread_mutex_unlock) 84__gthrw(pthread_mutexattr_create) 85__gthrw(pthread_mutexattr_setkind_np) 86__gthrw(pthread_mutexattr_delete) 87 88#ifdef _LIBOBJC 89/* Objective-C. */ 90__gthrw(pthread_cond_broadcast) 91__gthrw(pthread_cond_destroy) 92__gthrw(pthread_cond_init) 93__gthrw(pthread_cond_signal) 94__gthrw(pthread_cond_wait) 95__gthrw(pthread_exit) 96 97#ifdef pthread_getunique_np 98# define __gthrw_pthread_getunique_np pthread_getunique_np 99#else 100__gthrw(pthread_getunique_np) 101# define __gthrw_pthread_getunique_np __gthrw_(pthread_getunique_np) 102#endif 103 104__gthrw(pthread_mutex_destroy) 105__gthrw(pthread_self) 106__gthrw(pthread_yield) 107#endif 108 109#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 110 111static inline int 112__gthread_active_p (void) 113{ 114 static void *const __gthread_active_ptr = (void *) &__gthrw_(pthread_create); 115 return __gthread_active_ptr != 0; 116} 117 118#else /* not SUPPORTS_WEAK */ 119 120static inline int 121__gthread_active_p (void) 122{ 123 return 1; 124} 125 126#endif /* SUPPORTS_WEAK */ 127 128#ifdef _LIBOBJC 129 130/* Key structure for maintaining thread specific storage */ 131static pthread_key_t _objc_thread_storage; 132 133/* Thread local storage for a single thread */ 134static void *thread_local_storage = NULL; 135 136/* Backend initialization functions */ 137 138/* Initialize the threads subsystem. */ 139static inline int 140__gthread_objc_init_thread_system (void) 141{ 142 if (__gthread_active_p ()) 143 /* Initialize the thread storage key. */ 144 return __gthrw_(pthread_keycreate) (&_objc_thread_storage, NULL); 145 else 146 return -1; 147} 148 149/* Close the threads subsystem. */ 150static inline int 151__gthread_objc_close_thread_system (void) 152{ 153 if (__gthread_active_p ()) 154 return 0; 155 else 156 return -1; 157} 158 159/* Backend thread functions */ 160 161/* Create a new thread of execution. */ 162static inline objc_thread_t 163__gthread_objc_thread_detach (void (*func)(void *), void *arg) 164{ 165 objc_thread_t thread_id; 166 pthread_t new_thread_handle; 167 168 if (!__gthread_active_p ()) 169 return NULL; 170 171 if (!(__gthrw_(pthread_create) (&new_thread_handle, pthread_attr_default, 172 (void *) func, arg))) 173 { 174 /* ??? May not work! (64bit) */ 175 thread_id = *(objc_thread_t *) &new_thread_handle; 176 pthread_detach (&new_thread_handle); /* Fully detach thread. */ 177 } 178 else 179 thread_id = NULL; 180 181 return thread_id; 182} 183 184/* Set the current thread's priority. */ 185static inline int 186__gthread_objc_thread_set_priority (int priority) 187{ 188 int sys_priority = 0; 189 190 if (!__gthread_active_p ()) 191 return -1; 192 193 switch (priority) 194 { 195 case OBJC_THREAD_INTERACTIVE_PRIORITY: 196 sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2; 197 break; 198 default: 199 case OBJC_THREAD_BACKGROUND_PRIORITY: 200 sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2; 201 break; 202 case OBJC_THREAD_LOW_PRIORITY: 203 sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2; 204 break; 205 } 206 207 /* Change the priority. */ 208 if (pthread_setprio (__gthrw_(pthread_self) (), sys_priority) >= 0) 209 return 0; 210 else 211 /* Failed */ 212 return -1; 213} 214 215/* Return the current thread's priority. */ 216static inline int 217__gthread_objc_thread_get_priority (void) 218{ 219 int sys_priority; 220 221 if (__gthread_active_p ()) 222 { 223 if ((sys_priority = pthread_getprio (__gthrw_(pthread_self) ())) >= 0) 224 { 225 if (sys_priority >= PRI_FG_MIN_NP 226 && sys_priority <= PRI_FG_MAX_NP) 227 return OBJC_THREAD_INTERACTIVE_PRIORITY; 228 if (sys_priority >= PRI_BG_MIN_NP 229 && sys_priority <= PRI_BG_MAX_NP) 230 return OBJC_THREAD_BACKGROUND_PRIORITY; 231 return OBJC_THREAD_LOW_PRIORITY; 232 } 233 234 /* Failed */ 235 return -1; 236 } 237 else 238 return OBJC_THREAD_INTERACTIVE_PRIORITY; 239} 240 241/* Yield our process time to another thread. */ 242static inline void 243__gthread_objc_thread_yield (void) 244{ 245 if (__gthread_active_p ()) 246 __gthrw_(pthread_yield) (); 247} 248 249/* Terminate the current thread. */ 250static inline int 251__gthread_objc_thread_exit (void) 252{ 253 if (__gthread_active_p ()) 254 /* exit the thread */ 255 __gthrw_(pthread_exit) (&__objc_thread_exit_status); 256 257 /* Failed if we reached here */ 258 return -1; 259} 260 261/* Returns an integer value which uniquely describes a thread. */ 262static inline objc_thread_t 263__gthread_objc_thread_id (void) 264{ 265 if (__gthread_active_p ()) 266 { 267 pthread_t self = __gthrw_(pthread_self) (); 268 269 return (objc_thread_t) __gthrw_pthread_getunique_np (&self); 270 } 271 else 272 return (objc_thread_t) 1; 273} 274 275/* Sets the thread's local storage pointer. */ 276static inline int 277__gthread_objc_thread_set_data (void *value) 278{ 279 if (__gthread_active_p ()) 280 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); 281 else 282 { 283 thread_local_storage = value; 284 return 0; 285 } 286} 287 288/* Returns the thread's local storage pointer. */ 289static inline void * 290__gthread_objc_thread_get_data (void) 291{ 292 void *value = NULL; 293 294 if (__gthread_active_p ()) 295 { 296 if (!(__gthrw_(pthread_getspecific) (_objc_thread_storage, &value))) 297 return value; 298 299 return NULL; 300 } 301 else 302 return thread_local_storage; 303} 304 305/* Backend mutex functions */ 306 307/* Allocate a mutex. */ 308static inline int 309__gthread_objc_mutex_allocate (objc_mutex_t mutex) 310{ 311 if (__gthread_active_p ()) 312 { 313 mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); 314 315 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, 316 pthread_mutexattr_default)) 317 { 318 objc_free (mutex->backend); 319 mutex->backend = NULL; 320 return -1; 321 } 322 } 323 324 return 0; 325} 326 327/* Deallocate a mutex. */ 328static inline int 329__gthread_objc_mutex_deallocate (objc_mutex_t mutex) 330{ 331 if (__gthread_active_p ()) 332 { 333 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) 334 return -1; 335 336 objc_free (mutex->backend); 337 mutex->backend = NULL; 338 } 339 340 return 0; 341} 342 343/* Grab a lock on a mutex. */ 344static inline int 345__gthread_objc_mutex_lock (objc_mutex_t mutex) 346{ 347 if (__gthread_active_p ()) 348 return __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend); 349 else 350 return 0; 351} 352 353/* Try to grab a lock on a mutex. */ 354static inline int 355__gthread_objc_mutex_trylock (objc_mutex_t mutex) 356{ 357 if (__gthread_active_p () 358 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 1) 359 return -1; 360 361 return 0; 362} 363 364/* Unlock the mutex */ 365static inline int 366__gthread_objc_mutex_unlock (objc_mutex_t mutex) 367{ 368 if (__gthread_active_p ()) 369 return __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); 370 else 371 return 0; 372} 373 374/* Backend condition mutex functions */ 375 376/* Allocate a condition. */ 377static inline int 378__gthread_objc_condition_allocate (objc_condition_t condition 379 __attribute__ ((__unused__))) 380{ 381 if (__gthread_active_p ()) 382 /* Unimplemented. */ 383 return -1; 384 else 385 return 0; 386} 387 388/* Deallocate a condition. */ 389static inline int 390__gthread_objc_condition_deallocate (objc_condition_t condition 391 __attribute__ ((__unused__))) 392{ 393 if (__gthread_active_p ()) 394 /* Unimplemented. */ 395 return -1; 396 else 397 return 0; 398} 399 400/* Wait on the condition */ 401static inline int 402__gthread_objc_condition_wait (objc_condition_t condition 403 __attribute__ ((__unused__)), 404 objc_mutex_t mutex __attribute__ ((__unused__))) 405{ 406 if (__gthread_active_p ()) 407 /* Unimplemented. */ 408 return -1; 409 else 410 return 0; 411} 412 413/* Wake up all threads waiting on this condition. */ 414static inline int 415__gthread_objc_condition_broadcast (objc_condition_t condition 416 __attribute__ ((__unused__))) 417{ 418 if (__gthread_active_p ()) 419 /* Unimplemented. */ 420 return -1; 421 else 422 return 0; 423} 424 425/* Wake up one thread waiting on this condition. */ 426static inline int 427__gthread_objc_condition_signal (objc_condition_t condition 428 __attribute__ ((__unused__))) 429{ 430 if (__gthread_active_p ()) 431 /* Unimplemented. */ 432 return -1; 433 else 434 return 0; 435} 436 437#else /* _LIBOBJC */ 438 439static inline int 440__gthread_once (__gthread_once_t *__once, void (*__func) (void)) 441{ 442 if (__gthread_active_p ()) 443 return __gthrw_(pthread_once) (__once, __func); 444 else 445 return -1; 446} 447 448static inline int 449__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) 450{ 451 return __gthrw_(pthread_keycreate) (__key, __dtor); 452} 453 454static inline int 455__gthread_key_delete (__gthread_key_t __key __attribute__ ((__unused__))) 456{ 457 /* Operation is not supported. */ 458 return -1; 459} 460 461static inline void * 462__gthread_getspecific (__gthread_key_t __key) 463{ 464 void *__ptr; 465 if (__gthrw_(pthread_getspecific) (__key, &__ptr) == 0) 466 return __ptr; 467 else 468 return 0; 469} 470 471static inline int 472__gthread_setspecific (__gthread_key_t __key, const void *__ptr) 473{ 474 return __gthrw_(pthread_setspecific) 475 (__key, CONST_CAST2(void *, const void *, __ptr)); 476} 477 478static inline void 479__gthread_mutex_init_function (__gthread_mutex_t *__mutex) 480{ 481 if (__gthread_active_p ()) 482 __gthrw_(pthread_mutex_init) (__mutex, pthread_mutexattr_default); 483} 484 485static inline int 486__gthread_mutx_destroy (__gthread_mutex_t *__mutex) 487{ 488 if (__gthread_active_p ()) 489 return __gthrw_(pthread_mutex_destroy) (__mutex); 490 else 491 return 0; 492} 493 494static inline int 495__gthread_mutex_lock (__gthread_mutex_t *__mutex) 496{ 497 if (__gthread_active_p ()) 498 return __gthrw_(pthread_mutex_lock) (__mutex); 499 else 500 return 0; 501} 502 503static inline int 504__gthread_mutex_trylock (__gthread_mutex_t *__mutex) 505{ 506 if (__gthread_active_p ()) 507 return __gthrw_(pthread_mutex_trylock) (__mutex); 508 else 509 return 0; 510} 511 512static inline int 513__gthread_mutex_unlock (__gthread_mutex_t *__mutex) 514{ 515 if (__gthread_active_p ()) 516 return __gthrw_(pthread_mutex_unlock) (__mutex); 517 else 518 return 0; 519} 520 521static inline int 522__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) 523{ 524 if (__gthread_active_p ()) 525 { 526 pthread_mutexattr_t __attr; 527 int __r; 528 529 __r = __gthrw_(pthread_mutexattr_create) (&__attr); 530 if (!__r) 531 __r = __gthrw_(pthread_mutexattr_setkind_np) (&__attr, 532 MUTEX_RECURSIVE_NP); 533 if (!__r) 534 __r = __gthrw_(pthread_mutex_init) (__mutex, __attr); 535 if (!__r) 536 __r = __gthrw_(pthread_mutexattr_delete) (&__attr); 537 return __r; 538 } 539 return 0; 540} 541 542static inline int 543__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) 544{ 545 return __gthread_mutex_lock (__mutex); 546} 547 548static inline int 549__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) 550{ 551 return __gthread_mutex_trylock (__mutex); 552} 553 554static inline int 555__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) 556{ 557 return __gthread_mutex_unlock (__mutex); 558} 559 560#endif /* _LIBOBJC */ 561 562#endif 563#endif /* ! GCC_GTHR_DCE_H */ 564