MFV r313071:
[freebsd.git] / contrib / gcc / gthr-nks.h
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 */