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 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 2, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING. If not, write to the Free 19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20 02110-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 41 typedef NXKey_t __gthread_key_t; 42 typedef NXMutex_t *__gthread_mutex_t; 43 typedef 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 48 static 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 */ 64 static NXKey_t _objc_thread_storage; 65 66 /* Backend initialization functions */ 67 68 /* Initialize the threads subsystem. */ 69 static 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. */ 79 static 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. */ 90 static 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. */ 111 static 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. */ 120 static 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. */ 131 static inline void 132 __gthread_objc_thread_yield (void) 133 { 134 NXThreadYield (); 135 } 136 137 /* Terminate the current thread. */ 138 static 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. */ 149 static 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. */ 156 static 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. */ 163 static 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. */ 176 static 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. */ 187 static 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. */ 199 static 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. */ 206 static 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 */ 215 static 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. */ 224 static 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. */ 235 static 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 */ 245 static 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. */ 252 static 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. */ 259 static 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 279 typedef volatile long __gthread_once_t; 280 281 #define __GTHREAD_ONCE_INIT 0 282 283 static 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 299 static inline int 300 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) 301 { 302 return NXKeyCreate (dtor, NULL, key); 303 } 304 305 static 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 314 static inline int 315 __gthread_key_delete (__gthread_key_t key) 316 { 317 return NXKeyDelete (key); 318 } 319 320 static 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 330 static inline int 331 __gthread_setspecific (__gthread_key_t key, const void *ptr) 332 { 333 return NXKeySetValue (key, (void *)ptr); 334 } 335 336 static 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 344 static inline int 345 __gthread_mutex_lock (__gthread_mutex_t *mutex) 346 { 347 return NXLock (*mutex); 348 } 349 350 static inline int 351 __gthread_mutex_trylock (__gthread_mutex_t *mutex) 352 { 353 if (NXTryLock (*mutex)) 354 return 0; 355 return -1; 356 } 357 358 static inline int 359 __gthread_mutex_unlock (__gthread_mutex_t *mutex) 360 { 361 return NXUnlock (*mutex); 362 } 363 364 static 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 372 static inline int 373 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) 374 { 375 return NXLock (*mutex); 376 } 377 378 static 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 386 static 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