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