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