| /* Threads compatibility routines for libgcc2 and libobjc. */ |
| /* Compile this one with gcc. */ |
| /* Copyright (C) 2002, 2003, 2004, 2008, 2009 Free Software Foundation, Inc. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it under |
| the terms of the GNU General Public License as published by the Free |
| Software Foundation; either version 3, or (at your option) any later |
| version. |
| |
| GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| for more details. |
| |
| Under Section 7 of GPL version 3, you are granted additional |
| permissions described in the GCC Runtime Library Exception, version |
| 3.1, as published by the Free Software Foundation. |
| |
| You should have received a copy of the GNU General Public License and |
| a copy of the GCC Runtime Library Exception along with this program; |
| see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #ifndef GCC_GTHR_NKS_H |
| #define GCC_GTHR_NKS_H |
| |
| /* NKS threads specific definitions. |
| Easy, since the interface is mostly one-to-one mapping. */ |
| |
| #define __GTHREADS 1 |
| |
| #define NKS_NO_INLINE_FUNCS |
| #include <nksapi.h> |
| #include <string.h> |
| |
| typedef NXKey_t __gthread_key_t; |
| typedef NXMutex_t *__gthread_mutex_t; |
| typedef NXMutex_t *__gthread_recursive_mutex_t; |
| |
| #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function |
| #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function |
| |
| static inline int |
| __gthread_active_p (void) |
| { |
| return 1; |
| } |
| |
| #ifdef _LIBOBJC |
| |
| /* This is the config.h file in libobjc/ */ |
| #include <config.h> |
| |
| #ifdef HAVE_SCHED_H |
| # include <sched.h> |
| #endif |
| |
| /* Key structure for maintaining thread specific storage */ |
| static NXKey_t _objc_thread_storage; |
| |
| /* Backend initialization functions */ |
| |
| /* Initialize the threads subsystem. */ |
| static inline int |
| __gthread_objc_init_thread_system (void) |
| { |
| /* Initialize the thread storage key. */ |
| if (NXKeyCreate (NULL, NULL, &_objc_thread_storage) == 0) |
| return 0; |
| return -1; |
| } |
| |
| /* Close the threads subsystem. */ |
| static inline int |
| __gthread_objc_close_thread_system (void) |
| { |
| if (NXKeyDelete (_objc_thread_storage) == 0) |
| return 0; |
| return -1; |
| } |
| |
| /* Backend thread functions */ |
| |
| /* Create a new thread of execution. */ |
| static inline objc_thread_t |
| __gthread_objc_thread_detach (void (*func)(void *), void *arg) |
| { |
| objc_thread_t thread_id; |
| NXContext_t context; |
| NXThreadId_t new_thread_handle; |
| int err; |
| |
| if ((context = NXContextAlloc (func, arg, NX_PRIO_MED, 0, 0, 0, &err)) == NULL) |
| thread_id = NULL; |
| else if (NXThreadCreate (context, NX_THR_DETACHED, &new_thread_handle) == 0) |
| thread_id = (objc_thread_t) new_thread_handle; |
| else { |
| NXContextFree (context); |
| thread_id = NULL; |
| } |
| |
| return thread_id; |
| } |
| |
| /* Set the current thread's priority. */ |
| static inline int |
| __gthread_objc_thread_set_priority (int priority) |
| { |
| if (NXThreadSetPriority (NXThreadGetId (), priority) == 0) |
| return 0; |
| return -1; |
| } |
| |
| /* Return the current thread's priority. */ |
| static inline int |
| __gthread_objc_thread_get_priority (void) |
| { |
| int priority; |
| |
| if (NXThreadGetPriority (NXThreadGetId (), &priority) == 0) |
| return priority; |
| return -1; |
| } |
| |
| /* Yield our process time to another thread. */ |
| static inline void |
| __gthread_objc_thread_yield (void) |
| { |
| NXThreadYield (); |
| } |
| |
| /* Terminate the current thread. */ |
| static inline int |
| __gthread_objc_thread_exit (void) |
| { |
| /* exit the thread */ |
| NXThreadExit (&__objc_thread_exit_status); |
| |
| /* Failed if we reached here */ |
| return -1; |
| } |
| |
| /* Returns an integer value which uniquely describes a thread. */ |
| static inline objc_thread_t |
| __gthread_objc_thread_id (void) |
| { |
| (objc_thread_t) NXThreadGetId (); |
| } |
| |
| /* Sets the thread's local storage pointer. */ |
| static inline int |
| __gthread_objc_thread_set_data (void *value) |
| { |
| return NXKeySetValue (_objc_thread_storage, value); |
| } |
| |
| /* Returns the thread's local storage pointer. */ |
| static inline void * |
| __gthread_objc_thread_get_data (void) |
| { |
| void *value; |
| |
| if (NXKeyGetValue (_objc_thread_storage, &value) == 0) |
| return value; |
| return NULL; |
| } |
| |
| /* Backend mutex functions */ |
| |
| /* Allocate a mutex. */ |
| static inline int |
| __gthread_objc_mutex_allocate (objc_mutex_t mutex) |
| { |
| static const NX_LOCK_INFO_ALLOC (info, "GNU ObjC", 0); |
| |
| if ((mutex->backend = NXMutexAlloc (0, 0, &info)) == NULL) |
| return 0; |
| return -1; |
| } |
| |
| /* Deallocate a mutex. */ |
| static inline int |
| __gthread_objc_mutex_deallocate (objc_mutex_t mutex) |
| { |
| while (NXMutexIsOwned ((NXMutex_t *)mutex->backend)) |
| NXUnlock ((NXMutex_t *)mutex->backend); |
| if (NXMutexFree ((NXMutex_t *)mutex->backend) != 0) |
| return -1; |
| mutex->backend = NULL; |
| return 0; |
| } |
| |
| /* Grab a lock on a mutex. */ |
| static inline int |
| __gthread_objc_mutex_lock (objc_mutex_t mutex) |
| { |
| return NXLock ((NXMutex_t *)mutex->backend); |
| } |
| |
| /* Try to grab a lock on a mutex. */ |
| static inline int |
| __gthread_objc_mutex_trylock (objc_mutex_t mutex) |
| { |
| if (!NXTryLock ((NXMutex_t *)mutex->backend)) |
| return -1; |
| return 0; |
| } |
| |
| /* Unlock the mutex */ |
| static inline int |
| __gthread_objc_mutex_unlock (objc_mutex_t mutex) |
| { |
| return NXUnlock ((NXMutex_t *)mutex->backend); |
| } |
| |
| /* Backend condition mutex functions */ |
| |
| /* Allocate a condition. */ |
| static inline int |
| __gthread_objc_condition_allocate (objc_condition_t condition) |
| { |
| condition->backend = NXCondAlloc (NULL); |
| if (condition->backend == NULL) |
| return -1; |
| |
| return 0; |
| } |
| |
| /* Deallocate a condition. */ |
| static inline int |
| __gthread_objc_condition_deallocate (objc_condition_t condition) |
| { |
| if (NXCondFree ((NXCond_t *)condition->backend) != 0) |
| return -1; |
| condition->backend = NULL; |
| return 0; |
| } |
| |
| /* Wait on the condition */ |
| static inline int |
| __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) |
| { |
| return NXCondWait ((NXCond_t *)condition->backend, (NXMutex_t *)mutex->backend); |
| } |
| |
| /* Wake up all threads waiting on this condition. */ |
| static inline int |
| __gthread_objc_condition_broadcast (objc_condition_t condition) |
| { |
| return NXCondBroadcast ((NXCond_t *)condition->backend); |
| } |
| |
| /* Wake up one thread waiting on this condition. */ |
| static inline int |
| __gthread_objc_condition_signal (objc_condition_t condition) |
| { |
| return NXCondSignal ((NXCond_t *)condition->backend); |
| } |
| |
| #else /* _LIBOBJC */ |
| |
| #if defined(__cplusplus) |
| # include <bits/atomicity.h> |
| /* The remaining conditions here are temporary until there is |
| an application accessible atomic operations API set... */ |
| #elif defined(_M_IA64) || defined(__ia64__) |
| # include <../libstdc++-v3/config/cpu/ia64/bits/atomicity.h> |
| #elif defined(_M_IX86) || defined(__i486__) |
| # include <../libstdc++-v3/config/cpu/i486/bits/atomicity.h> |
| #elif defined(_M_AMD64) || defined(__x86_64__) |
| # include <../libstdc++-v3/config/cpu/x86-64/bits/atomicity.h> |
| #endif |
| |
| typedef volatile long __gthread_once_t; |
| |
| #define __GTHREAD_ONCE_INIT 0 |
| |
| static inline int |
| __gthread_once (__gthread_once_t *__once, void (*__func) (void)) |
| { |
| if (__compare_and_swap (__once, 0, 1)) |
| { |
| __func (); |
| *__once |= 2; |
| } |
| else |
| { |
| while (!(*__once & 2)) |
| NXThreadYield (); |
| } |
| return 0; |
| } |
| |
| static inline int |
| __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) |
| { |
| return NXKeyCreate (__dtor, NULL, __key); |
| } |
| |
| static inline int |
| __gthread_key_dtor (__gthread_key_t __key, void *__ptr) |
| { |
| /* Just reset the key value to zero. */ |
| if (__ptr) |
| return NXKeySetValue (__key, NULL); |
| return 0; |
| } |
| |
| static inline int |
| __gthread_key_delete (__gthread_key_t __key) |
| { |
| return NXKeyDelete (__key); |
| } |
| |
| static inline void * |
| __gthread_getspecific (__gthread_key_t __key) |
| { |
| void *__value; |
| |
| if (NXKeyGetValue (__key, &__value) == 0) |
| return __value; |
| return NULL; |
| } |
| |
| static inline int |
| __gthread_setspecific (__gthread_key_t __key, const void *__ptr) |
| { |
| return NXKeySetValue (__key, (void *)__ptr); |
| } |
| |
| static inline void |
| __gthread_mutex_init_function (__gthread_mutex_t *__mutex) |
| { |
| static const NX_LOCK_INFO_ALLOC (__info, "GTHREADS", 0); |
| |
| *__mutex = NXMutexAlloc (0, 0, &__info); |
| } |
| |
| static inline int |
| __gthread_mutex_destroy (__gthread_mutex_t * UNUSED(__mutex)) |
| { |
| return 0; |
| } |
| |
| static inline int |
| __gthread_mutex_lock (__gthread_mutex_t *__mutex) |
| { |
| return NXLock (*__mutex); |
| } |
| |
| static inline int |
| __gthread_mutex_trylock (__gthread_mutex_t *__mutex) |
| { |
| if (NXTryLock (*__mutex)) |
| return 0; |
| return -1; |
| } |
| |
| static inline int |
| __gthread_mutex_unlock (__gthread_mutex_t *__mutex) |
| { |
| return NXUnlock (*__mutex); |
| } |
| |
| static inline void |
| __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) |
| { |
| static const NX_LOCK_INFO_ALLOC (__info, "GTHREADS", 0); |
| |
| *__mutex = NXMutexAlloc (NX_MUTEX_RECURSIVE, 0, &__info); |
| } |
| |
| static inline int |
| __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) |
| { |
| return NXLock (*__mutex); |
| } |
| |
| static inline int |
| __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) |
| { |
| if (NXTryLock (*__mutex)) |
| return 0; |
| return -1; |
| } |
| |
| static inline int |
| __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) |
| { |
| return NXUnlock (*__mutex); |
| } |
| |
| #endif /* _LIBOBJC */ |
| |
| #endif /* not GCC_GTHR_NKS_H */ |