1 /* Threads compatibility routines for libgcc2 and libobjc. */ 2 /* Compile this one with gcc. */ 3 /* Copyright (C) 1997-2020 Free Software Foundation, Inc. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 Under Section 7 of GPL version 3, you are granted additional 18 permissions described in the GCC Runtime Library Exception, version 19 3.1, as published by the Free Software Foundation. 20 21 You should have received a copy of the GNU General Public License and 22 a copy of the GCC Runtime Library Exception along with this program; 23 see 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 52 typedef pthread_key_t __gthread_key_t; 53 typedef pthread_once_t __gthread_once_t; 54 typedef pthread_mutex_t __gthread_mutex_t; 55 typedef 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 110 static 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 119 static 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 */ 130 static pthread_key_t _objc_thread_storage; 131 132 /* Thread local storage for a single thread */ 133 static void *thread_local_storage = NULL; 134 135 /* Backend initialization functions */ 136 137 /* Initialize the threads subsystem. */ 138 static 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. */ 149 static 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. */ 161 static 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. */ 184 static 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. */ 215 static 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. */ 241 static 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. */ 249 static 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. */ 261 static 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. */ 275 static 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. */ 288 static 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. */ 307 static 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. */ 327 static 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. */ 343 static 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. */ 353 static 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 */ 364 static 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. */ 376 static 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. */ 388 static 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 */ 400 static 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. */ 413 static 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. */ 425 static 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 438 static 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 447 static inline int 448 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) 449 { 450 return __gthrw_(pthread_keycreate) (__key, __dtor); 451 } 452 453 static inline int 454 __gthread_key_delete (__gthread_key_t __key __attribute__ ((__unused__))) 455 { 456 /* Operation is not supported. */ 457 return -1; 458 } 459 460 static 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 470 static 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 477 static 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 484 static 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 493 static 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 502 static 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 511 static 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 520 static 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 541 static inline int 542 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) 543 { 544 return __gthread_mutex_lock (__mutex); 545 } 546 547 static inline int 548 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) 549 { 550 return __gthread_mutex_trylock (__mutex); 551 } 552 553 static inline int 554 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) 555 { 556 return __gthread_mutex_unlock (__mutex); 557 } 558 559 static 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