1169689Skan/* Threads compatibility routines for libgcc2 and libobjc. */ 2169689Skan/* Compile this one with gcc. */ 3169689Skan/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. 4169689Skan 5169689SkanThis file is part of GCC. 6169689Skan 7169689SkanGCC is free software; you can redistribute it and/or modify it under 8169689Skanthe terms of the GNU General Public License as published by the Free 9169689SkanSoftware Foundation; either version 2, or (at your option) any later 10169689Skanversion. 11169689Skan 12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 14169689SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15169689Skanfor more details. 16169689Skan 17169689SkanYou should have received a copy of the GNU General Public License 18169689Skanalong with GCC; see the file COPYING. If not, write to the Free 19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169689Skan02110-1301, USA. */ 21169689Skan 22169689Skan/* As a special exception, if you link this library with other files, 23169689Skan some of which are compiled with GCC, to produce an executable, 24169689Skan this library does not by itself cause the resulting executable 25169689Skan to be covered by the GNU General Public License. 26169689Skan This exception does not however invalidate any other reasons why 27169689Skan the executable file might be covered by the GNU General Public License. */ 28169689Skan 29169689Skan#ifndef GCC_GTHR_NKS_H 30169689Skan#define GCC_GTHR_NKS_H 31169689Skan 32169689Skan/* NKS threads specific definitions. 33169689Skan Easy, since the interface is mostly one-to-one mapping. */ 34169689Skan 35169689Skan#define __GTHREADS 1 36169689Skan 37169689Skan#define NKS_NO_INLINE_FUNCS 38169689Skan#include <nksapi.h> 39169689Skan#include <string.h> 40169689Skan 41169689Skantypedef NXKey_t __gthread_key_t; 42169689Skantypedef NXMutex_t *__gthread_mutex_t; 43169689Skantypedef NXMutex_t *__gthread_recursive_mutex_t; 44169689Skan 45169689Skan#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function 46169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 47169689Skan 48169689Skanstatic inline int 49169689Skan__gthread_active_p (void) 50169689Skan{ 51169689Skan return 1; 52169689Skan} 53169689Skan 54169689Skan#ifdef _LIBOBJC 55169689Skan 56169689Skan/* This is the config.h file in libobjc/ */ 57169689Skan#include <config.h> 58169689Skan 59169689Skan#ifdef HAVE_SCHED_H 60169689Skan# include <sched.h> 61169689Skan#endif 62169689Skan 63169689Skan/* Key structure for maintaining thread specific storage */ 64169689Skanstatic NXKey_t _objc_thread_storage; 65169689Skan 66169689Skan/* Backend initialization functions */ 67169689Skan 68169689Skan/* Initialize the threads subsystem. */ 69169689Skanstatic inline int 70169689Skan__gthread_objc_init_thread_system (void) 71169689Skan{ 72169689Skan /* Initialize the thread storage key. */ 73169689Skan if (NXKeyCreate (NULL, NULL, &_objc_thread_storage) == 0) 74169689Skan return 0; 75169689Skan return -1; 76169689Skan} 77169689Skan 78169689Skan/* Close the threads subsystem. */ 79169689Skanstatic inline int 80169689Skan__gthread_objc_close_thread_system (void) 81169689Skan{ 82169689Skan if (NXKeyDelete (_objc_thread_storage) == 0) 83169689Skan return 0; 84169689Skan return -1; 85169689Skan} 86169689Skan 87169689Skan/* Backend thread functions */ 88169689Skan 89169689Skan/* Create a new thread of execution. */ 90169689Skanstatic inline objc_thread_t 91169689Skan__gthread_objc_thread_detach (void (*func)(void *), void *arg) 92169689Skan{ 93169689Skan objc_thread_t thread_id; 94169689Skan NXContext_t context; 95169689Skan NXThreadId_t new_thread_handle; 96169689Skan int err; 97169689Skan 98169689Skan if ((context = NXContextAlloc (func, arg, NX_PRIO_MED, 0, 0, 0, &err)) == NULL) 99169689Skan thread_id = NULL; 100169689Skan else if (NXThreadCreate (context, NX_THR_DETACHED, &new_thread_handle) == 0) 101169689Skan thread_id = (objc_thread_t) new_thread_handle; 102169689Skan else { 103169689Skan NXContextFree (context); 104169689Skan thread_id = NULL; 105169689Skan } 106169689Skan 107169689Skan return thread_id; 108169689Skan} 109169689Skan 110169689Skan/* Set the current thread's priority. */ 111169689Skanstatic inline int 112169689Skan__gthread_objc_thread_set_priority (int priority) 113169689Skan{ 114169689Skan if (NXThreadSetPriority (NXThreadGetId (), priority) == 0) 115169689Skan return 0; 116169689Skan return -1; 117169689Skan} 118169689Skan 119169689Skan/* Return the current thread's priority. */ 120169689Skanstatic inline int 121169689Skan__gthread_objc_thread_get_priority (void) 122169689Skan{ 123169689Skan int priority; 124169689Skan 125169689Skan if (NXThreadGetPriority (NXThreadGetId (), &priority) == 0) 126169689Skan return priority; 127169689Skan return -1; 128169689Skan} 129169689Skan 130169689Skan/* Yield our process time to another thread. */ 131169689Skanstatic inline void 132169689Skan__gthread_objc_thread_yield (void) 133169689Skan{ 134169689Skan NXThreadYield (); 135169689Skan} 136169689Skan 137169689Skan/* Terminate the current thread. */ 138169689Skanstatic inline int 139169689Skan__gthread_objc_thread_exit (void) 140169689Skan{ 141169689Skan /* exit the thread */ 142169689Skan NXThreadExit (&__objc_thread_exit_status); 143169689Skan 144169689Skan /* Failed if we reached here */ 145169689Skan return -1; 146169689Skan} 147169689Skan 148169689Skan/* Returns an integer value which uniquely describes a thread. */ 149169689Skanstatic inline objc_thread_t 150169689Skan__gthread_objc_thread_id (void) 151169689Skan{ 152169689Skan (objc_thread_t) NXThreadGetId (); 153169689Skan} 154169689Skan 155169689Skan/* Sets the thread's local storage pointer. */ 156169689Skanstatic inline int 157169689Skan__gthread_objc_thread_set_data (void *value) 158169689Skan{ 159169689Skan return NXKeySetValue (_objc_thread_storage, value); 160169689Skan} 161169689Skan 162169689Skan/* Returns the thread's local storage pointer. */ 163169689Skanstatic inline void * 164169689Skan__gthread_objc_thread_get_data (void) 165169689Skan{ 166169689Skan void *value; 167169689Skan 168169689Skan if (NXKeyGetValue (_objc_thread_storage, &value) == 0) 169169689Skan return value; 170169689Skan return NULL; 171169689Skan} 172169689Skan 173169689Skan/* Backend mutex functions */ 174169689Skan 175169689Skan/* Allocate a mutex. */ 176169689Skanstatic inline int 177169689Skan__gthread_objc_mutex_allocate (objc_mutex_t mutex) 178169689Skan{ 179169689Skan static const NX_LOCK_INFO_ALLOC (info, "GNU ObjC", 0); 180169689Skan 181169689Skan if ((mutex->backend = NXMutexAlloc (0, 0, &info)) == NULL) 182169689Skan return 0; 183169689Skan return -1; 184169689Skan} 185169689Skan 186169689Skan/* Deallocate a mutex. */ 187169689Skanstatic inline int 188169689Skan__gthread_objc_mutex_deallocate (objc_mutex_t mutex) 189169689Skan{ 190169689Skan while (NXMutexIsOwned ((NXMutex_t *)mutex->backend)) 191169689Skan NXUnlock ((NXMutex_t *)mutex->backend); 192169689Skan if (NXMutexFree ((NXMutex_t *)mutex->backend) != 0) 193169689Skan return -1; 194169689Skan mutex->backend = NULL; 195169689Skan return 0; 196169689Skan} 197169689Skan 198169689Skan/* Grab a lock on a mutex. */ 199169689Skanstatic inline int 200169689Skan__gthread_objc_mutex_lock (objc_mutex_t mutex) 201169689Skan{ 202169689Skan return NXLock ((NXMutex_t *)mutex->backend); 203169689Skan} 204169689Skan 205169689Skan/* Try to grab a lock on a mutex. */ 206169689Skanstatic inline int 207169689Skan__gthread_objc_mutex_trylock (objc_mutex_t mutex) 208169689Skan{ 209169689Skan if (!NXTryLock ((NXMutex_t *)mutex->backend)) 210169689Skan return -1; 211169689Skan return 0; 212169689Skan} 213169689Skan 214169689Skan/* Unlock the mutex */ 215169689Skanstatic inline int 216169689Skan__gthread_objc_mutex_unlock (objc_mutex_t mutex) 217169689Skan{ 218169689Skan return NXUnlock ((NXMutex_t *)mutex->backend); 219169689Skan} 220169689Skan 221169689Skan/* Backend condition mutex functions */ 222169689Skan 223169689Skan/* Allocate a condition. */ 224169689Skanstatic inline int 225169689Skan__gthread_objc_condition_allocate (objc_condition_t condition) 226169689Skan{ 227169689Skan condition->backend = NXCondAlloc (NULL); 228169689Skan if (condition->backend == NULL) 229169689Skan return -1; 230169689Skan 231169689Skan return 0; 232169689Skan} 233169689Skan 234169689Skan/* Deallocate a condition. */ 235169689Skanstatic inline int 236169689Skan__gthread_objc_condition_deallocate (objc_condition_t condition) 237169689Skan{ 238169689Skan if (NXCondFree ((NXCond_t *)condition->backend) != 0) 239169689Skan return -1; 240169689Skan condition->backend = NULL; 241169689Skan return 0; 242169689Skan} 243169689Skan 244169689Skan/* Wait on the condition */ 245169689Skanstatic inline int 246169689Skan__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) 247169689Skan{ 248169689Skan return NXCondWait ((NXCond_t *)condition->backend, (NXMutex_t *)mutex->backend); 249169689Skan} 250169689Skan 251169689Skan/* Wake up all threads waiting on this condition. */ 252169689Skanstatic inline int 253169689Skan__gthread_objc_condition_broadcast (objc_condition_t condition) 254169689Skan{ 255169689Skan return NXCondBroadcast ((NXCond_t *)condition->backend); 256169689Skan} 257169689Skan 258169689Skan/* Wake up one thread waiting on this condition. */ 259169689Skanstatic inline int 260169689Skan__gthread_objc_condition_signal (objc_condition_t condition) 261169689Skan{ 262169689Skan return NXCondSignal ((NXCond_t *)condition->backend); 263169689Skan} 264169689Skan 265169689Skan#else /* _LIBOBJC */ 266169689Skan 267169689Skan#if defined(__cplusplus) 268169689Skan# include <bits/atomicity.h> 269169689Skan/* The remaining conditions here are temporary until there is 270169689Skan an application accessible atomic operations API set... */ 271169689Skan#elif defined(_M_IA64) || defined(__ia64__) 272169689Skan# include <../libstdc++-v3/config/cpu/ia64/bits/atomicity.h> 273169689Skan#elif defined(_M_IX86) || defined(__i486__) 274169689Skan# include <../libstdc++-v3/config/cpu/i486/bits/atomicity.h> 275169689Skan#elif defined(_M_AMD64) || defined(__x86_64__) 276169689Skan# include <../libstdc++-v3/config/cpu/x86-64/bits/atomicity.h> 277169689Skan#endif 278169689Skan 279169689Skantypedef volatile long __gthread_once_t; 280169689Skan 281169689Skan#define __GTHREAD_ONCE_INIT 0 282169689Skan 283169689Skanstatic inline int 284169689Skan__gthread_once (__gthread_once_t *once, void (*func) (void)) 285169689Skan{ 286169689Skan if (__compare_and_swap (once, 0, 1)) 287169689Skan { 288169689Skan func(); 289169689Skan *once |= 2; 290169689Skan } 291169689Skan else 292169689Skan { 293169689Skan while (!(*once & 2)) 294169689Skan NXThreadYield (); 295169689Skan } 296169689Skan return 0; 297169689Skan} 298169689Skan 299169689Skanstatic inline int 300169689Skan__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) 301169689Skan{ 302169689Skan return NXKeyCreate (dtor, NULL, key); 303169689Skan} 304169689Skan 305169689Skanstatic inline int 306169689Skan__gthread_key_dtor (__gthread_key_t key, void *ptr) 307169689Skan{ 308169689Skan /* Just reset the key value to zero. */ 309169689Skan if (ptr) 310169689Skan return NXKeySetValue (key, NULL); 311169689Skan return 0; 312169689Skan} 313169689Skan 314169689Skanstatic inline int 315169689Skan__gthread_key_delete (__gthread_key_t key) 316169689Skan{ 317169689Skan return NXKeyDelete (key); 318169689Skan} 319169689Skan 320169689Skanstatic inline void * 321169689Skan__gthread_getspecific (__gthread_key_t key) 322169689Skan{ 323169689Skan void *value; 324169689Skan 325169689Skan if (NXKeyGetValue (key, &value) == 0) 326169689Skan return value; 327169689Skan return NULL; 328169689Skan} 329169689Skan 330169689Skanstatic inline int 331169689Skan__gthread_setspecific (__gthread_key_t key, const void *ptr) 332169689Skan{ 333169689Skan return NXKeySetValue (key, (void *)ptr); 334169689Skan} 335169689Skan 336169689Skanstatic inline void 337169689Skan__gthread_mutex_init_function (__gthread_mutex_t *mutex) 338169689Skan{ 339169689Skan static const NX_LOCK_INFO_ALLOC (info, "GTHREADS", 0); 340169689Skan 341169689Skan *mutex = NXMutexAlloc (0, 0, &info); 342169689Skan} 343169689Skan 344169689Skanstatic inline int 345169689Skan__gthread_mutex_lock (__gthread_mutex_t *mutex) 346169689Skan{ 347169689Skan return NXLock (*mutex); 348169689Skan} 349169689Skan 350169689Skanstatic inline int 351169689Skan__gthread_mutex_trylock (__gthread_mutex_t *mutex) 352169689Skan{ 353169689Skan if (NXTryLock (*mutex)) 354169689Skan return 0; 355169689Skan return -1; 356169689Skan} 357169689Skan 358169689Skanstatic inline int 359169689Skan__gthread_mutex_unlock (__gthread_mutex_t *mutex) 360169689Skan{ 361169689Skan return NXUnlock (*mutex); 362169689Skan} 363169689Skan 364169689Skanstatic inline void 365169689Skan__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) 366169689Skan{ 367169689Skan static const NX_LOCK_INFO_ALLOC (info, "GTHREADS", 0); 368169689Skan 369169689Skan *mutex = NXMutexAlloc (NX_MUTEX_RECURSIVE, 0, &info); 370169689Skan} 371169689Skan 372169689Skanstatic inline int 373169689Skan__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) 374169689Skan{ 375169689Skan return NXLock (*mutex); 376169689Skan} 377169689Skan 378169689Skanstatic inline int 379169689Skan__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) 380169689Skan{ 381169689Skan if (NXTryLock (*mutex)) 382169689Skan return 0; 383169689Skan return -1; 384169689Skan} 385169689Skan 386169689Skanstatic inline int 387169689Skan__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) 388169689Skan{ 389169689Skan return NXUnlock (*mutex); 390169689Skan} 391169689Skan 392169689Skan#endif /* _LIBOBJC */ 393169689Skan 394169689Skan#endif /* not GCC_GTHR_NKS_H */ 395