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