gthr-nks.h revision 256281
1/* Threads compatibility routines for libgcc2 and libobjc. */ 2/* Compile this one with gcc. */ 3/* Copyright (C) 2002, 2003, 2004 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, 51 Franklin Street, Fifth Floor, Boston, MA 2002110-1301, 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_NKS_H 30#define GCC_GTHR_NKS_H 31 32/* NKS threads specific definitions. 33 Easy, since the interface is mostly one-to-one mapping. */ 34 35#define __GTHREADS 1 36 37#define NKS_NO_INLINE_FUNCS 38#include <nksapi.h> 39#include <string.h> 40 41typedef NXKey_t __gthread_key_t; 42typedef NXMutex_t *__gthread_mutex_t; 43typedef NXMutex_t *__gthread_recursive_mutex_t; 44 45#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function 46#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 47 48static inline int 49__gthread_active_p (void) 50{ 51 return 1; 52} 53 54#ifdef _LIBOBJC 55 56/* This is the config.h file in libobjc/ */ 57#include <config.h> 58 59#ifdef HAVE_SCHED_H 60# include <sched.h> 61#endif 62 63/* Key structure for maintaining thread specific storage */ 64static NXKey_t _objc_thread_storage; 65 66/* Backend initialization functions */ 67 68/* Initialize the threads subsystem. */ 69static inline int 70__gthread_objc_init_thread_system (void) 71{ 72 /* Initialize the thread storage key. */ 73 if (NXKeyCreate (NULL, NULL, &_objc_thread_storage) == 0) 74 return 0; 75 return -1; 76} 77 78/* Close the threads subsystem. */ 79static inline int 80__gthread_objc_close_thread_system (void) 81{ 82 if (NXKeyDelete (_objc_thread_storage) == 0) 83 return 0; 84 return -1; 85} 86 87/* Backend thread functions */ 88 89/* Create a new thread of execution. */ 90static inline objc_thread_t 91__gthread_objc_thread_detach (void (*func)(void *), void *arg) 92{ 93 objc_thread_t thread_id; 94 NXContext_t context; 95 NXThreadId_t new_thread_handle; 96 int err; 97 98 if ((context = NXContextAlloc (func, arg, NX_PRIO_MED, 0, 0, 0, &err)) == NULL) 99 thread_id = NULL; 100 else if (NXThreadCreate (context, NX_THR_DETACHED, &new_thread_handle) == 0) 101 thread_id = (objc_thread_t) new_thread_handle; 102 else { 103 NXContextFree (context); 104 thread_id = NULL; 105 } 106 107 return thread_id; 108} 109 110/* Set the current thread's priority. */ 111static inline int 112__gthread_objc_thread_set_priority (int priority) 113{ 114 if (NXThreadSetPriority (NXThreadGetId (), priority) == 0) 115 return 0; 116 return -1; 117} 118 119/* Return the current thread's priority. */ 120static inline int 121__gthread_objc_thread_get_priority (void) 122{ 123 int priority; 124 125 if (NXThreadGetPriority (NXThreadGetId (), &priority) == 0) 126 return priority; 127 return -1; 128} 129 130/* Yield our process time to another thread. */ 131static inline void 132__gthread_objc_thread_yield (void) 133{ 134 NXThreadYield (); 135} 136 137/* Terminate the current thread. */ 138static inline int 139__gthread_objc_thread_exit (void) 140{ 141 /* exit the thread */ 142 NXThreadExit (&__objc_thread_exit_status); 143 144 /* Failed if we reached here */ 145 return -1; 146} 147 148/* Returns an integer value which uniquely describes a thread. */ 149static inline objc_thread_t 150__gthread_objc_thread_id (void) 151{ 152 (objc_thread_t) NXThreadGetId (); 153} 154 155/* Sets the thread's local storage pointer. */ 156static inline int 157__gthread_objc_thread_set_data (void *value) 158{ 159 return NXKeySetValue (_objc_thread_storage, value); 160} 161 162/* Returns the thread's local storage pointer. */ 163static inline void * 164__gthread_objc_thread_get_data (void) 165{ 166 void *value; 167 168 if (NXKeyGetValue (_objc_thread_storage, &value) == 0) 169 return value; 170 return NULL; 171} 172 173/* Backend mutex functions */ 174 175/* Allocate a mutex. */ 176static inline int 177__gthread_objc_mutex_allocate (objc_mutex_t mutex) 178{ 179 static const NX_LOCK_INFO_ALLOC (info, "GNU ObjC", 0); 180 181 if ((mutex->backend = NXMutexAlloc (0, 0, &info)) == NULL) 182 return 0; 183 return -1; 184} 185 186/* Deallocate a mutex. */ 187static inline int 188__gthread_objc_mutex_deallocate (objc_mutex_t mutex) 189{ 190 while (NXMutexIsOwned ((NXMutex_t *)mutex->backend)) 191 NXUnlock ((NXMutex_t *)mutex->backend); 192 if (NXMutexFree ((NXMutex_t *)mutex->backend) != 0) 193 return -1; 194 mutex->backend = NULL; 195 return 0; 196} 197 198/* Grab a lock on a mutex. */ 199static inline int 200__gthread_objc_mutex_lock (objc_mutex_t mutex) 201{ 202 return NXLock ((NXMutex_t *)mutex->backend); 203} 204 205/* Try to grab a lock on a mutex. */ 206static inline int 207__gthread_objc_mutex_trylock (objc_mutex_t mutex) 208{ 209 if (!NXTryLock ((NXMutex_t *)mutex->backend)) 210 return -1; 211 return 0; 212} 213 214/* Unlock the mutex */ 215static inline int 216__gthread_objc_mutex_unlock (objc_mutex_t mutex) 217{ 218 return NXUnlock ((NXMutex_t *)mutex->backend); 219} 220 221/* Backend condition mutex functions */ 222 223/* Allocate a condition. */ 224static inline int 225__gthread_objc_condition_allocate (objc_condition_t condition) 226{ 227 condition->backend = NXCondAlloc (NULL); 228 if (condition->backend == NULL) 229 return -1; 230 231 return 0; 232} 233 234/* Deallocate a condition. */ 235static inline int 236__gthread_objc_condition_deallocate (objc_condition_t condition) 237{ 238 if (NXCondFree ((NXCond_t *)condition->backend) != 0) 239 return -1; 240 condition->backend = NULL; 241 return 0; 242} 243 244/* Wait on the condition */ 245static inline int 246__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) 247{ 248 return NXCondWait ((NXCond_t *)condition->backend, (NXMutex_t *)mutex->backend); 249} 250 251/* Wake up all threads waiting on this condition. */ 252static inline int 253__gthread_objc_condition_broadcast (objc_condition_t condition) 254{ 255 return NXCondBroadcast ((NXCond_t *)condition->backend); 256} 257 258/* Wake up one thread waiting on this condition. */ 259static inline int 260__gthread_objc_condition_signal (objc_condition_t condition) 261{ 262 return NXCondSignal ((NXCond_t *)condition->backend); 263} 264 265#else /* _LIBOBJC */ 266 267#if defined(__cplusplus) 268# include <bits/atomicity.h> 269/* The remaining conditions here are temporary until there is 270 an application accessible atomic operations API set... */ 271#elif defined(_M_IA64) || defined(__ia64__) 272# include <../libstdc++-v3/config/cpu/ia64/bits/atomicity.h> 273#elif defined(_M_IX86) || defined(__i486__) 274# include <../libstdc++-v3/config/cpu/i486/bits/atomicity.h> 275#elif defined(_M_AMD64) || defined(__x86_64__) 276# include <../libstdc++-v3/config/cpu/x86-64/bits/atomicity.h> 277#endif 278 279typedef volatile long __gthread_once_t; 280 281#define __GTHREAD_ONCE_INIT 0 282 283static inline int 284__gthread_once (__gthread_once_t *once, void (*func) (void)) 285{ 286 if (__compare_and_swap (once, 0, 1)) 287 { 288 func(); 289 *once |= 2; 290 } 291 else 292 { 293 while (!(*once & 2)) 294 NXThreadYield (); 295 } 296 return 0; 297} 298 299static inline int 300__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) 301{ 302 return NXKeyCreate (dtor, NULL, key); 303} 304 305static inline int 306__gthread_key_dtor (__gthread_key_t key, void *ptr) 307{ 308 /* Just reset the key value to zero. */ 309 if (ptr) 310 return NXKeySetValue (key, NULL); 311 return 0; 312} 313 314static inline int 315__gthread_key_delete (__gthread_key_t key) 316{ 317 return NXKeyDelete (key); 318} 319 320static inline void * 321__gthread_getspecific (__gthread_key_t key) 322{ 323 void *value; 324 325 if (NXKeyGetValue (key, &value) == 0) 326 return value; 327 return NULL; 328} 329 330static inline int 331__gthread_setspecific (__gthread_key_t key, const void *ptr) 332{ 333 return NXKeySetValue (key, (void *)ptr); 334} 335 336static inline void 337__gthread_mutex_init_function (__gthread_mutex_t *mutex) 338{ 339 static const NX_LOCK_INFO_ALLOC (info, "GTHREADS", 0); 340 341 *mutex = NXMutexAlloc (0, 0, &info); 342} 343 344static inline int 345__gthread_mutex_lock (__gthread_mutex_t *mutex) 346{ 347 return NXLock (*mutex); 348} 349 350static inline int 351__gthread_mutex_trylock (__gthread_mutex_t *mutex) 352{ 353 if (NXTryLock (*mutex)) 354 return 0; 355 return -1; 356} 357 358static inline int 359__gthread_mutex_unlock (__gthread_mutex_t *mutex) 360{ 361 return NXUnlock (*mutex); 362} 363 364static inline void 365__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) 366{ 367 static const NX_LOCK_INFO_ALLOC (info, "GTHREADS", 0); 368 369 *mutex = NXMutexAlloc (NX_MUTEX_RECURSIVE, 0, &info); 370} 371 372static inline int 373__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) 374{ 375 return NXLock (*mutex); 376} 377 378static inline int 379__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) 380{ 381 if (NXTryLock (*mutex)) 382 return 0; 383 return -1; 384} 385 386static inline int 387__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) 388{ 389 return NXUnlock (*mutex); 390} 391 392#endif /* _LIBOBJC */ 393 394#endif /* not GCC_GTHR_NKS_H */ 395