2010-02-26 Manuel López-Ibáñez <manu@gcc.gnu.org>
[official-gcc.git] / gcc / gthr-nks.h
blob311c6904b1ae8915b8108cd36348bf165db78479
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.
5 This file is part of GCC.
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 3, or (at your option) any later
10 version.
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.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #ifndef GCC_GTHR_NKS_H
27 #define GCC_GTHR_NKS_H
29 /* NKS threads specific definitions.
30 Easy, since the interface is mostly one-to-one mapping. */
32 #define __GTHREADS 1
34 #define NKS_NO_INLINE_FUNCS
35 #include <nksapi.h>
36 #include <string.h>
38 typedef NXKey_t __gthread_key_t;
39 typedef NXMutex_t *__gthread_mutex_t;
40 typedef NXMutex_t *__gthread_recursive_mutex_t;
42 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
43 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
45 static inline int
46 __gthread_active_p (void)
48 return 1;
51 #ifdef _LIBOBJC
53 /* This is the config.h file in libobjc/ */
54 #include <config.h>
56 #ifdef HAVE_SCHED_H
57 # include <sched.h>
58 #endif
60 /* Key structure for maintaining thread specific storage */
61 static NXKey_t _objc_thread_storage;
63 /* Backend initialization functions */
65 /* Initialize the threads subsystem. */
66 static inline int
67 __gthread_objc_init_thread_system (void)
69 /* Initialize the thread storage key. */
70 if (NXKeyCreate (NULL, NULL, &_objc_thread_storage) == 0)
71 return 0;
72 return -1;
75 /* Close the threads subsystem. */
76 static inline int
77 __gthread_objc_close_thread_system (void)
79 if (NXKeyDelete (_objc_thread_storage) == 0)
80 return 0;
81 return -1;
84 /* Backend thread functions */
86 /* Create a new thread of execution. */
87 static inline objc_thread_t
88 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
90 objc_thread_t thread_id;
91 NXContext_t context;
92 NXThreadId_t new_thread_handle;
93 int err;
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;
104 return thread_id;
107 /* Set the current thread's priority. */
108 static inline int
109 __gthread_objc_thread_set_priority (int priority)
111 if (NXThreadSetPriority (NXThreadGetId (), priority) == 0)
112 return 0;
113 return -1;
116 /* Return the current thread's priority. */
117 static inline int
118 __gthread_objc_thread_get_priority (void)
120 int priority;
122 if (NXThreadGetPriority (NXThreadGetId (), &priority) == 0)
123 return priority;
124 return -1;
127 /* Yield our process time to another thread. */
128 static inline void
129 __gthread_objc_thread_yield (void)
131 NXThreadYield ();
134 /* Terminate the current thread. */
135 static inline int
136 __gthread_objc_thread_exit (void)
138 /* exit the thread */
139 NXThreadExit (&__objc_thread_exit_status);
141 /* Failed if we reached here */
142 return -1;
145 /* Returns an integer value which uniquely describes a thread. */
146 static inline objc_thread_t
147 __gthread_objc_thread_id (void)
149 (objc_thread_t) NXThreadGetId ();
152 /* Sets the thread's local storage pointer. */
153 static inline int
154 __gthread_objc_thread_set_data (void *value)
156 return NXKeySetValue (_objc_thread_storage, value);
159 /* Returns the thread's local storage pointer. */
160 static inline void *
161 __gthread_objc_thread_get_data (void)
163 void *value;
165 if (NXKeyGetValue (_objc_thread_storage, &value) == 0)
166 return value;
167 return NULL;
170 /* Backend mutex functions */
172 /* Allocate a mutex. */
173 static inline int
174 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
176 static const NX_LOCK_INFO_ALLOC (info, "GNU ObjC", 0);
178 if ((mutex->backend = NXMutexAlloc (0, 0, &info)) == NULL)
179 return 0;
180 return -1;
183 /* Deallocate a mutex. */
184 static inline int
185 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
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;
195 /* Grab a lock on a mutex. */
196 static inline int
197 __gthread_objc_mutex_lock (objc_mutex_t mutex)
199 return NXLock ((NXMutex_t *)mutex->backend);
202 /* Try to grab a lock on a mutex. */
203 static inline int
204 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
206 if (!NXTryLock ((NXMutex_t *)mutex->backend))
207 return -1;
208 return 0;
211 /* Unlock the mutex */
212 static inline int
213 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
215 return NXUnlock ((NXMutex_t *)mutex->backend);
218 /* Backend condition mutex functions */
220 /* Allocate a condition. */
221 static inline int
222 __gthread_objc_condition_allocate (objc_condition_t condition)
224 condition->backend = NXCondAlloc (NULL);
225 if (condition->backend == NULL)
226 return -1;
228 return 0;
231 /* Deallocate a condition. */
232 static inline int
233 __gthread_objc_condition_deallocate (objc_condition_t condition)
235 if (NXCondFree ((NXCond_t *)condition->backend) != 0)
236 return -1;
237 condition->backend = NULL;
238 return 0;
241 /* Wait on the condition */
242 static inline int
243 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
245 return NXCondWait ((NXCond_t *)condition->backend, (NXMutex_t *)mutex->backend);
248 /* Wake up all threads waiting on this condition. */
249 static inline int
250 __gthread_objc_condition_broadcast (objc_condition_t condition)
252 return NXCondBroadcast ((NXCond_t *)condition->backend);
255 /* Wake up one thread waiting on this condition. */
256 static inline int
257 __gthread_objc_condition_signal (objc_condition_t condition)
259 return NXCondSignal ((NXCond_t *)condition->backend);
262 #else /* _LIBOBJC */
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
276 typedef volatile long __gthread_once_t;
278 #define __GTHREAD_ONCE_INIT 0
280 static inline int
281 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
283 if (__compare_and_swap (__once, 0, 1))
285 __func ();
286 *__once |= 2;
288 else
290 while (!(*__once & 2))
291 NXThreadYield ();
293 return 0;
296 static inline int
297 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
299 return NXKeyCreate (__dtor, NULL, __key);
302 static inline int
303 __gthread_key_dtor (__gthread_key_t __key, void *__ptr)
305 /* Just reset the key value to zero. */
306 if (__ptr)
307 return NXKeySetValue (__key, NULL);
308 return 0;
311 static inline int
312 __gthread_key_delete (__gthread_key_t __key)
314 return NXKeyDelete (__key);
317 static inline void *
318 __gthread_getspecific (__gthread_key_t __key)
320 void *__value;
322 if (NXKeyGetValue (__key, &__value) == 0)
323 return __value;
324 return NULL;
327 static inline int
328 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
330 return NXKeySetValue (__key, (void *)__ptr);
333 static inline void
334 __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
336 static const NX_LOCK_INFO_ALLOC (__info, "GTHREADS", 0);
338 *__mutex = NXMutexAlloc (0, 0, &__info);
341 static inline int
342 __gthread_mutex_destroy (__gthread_mutex_t * UNUSED(__mutex))
344 return 0;
347 static inline int
348 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
350 return NXLock (*__mutex);
353 static inline int
354 __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
356 if (NXTryLock (*__mutex))
357 return 0;
358 return -1;
361 static inline int
362 __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
364 return NXUnlock (*__mutex);
367 static inline void
368 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
370 static const NX_LOCK_INFO_ALLOC (__info, "GTHREADS", 0);
372 *__mutex = NXMutexAlloc (NX_MUTEX_RECURSIVE, 0, &__info);
375 static inline int
376 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
378 return NXLock (*__mutex);
381 static inline int
382 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
384 if (NXTryLock (*__mutex))
385 return 0;
386 return -1;
389 static inline int
390 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
392 return NXUnlock (*__mutex);
395 #endif /* _LIBOBJC */
397 #endif /* not GCC_GTHR_NKS_H */