1169689Skan/* Threads compatibility routines for libgcc2 and libobjc. */ 250397Sobrien/* Compile this one with gcc. */ 3169689Skan/* Copyright (C) 1997, 1999, 2000, 2001, 2004, 2005 4169689Skan Free Software Foundation, Inc. 550397Sobrien 690075SobrienThis file is part of GCC. 750397Sobrien 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1250397Sobrien 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1750397Sobrien 1850397SobrienYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2250397Sobrien 2350397Sobrien/* As a special exception, if you link this library with other files, 2450397Sobrien some of which are compiled with GCC, to produce an executable, 2550397Sobrien this library does not by itself cause the resulting executable 2650397Sobrien to be covered by the GNU General Public License. 2750397Sobrien This exception does not however invalidate any other reasons why 2850397Sobrien the executable file might be covered by the GNU General Public License. */ 2950397Sobrien 3090075Sobrien#ifndef GCC_GTHR_DCE_H 3190075Sobrien#define GCC_GTHR_DCE_H 3250397Sobrien 3390075Sobrien/* If _DCE_THREADS is not defined, then we're building the single 3490075Sobrien threaded version of the libraries and do not want to reference 3590075Sobrien anything related to pthreads or dce. */ 3690075Sobrien#ifndef _DCE_THREADS 3790075Sobrien#include "gthr-single.h" 3890075Sobrien#else 3950397Sobrien/* DCE threads interface. 4050397Sobrien DCE threads are based on POSIX threads draft 4, and many things 4190075Sobrien have changed since then. */ 4250397Sobrien 4350397Sobrien#define __GTHREADS 1 4450397Sobrien 4550397Sobrien#include <pthread.h> 4650397Sobrien 4750397Sobrientypedef pthread_key_t __gthread_key_t; 4850397Sobrientypedef pthread_once_t __gthread_once_t; 4950397Sobrientypedef pthread_mutex_t __gthread_mutex_t; 50169689Skantypedef pthread_mutex_t __gthread_recursive_mutex_t; 5150397Sobrien 5250397Sobrien#define __GTHREAD_ONCE_INIT pthread_once_init 5350397Sobrien 5490075Sobrien#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function 55169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 5690075Sobrien 5790075Sobrien#define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init 5890075Sobrien 5950397Sobrien#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 60169689Skan# define __gthrw(name) \ 61169689Skan static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))); 62169689Skan# define __gthrw_(name) __gthrw_ ## name 63169689Skan#else 64169689Skan# define __gthrw(name) 65169689Skan# define __gthrw_(name) name 66169689Skan#endif 6750397Sobrien 68169689Skan__gthrw(pthread_once) 69169689Skan__gthrw(pthread_keycreate) 70169689Skan__gthrw(pthread_getspecific) 71169689Skan__gthrw(pthread_setspecific) 72169689Skan__gthrw(pthread_create) 73169689Skan__gthrw(pthread_mutex_init) 74169689Skan__gthrw(pthread_mutex_lock) 75169689Skan__gthrw(pthread_mutex_trylock) 76169689Skan__gthrw(pthread_mutex_unlock) 77169689Skan__gthrw(pthread_mutexattr_create) 78169689Skan__gthrw(pthread_mutexattr_setkind_np) 79169689Skan__gthrw(pthread_mutexattr_delete) 8050397Sobrien 8190075Sobrien#ifdef _LIBOBJC 82117395Skan/* Objective-C. */ 83169689Skan__gthrw(pthread_cond_broadcast) 84169689Skan__gthrw(pthread_cond_destroy) 85169689Skan__gthrw(pthread_cond_init) 86169689Skan__gthrw(pthread_cond_signal) 87169689Skan__gthrw(pthread_cond_wait) 88169689Skan__gthrw(pthread_exit) 89169689Skan 90169689Skan#ifdef pthread_getunique_np 91169689Skan# define __gthrw_pthread_getunique_np pthread_getunique_np 92169689Skan#else 93169689Skan__gthrw(pthread_getunique_np) 94169689Skan# define __gthrw_pthread_getunique_np __gthrw_(pthread_getunique_np) 9590075Sobrien#endif 9650397Sobrien 97169689Skan__gthrw(pthread_mutex_destroy) 98169689Skan__gthrw(pthread_self) 99169689Skan__gthrw(pthread_yield) 100169689Skan#endif 101169689Skan 102169689Skan#if SUPPORTS_WEAK && GTHREAD_USE_WEAK 103169689Skan 10450397Sobrienstatic inline int 10590075Sobrien__gthread_active_p (void) 10650397Sobrien{ 107169689Skan static void *const __gthread_active_ptr = (void *) &__gthrw_(pthread_create); 10850397Sobrien return __gthread_active_ptr != 0; 10950397Sobrien} 11050397Sobrien 11150397Sobrien#else /* not SUPPORTS_WEAK */ 11250397Sobrien 11350397Sobrienstatic inline int 11490075Sobrien__gthread_active_p (void) 11550397Sobrien{ 11650397Sobrien return 1; 11750397Sobrien} 11850397Sobrien 11950397Sobrien#endif /* SUPPORTS_WEAK */ 12050397Sobrien 12190075Sobrien#ifdef _LIBOBJC 12290075Sobrien 12390075Sobrien/* Key structure for maintaining thread specific storage */ 12490075Sobrienstatic pthread_key_t _objc_thread_storage; 12590075Sobrien 12690075Sobrien/* Thread local storage for a single thread */ 12790075Sobrienstatic void *thread_local_storage = NULL; 12890075Sobrien 12990075Sobrien/* Backend initialization functions */ 13090075Sobrien 13190075Sobrien/* Initialize the threads subsystem. */ 13250397Sobrienstatic inline int 133117395Skan__gthread_objc_init_thread_system (void) 13450397Sobrien{ 13550397Sobrien if (__gthread_active_p ()) 136169689Skan /* Initialize the thread storage key. */ 137169689Skan return __gthrw_(pthread_keycreate) (&_objc_thread_storage, NULL); 13890075Sobrien else 13990075Sobrien return -1; 14090075Sobrien} 14190075Sobrien 14290075Sobrien/* Close the threads subsystem. */ 14390075Sobrienstatic inline int 144117395Skan__gthread_objc_close_thread_system (void) 14590075Sobrien{ 14690075Sobrien if (__gthread_active_p ()) 14790075Sobrien return 0; 14890075Sobrien else 14990075Sobrien return -1; 15090075Sobrien} 15190075Sobrien 15290075Sobrien/* Backend thread functions */ 15390075Sobrien 15490075Sobrien/* Create a new thread of execution. */ 15590075Sobrienstatic inline objc_thread_t 156117395Skan__gthread_objc_thread_detach (void (*func)(void *), void *arg) 15790075Sobrien{ 15890075Sobrien objc_thread_t thread_id; 15990075Sobrien pthread_t new_thread_handle; 16090075Sobrien 16190075Sobrien if (!__gthread_active_p ()) 16290075Sobrien return NULL; 163117395Skan 164169689Skan if (!(__gthrw_(pthread_create) (&new_thread_handle, pthread_attr_default, 165117395Skan (void *) func, arg))) 16690075Sobrien { 16790075Sobrien /* ??? May not work! (64bit) */ 168117395Skan thread_id = *(objc_thread_t *) &new_thread_handle; 169117395Skan pthread_detach (&new_thread_handle); /* Fully detach thread. */ 17090075Sobrien } 17190075Sobrien else 17290075Sobrien thread_id = NULL; 173117395Skan 17490075Sobrien return thread_id; 17590075Sobrien} 17690075Sobrien 17790075Sobrien/* Set the current thread's priority. */ 17890075Sobrienstatic inline int 179117395Skan__gthread_objc_thread_set_priority (int priority) 18090075Sobrien{ 18190075Sobrien int sys_priority = 0; 18290075Sobrien 18390075Sobrien if (!__gthread_active_p ()) 18490075Sobrien return -1; 18590075Sobrien 18690075Sobrien switch (priority) 18790075Sobrien { 18890075Sobrien case OBJC_THREAD_INTERACTIVE_PRIORITY: 18990075Sobrien sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2; 19090075Sobrien break; 19190075Sobrien default: 19290075Sobrien case OBJC_THREAD_BACKGROUND_PRIORITY: 19390075Sobrien sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2; 19490075Sobrien break; 19590075Sobrien case OBJC_THREAD_LOW_PRIORITY: 19690075Sobrien sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2; 19790075Sobrien break; 19890075Sobrien } 199117395Skan 20090075Sobrien /* Change the priority. */ 201169689Skan if (pthread_setprio (__gthrw_(pthread_self) (), sys_priority) >= 0) 20290075Sobrien return 0; 20390075Sobrien else 20490075Sobrien /* Failed */ 20590075Sobrien return -1; 20690075Sobrien} 20790075Sobrien 20890075Sobrien/* Return the current thread's priority. */ 20990075Sobrienstatic inline int 210117395Skan__gthread_objc_thread_get_priority (void) 21190075Sobrien{ 21290075Sobrien int sys_priority; 21390075Sobrien 21490075Sobrien if (__gthread_active_p ()) 21590075Sobrien { 216169689Skan if ((sys_priority = pthread_getprio (__gthrw_(pthread_self) ())) >= 0) 217117395Skan { 21890075Sobrien if (sys_priority >= PRI_FG_MIN_NP 21990075Sobrien && sys_priority <= PRI_FG_MAX_NP) 22090075Sobrien return OBJC_THREAD_INTERACTIVE_PRIORITY; 22190075Sobrien if (sys_priority >= PRI_BG_MIN_NP 22290075Sobrien && sys_priority <= PRI_BG_MAX_NP) 22390075Sobrien return OBJC_THREAD_BACKGROUND_PRIORITY; 22490075Sobrien return OBJC_THREAD_LOW_PRIORITY; 22590075Sobrien } 22690075Sobrien 22790075Sobrien /* Failed */ 22890075Sobrien return -1; 22990075Sobrien } 23090075Sobrien else 23190075Sobrien return OBJC_THREAD_INTERACTIVE_PRIORITY; 23290075Sobrien} 23390075Sobrien 23490075Sobrien/* Yield our process time to another thread. */ 23590075Sobrienstatic inline void 236117395Skan__gthread_objc_thread_yield (void) 23790075Sobrien{ 23890075Sobrien if (__gthread_active_p ()) 239169689Skan __gthrw_(pthread_yield) (); 24090075Sobrien} 24190075Sobrien 24290075Sobrien/* Terminate the current thread. */ 24390075Sobrienstatic inline int 244117395Skan__gthread_objc_thread_exit (void) 24590075Sobrien{ 24690075Sobrien if (__gthread_active_p ()) 24790075Sobrien /* exit the thread */ 248169689Skan __gthrw_(pthread_exit) (&__objc_thread_exit_status); 24990075Sobrien 25090075Sobrien /* Failed if we reached here */ 25190075Sobrien return -1; 25290075Sobrien} 25390075Sobrien 25490075Sobrien/* Returns an integer value which uniquely describes a thread. */ 25590075Sobrienstatic inline objc_thread_t 256117395Skan__gthread_objc_thread_id (void) 25790075Sobrien{ 25890075Sobrien if (__gthread_active_p ()) 25990075Sobrien { 260169689Skan pthread_t self = __gthrw_(pthread_self) (); 26190075Sobrien 262169689Skan return (objc_thread_t) __gthrw_pthread_getunique_np (&self); 26390075Sobrien } 26490075Sobrien else 265117395Skan return (objc_thread_t) 1; 26690075Sobrien} 26790075Sobrien 26890075Sobrien/* Sets the thread's local storage pointer. */ 26990075Sobrienstatic inline int 270117395Skan__gthread_objc_thread_set_data (void *value) 27190075Sobrien{ 27290075Sobrien if (__gthread_active_p ()) 273169689Skan return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); 27490075Sobrien else 27590075Sobrien { 27690075Sobrien thread_local_storage = value; 27790075Sobrien return 0; 27890075Sobrien } 27990075Sobrien} 28090075Sobrien 28190075Sobrien/* Returns the thread's local storage pointer. */ 28290075Sobrienstatic inline void * 283117395Skan__gthread_objc_thread_get_data (void) 28490075Sobrien{ 28590075Sobrien void *value = NULL; 28690075Sobrien 28790075Sobrien if (__gthread_active_p ()) 28890075Sobrien { 289169689Skan if (!(__gthrw_(pthread_getspecific) (_objc_thread_storage, &value))) 29090075Sobrien return value; 29190075Sobrien 29290075Sobrien return NULL; 29390075Sobrien } 29490075Sobrien else 29590075Sobrien return thread_local_storage; 29690075Sobrien} 29790075Sobrien 29890075Sobrien/* Backend mutex functions */ 29990075Sobrien 30090075Sobrien/* Allocate a mutex. */ 30190075Sobrienstatic inline int 302117395Skan__gthread_objc_mutex_allocate (objc_mutex_t mutex) 30390075Sobrien{ 30490075Sobrien if (__gthread_active_p ()) 30590075Sobrien { 306117395Skan mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); 30790075Sobrien 308169689Skan if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, 309117395Skan pthread_mutexattr_default)) 310117395Skan { 311117395Skan objc_free (mutex->backend); 312117395Skan mutex->backend = NULL; 313117395Skan return -1; 314117395Skan } 31590075Sobrien } 31690075Sobrien 31790075Sobrien return 0; 31890075Sobrien} 31990075Sobrien 32090075Sobrien/* Deallocate a mutex. */ 32190075Sobrienstatic inline int 322117395Skan__gthread_objc_mutex_deallocate (objc_mutex_t mutex) 32390075Sobrien{ 32490075Sobrien if (__gthread_active_p ()) 32590075Sobrien { 326169689Skan if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) 327117395Skan return -1; 32890075Sobrien 329117395Skan objc_free (mutex->backend); 33090075Sobrien mutex->backend = NULL; 33190075Sobrien } 33290075Sobrien 33390075Sobrien return 0; 33490075Sobrien} 33590075Sobrien 33690075Sobrien/* Grab a lock on a mutex. */ 33790075Sobrienstatic inline int 338117395Skan__gthread_objc_mutex_lock (objc_mutex_t mutex) 33990075Sobrien{ 34090075Sobrien if (__gthread_active_p ()) 341169689Skan return __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend); 34290075Sobrien else 34390075Sobrien return 0; 34490075Sobrien} 34590075Sobrien 34690075Sobrien/* Try to grab a lock on a mutex. */ 34790075Sobrienstatic inline int 348117395Skan__gthread_objc_mutex_trylock (objc_mutex_t mutex) 34990075Sobrien{ 35090075Sobrien if (__gthread_active_p () 351169689Skan && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 1) 35290075Sobrien return -1; 35390075Sobrien 35490075Sobrien return 0; 35590075Sobrien} 35690075Sobrien 35790075Sobrien/* Unlock the mutex */ 35890075Sobrienstatic inline int 359117395Skan__gthread_objc_mutex_unlock (objc_mutex_t mutex) 36090075Sobrien{ 36190075Sobrien if (__gthread_active_p ()) 362169689Skan return __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); 36390075Sobrien else 36490075Sobrien return 0; 36590075Sobrien} 36690075Sobrien 36790075Sobrien/* Backend condition mutex functions */ 36890075Sobrien 36990075Sobrien/* Allocate a condition. */ 37090075Sobrienstatic inline int 371169689Skan__gthread_objc_condition_allocate (objc_condition_t condition 372169689Skan __attribute__ ((__unused__))) 37390075Sobrien{ 37490075Sobrien if (__gthread_active_p ()) 37590075Sobrien /* Unimplemented. */ 37690075Sobrien return -1; 37790075Sobrien else 37890075Sobrien return 0; 37990075Sobrien} 38090075Sobrien 38190075Sobrien/* Deallocate a condition. */ 38290075Sobrienstatic inline int 383169689Skan__gthread_objc_condition_deallocate (objc_condition_t condition 384169689Skan __attribute__ ((__unused__))) 38590075Sobrien{ 38690075Sobrien if (__gthread_active_p ()) 38790075Sobrien /* Unimplemented. */ 38890075Sobrien return -1; 38990075Sobrien else 39090075Sobrien return 0; 39190075Sobrien} 39290075Sobrien 39390075Sobrien/* Wait on the condition */ 39490075Sobrienstatic inline int 395169689Skan__gthread_objc_condition_wait (objc_condition_t condition 396169689Skan __attribute__ ((__unused__)), 397169689Skan objc_mutex_t mutex __attribute__ ((__unused__))) 39890075Sobrien{ 39990075Sobrien if (__gthread_active_p ()) 40090075Sobrien /* Unimplemented. */ 40190075Sobrien return -1; 40290075Sobrien else 40390075Sobrien return 0; 40490075Sobrien} 40590075Sobrien 40690075Sobrien/* Wake up all threads waiting on this condition. */ 40790075Sobrienstatic inline int 408169689Skan__gthread_objc_condition_broadcast (objc_condition_t condition 409169689Skan __attribute__ ((__unused__))) 41090075Sobrien{ 41190075Sobrien if (__gthread_active_p ()) 41290075Sobrien /* Unimplemented. */ 41390075Sobrien return -1; 41490075Sobrien else 41590075Sobrien return 0; 41690075Sobrien} 41790075Sobrien 41890075Sobrien/* Wake up one thread waiting on this condition. */ 41990075Sobrienstatic inline int 420169689Skan__gthread_objc_condition_signal (objc_condition_t condition 421169689Skan __attribute__ ((__unused__))) 42290075Sobrien{ 42390075Sobrien if (__gthread_active_p ()) 42490075Sobrien /* Unimplemented. */ 42590075Sobrien return -1; 42690075Sobrien else 42790075Sobrien return 0; 42890075Sobrien} 42990075Sobrien 43090075Sobrien#else /* _LIBOBJC */ 43190075Sobrien 43290075Sobrienstatic inline int 43390075Sobrien__gthread_once (__gthread_once_t *once, void (*func) (void)) 43490075Sobrien{ 43590075Sobrien if (__gthread_active_p ()) 436169689Skan return __gthrw_(pthread_once) (once, func); 43750397Sobrien else 43850397Sobrien return -1; 43950397Sobrien} 44050397Sobrien 44150397Sobrienstatic inline int 44250397Sobrien__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) 44350397Sobrien{ 444169689Skan return __gthrw_(pthread_keycreate) (key, dtor); 44550397Sobrien} 44650397Sobrien 44750397Sobrienstatic inline int 448169689Skan__gthread_key_delete (__gthread_key_t key __attribute__ ((__unused__))) 44950397Sobrien{ 45090075Sobrien /* Operation is not supported. */ 45190075Sobrien return -1; 45250397Sobrien} 45350397Sobrien 45450397Sobrienstatic inline void * 45550397Sobrien__gthread_getspecific (__gthread_key_t key) 45650397Sobrien{ 45750397Sobrien void *ptr; 458169689Skan if (__gthrw_(pthread_getspecific) (key, &ptr) == 0) 45950397Sobrien return ptr; 46050397Sobrien else 46150397Sobrien return 0; 46250397Sobrien} 46350397Sobrien 46450397Sobrienstatic inline int 46550397Sobrien__gthread_setspecific (__gthread_key_t key, const void *ptr) 46650397Sobrien{ 467169689Skan return __gthrw_(pthread_setspecific) (key, (void *) ptr); 46850397Sobrien} 46950397Sobrien 47090075Sobrienstatic inline void 47190075Sobrien__gthread_mutex_init_function (__gthread_mutex_t *mutex) 47290075Sobrien{ 47390075Sobrien if (__gthread_active_p ()) 474169689Skan __gthrw_(pthread_mutex_init) (mutex, pthread_mutexattr_default); 47590075Sobrien} 47690075Sobrien 47750397Sobrienstatic inline int 47850397Sobrien__gthread_mutex_lock (__gthread_mutex_t *mutex) 47950397Sobrien{ 48050397Sobrien if (__gthread_active_p ()) 481169689Skan return __gthrw_(pthread_mutex_lock) (mutex); 48250397Sobrien else 48350397Sobrien return 0; 48450397Sobrien} 48550397Sobrien 48650397Sobrienstatic inline int 48750397Sobrien__gthread_mutex_trylock (__gthread_mutex_t *mutex) 48850397Sobrien{ 48950397Sobrien if (__gthread_active_p ()) 490169689Skan return __gthrw_(pthread_mutex_trylock) (mutex); 49150397Sobrien else 49250397Sobrien return 0; 49350397Sobrien} 49450397Sobrien 49550397Sobrienstatic inline int 49650397Sobrien__gthread_mutex_unlock (__gthread_mutex_t *mutex) 49750397Sobrien{ 49850397Sobrien if (__gthread_active_p ()) 499169689Skan return __gthrw_(pthread_mutex_unlock) (mutex); 50050397Sobrien else 50150397Sobrien return 0; 50250397Sobrien} 50350397Sobrien 504169689Skanstatic inline int 505169689Skan__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) 506169689Skan{ 507169689Skan if (__gthread_active_p ()) 508169689Skan { 509169689Skan pthread_mutexattr_t attr; 510169689Skan int r; 511169689Skan 512169689Skan r = __gthrw_(pthread_mutexattr_create) (&attr); 513169689Skan if (!r) 514169689Skan r = __gthrw_(pthread_mutexattr_setkind_np) (&attr, MUTEX_RECURSIVE_NP); 515169689Skan if (!r) 516169689Skan r = __gthrw_(pthread_mutex_init) (mutex, attr); 517169689Skan if (!r) 518169689Skan r = __gthrw_(pthread_mutexattr_delete) (&attr); 519169689Skan return r; 520169689Skan } 521169689Skan return 0; 522169689Skan} 523169689Skan 524169689Skanstatic inline int 525169689Skan__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) 526169689Skan{ 527169689Skan return __gthread_mutex_lock (mutex); 528169689Skan} 529169689Skan 530169689Skanstatic inline int 531169689Skan__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) 532169689Skan{ 533169689Skan return __gthread_mutex_trylock (mutex); 534169689Skan} 535169689Skan 536169689Skanstatic inline int 537169689Skan__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) 538169689Skan{ 539169689Skan return __gthread_mutex_unlock (mutex); 540169689Skan} 541169689Skan 54290075Sobrien#endif /* _LIBOBJC */ 54390075Sobrien 54490075Sobrien#endif 54590075Sobrien#endif /* ! GCC_GTHR_DCE_H */ 546