1256106Sdes/* Threads compatibility routines for libgcc2 and libobjc. */ 2256106Sdes/* Compile this one with gcc. */ 3256106Sdes/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. 4256106Sdes 5256106SdesThis file is part of GCC. 6256106Sdes 7256106SdesGCC is free software; you can redistribute it and/or modify it under 8256106Sdesthe terms of the GNU General Public License as published by the Free 9256106SdesSoftware Foundation; either version 2, or (at your option) any later 10256106Sdesversion. 11256106Sdes 12256106SdesGCC is distributed in the hope that it will be useful, but WITHOUT ANY 13256106SdesWARRANTY; without even the implied warranty of MERCHANTABILITY or 14256106SdesFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15256106Sdesfor more details. 16256106Sdes 17256106SdesYou should have received a copy of the GNU General Public License 18256106Sdesalong with GCC; see the file COPYING. If not, write to the Free 19256106SdesSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20256106Sdes02110-1301, USA. */ 21256106Sdes 22256106Sdes/* As a special exception, if you link this library with other files, 23256106Sdes some of which are compiled with GCC, to produce an executable, 24256106Sdes this library does not by itself cause the resulting executable 25256106Sdes to be covered by the GNU General Public License. 26256106Sdes This exception does not however invalidate any other reasons why 27256106Sdes the executable file might be covered by the GNU General Public License. */ 28256106Sdes 29256106Sdes#ifndef GCC_GTHR_NKS_H 30256106Sdes#define GCC_GTHR_NKS_H 31256106Sdes 32256106Sdes/* NKS threads specific definitions. 33256106Sdes Easy, since the interface is mostly one-to-one mapping. */ 34256106Sdes 35256106Sdes#define __GTHREADS 1 36256106Sdes 37256106Sdes#define NKS_NO_INLINE_FUNCS 38256106Sdes#include <nksapi.h> 39256106Sdes#include <string.h> 40256106Sdes 41256106Sdestypedef NXKey_t __gthread_key_t; 42256106Sdestypedef NXMutex_t *__gthread_mutex_t; 43256106Sdestypedef NXMutex_t *__gthread_recursive_mutex_t; 44256106Sdes 45256106Sdes#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function 46256106Sdes#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function 47256106Sdes 48256106Sdesstatic inline int 49256106Sdes__gthread_active_p (void) 50256106Sdes{ 51256106Sdes return 1; 52256106Sdes} 53256106Sdes 54256106Sdes#ifdef _LIBOBJC 55256106Sdes 56256106Sdes/* This is the config.h file in libobjc/ */ 57256106Sdes#include <config.h> 58256106Sdes 59256106Sdes#ifdef HAVE_SCHED_H 60256106Sdes# include <sched.h> 61256106Sdes#endif 62256106Sdes 63256106Sdes/* Key structure for maintaining thread specific storage */ 64256106Sdesstatic NXKey_t _objc_thread_storage; 65256106Sdes 66256106Sdes/* Backend initialization functions */ 67256106Sdes 68256106Sdes/* Initialize the threads subsystem. */ 69256106Sdesstatic inline int 70256106Sdes__gthread_objc_init_thread_system (void) 71256106Sdes{ 72256106Sdes /* Initialize the thread storage key. */ 73256106Sdes if (NXKeyCreate (NULL, NULL, &_objc_thread_storage) == 0) 74256106Sdes return 0; 75256106Sdes return -1; 76256106Sdes} 77256106Sdes 78256106Sdes/* Close the threads subsystem. */ 79256106Sdesstatic inline int 80256106Sdes__gthread_objc_close_thread_system (void) 81256106Sdes{ 82256106Sdes if (NXKeyDelete (_objc_thread_storage) == 0) 83256106Sdes return 0; 84256106Sdes return -1; 85256106Sdes} 86256106Sdes 87256106Sdes/* Backend thread functions */ 88256106Sdes 89256106Sdes/* Create a new thread of execution. */ 90256106Sdesstatic inline objc_thread_t 91256106Sdes__gthread_objc_thread_detach (void (*func)(void *), void *arg) 92256106Sdes{ 93256106Sdes objc_thread_t thread_id; 94256106Sdes NXContext_t context; 95256106Sdes NXThreadId_t new_thread_handle; 96256106Sdes int err; 97256106Sdes 98256106Sdes if ((context = NXContextAlloc (func, arg, NX_PRIO_MED, 0, 0, 0, &err)) == NULL) 99256106Sdes thread_id = NULL; 100256106Sdes else if (NXThreadCreate (context, NX_THR_DETACHED, &new_thread_handle) == 0) 101256106Sdes thread_id = (objc_thread_t) new_thread_handle; 102256106Sdes else { 103256241Sdes NXContextFree (context); 104256106Sdes thread_id = NULL; 105256106Sdes } 106256106Sdes 107256106Sdes return thread_id; 108256106Sdes} 109256241Sdes 110256106Sdes/* Set the current thread's priority. */ 111256106Sdesstatic inline int 112256106Sdes__gthread_objc_thread_set_priority (int priority) 113256106Sdes{ 114256106Sdes if (NXThreadSetPriority (NXThreadGetId (), priority) == 0) 115256106Sdes return 0; 116256106Sdes return -1; 117256106Sdes} 118256106Sdes 119256106Sdes/* Return the current thread's priority. */ 120256106Sdesstatic inline int 121256106Sdes__gthread_objc_thread_get_priority (void) 122256106Sdes{ 123256106Sdes int priority; 124307403Ssevan 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