OSDN Git Service

PR middle-end/17055
[pf3gnuchains/gcc-fork.git] / gcc / gthr-nks.h
1 /* Threads compatibility routines for libgcc2 and libobjc.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 2002 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
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License 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
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, 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 __gthr_nks_h
30 #define __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
44 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
45
46 static inline int
47 __gthread_active_p (void)
48 {
49   return 1;
50 }
51
52 #ifdef _LIBOBJC
53
54 /* This is the config.h file in libobjc/ */
55 #include <config.h>
56
57 #ifdef HAVE_SCHED_H
58 # include <sched.h>
59 #endif
60
61 /* Key structure for maintaining thread specific storage */
62 static NXKey_t _objc_thread_storage;
63
64 /* Backend initialization functions */
65
66 /* Initialize the threads subsystem.  */
67 static inline int
68 __gthread_objc_init_thread_system(void)
69 {
70   /* Initialize the thread storage key */
71   if (NXKeyCreate(NULL, NULL, &_objc_thread_storage) == 0)
72     return 0;
73   return -1;
74 }
75
76 /* Close the threads subsystem.  */
77 static inline int
78 __gthread_objc_close_thread_system(void)
79 {
80   if (NXKeyDelete(_objc_thread_storage) == 0)
81     return 0;
82   return -1;
83 }
84
85 /* Backend thread functions */
86
87 /* Create a new thread of execution.  */
88 static inline objc_thread_t
89 __gthread_objc_thread_detach(void (*func)(void *), void *arg)
90 {
91   objc_thread_t thread_id;
92   NXContext_t context;
93   NXThreadId_t new_thread_handle;
94   int err;
95
96   if ((context = NXContextAlloc(func, arg, NX_PRIO_MED, 0, 0, 0, &err)) == NULL)
97     thread_id = NULL;
98   else if (NXThreadCreate(context, NX_THR_DETACHED, &new_thread_handle) == 0)
99     thread_id = (objc_thread_t) new_thread_handle;
100   else {
101     NXContextFree(context);
102     thread_id = NULL;
103   }
104   
105   return thread_id;
106 }
107
108 /* Set the current thread's priority.  */
109 static inline int
110 __gthread_objc_thread_set_priority(int priority)
111 {
112   if (NXThreadSetPriority(NXThreadGetId(), priority) == 0)
113     return 0;
114   return -1;
115 }
116
117 /* Return the current thread's priority.  */
118 static inline int
119 __gthread_objc_thread_get_priority(void)
120 {
121   int priority;
122
123   if (NXThreadGetPriority(NXThreadGetId(), &priority) == 0)
124     return priority;
125   return -1;
126 }
127
128 /* Yield our process time to another thread.  */
129 static inline void
130 __gthread_objc_thread_yield(void)
131 {
132   NXThreadYield();
133 }
134
135 /* Terminate the current thread.  */
136 static inline int
137 __gthread_objc_thread_exit(void)
138 {
139   /* exit the thread */
140   NXThreadExit(&__objc_thread_exit_status);
141
142   /* Failed if we reached here */
143   return -1;
144 }
145
146 /* Returns an integer value which uniquely describes a thread.  */
147 static inline objc_thread_t
148 __gthread_objc_thread_id(void)
149 {
150   (objc_thread_t) NXThreadGetId();
151 }
152
153 /* Sets the thread's local storage pointer.  */
154 static inline int
155 __gthread_objc_thread_set_data(void *value)
156 {
157   return NXKeySetValue(_objc_thread_storage, value);
158 }
159
160 /* Returns the thread's local storage pointer.  */
161 static inline void *
162 __gthread_objc_thread_get_data(void)
163 {
164   void *value;
165
166   if (NXKeyGetValue(_objc_thread_storage, &value) == 0)
167     return value;
168   return NULL;
169 }
170
171 /* Backend mutex functions */
172
173 /* Allocate a mutex.  */
174 static inline int
175 __gthread_objc_mutex_allocate(objc_mutex_t mutex)
176 {
177   static const NX_LOCK_INFO_ALLOC(info, "GNU ObjC", 0);
178
179   if ((mutex->backend = NXMutexAlloc(NX_MUTEX_RECURSIVE/*???*/, 0, &info)) == NULL)
180     return 0;
181   return -1;
182 }
183
184 /* Deallocate a mutex.  */
185 static inline int
186 __gthread_objc_mutex_deallocate(objc_mutex_t mutex)
187 {
188   while(NXMutexIsOwned((NXMutex_t *)mutex->backend))
189     NXUnlock((NXMutex_t *)mutex->backend);
190   if (NXMutexFree((NXMutex_t *)mutex->backend) != 0)
191     return -1;
192   mutex->backend = NULL;
193   return 0;
194 }
195
196 /* Grab a lock on a mutex.  */
197 static inline int
198 __gthread_objc_mutex_lock(objc_mutex_t mutex)
199 {
200   return NXLock((NXMutex_t *)mutex->backend);
201 }
202
203 /* Try to grab a lock on a mutex.  */
204 static inline int
205 __gthread_objc_mutex_trylock(objc_mutex_t mutex)
206 {
207   if (!NXTryLock((NXMutex_t *)mutex->backend))
208     return -1;
209   return 0;
210 }
211
212 /* Unlock the mutex */
213 static inline int
214 __gthread_objc_mutex_unlock(objc_mutex_t mutex)
215 {
216   return NXUnlock((NXMutex_t *)mutex->backend);
217 }
218
219 /* Backend condition mutex functions */
220
221 /* Allocate a condition.  */
222 static inline int
223 __gthread_objc_condition_allocate(objc_condition_t condition)
224 {
225   condition->backend = NXCondAlloc(NULL);
226   if (condition->backend == NULL)
227     return -1;
228
229   return 0;
230 }
231
232 /* Deallocate a condition.  */
233 static inline int
234 __gthread_objc_condition_deallocate(objc_condition_t condition)
235 {
236    if (NXCondFree((NXCond_t *)condition->backend) != 0)
237      return -1;
238    condition->backend = NULL;
239    return 0;
240 }
241
242 /* Wait on the condition */
243 static inline int
244 __gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
245 {
246   return NXCondWait((NXCond_t *)condition->backend, (NXMutex_t *)mutex->backend);
247 }
248
249 /* Wake up all threads waiting on this condition.  */
250 static inline int
251 __gthread_objc_condition_broadcast(objc_condition_t condition)
252 {
253   return NXCondBroadcast((NXCond_t *)condition->backend);
254 }
255
256 /* Wake up one thread waiting on this condition.  */
257 static inline int
258 __gthread_objc_condition_signal(objc_condition_t condition)
259 {
260   return NXCondSignal((NXCond_t *)condition->backend);
261 }
262
263 #else /* _LIBOBJC */
264
265 #if defined(__cplusplus)
266 # include <bits/atomicity.h>
267 /* The remaining conditions here are temporary until there is
268    an application accessible atomic operations API set... */
269 #elif defined(_M_IA64) || defined(__ia64__)
270 # include <../libstdc++-v3/config/cpu/ia64/bits/atomicity.h>
271 #elif defined(_M_IX86) || defined(__i486__)
272 # include <../libstdc++-v3/config/cpu/i486/bits/atomicity.h>
273 #elif defined(_M_AMD64) || defined(__x86_64__)
274 # include <../libstdc++-v3/config/cpu/x86-64/bits/atomicity.h>
275 #endif
276
277 typedef volatile long __gthread_once_t;
278
279 #define __GTHREAD_ONCE_INIT 0
280
281 static inline int
282 __gthread_once (__gthread_once_t *once, void (*func) (void))
283 {
284   if (__compare_and_swap(once, 0, 1))
285   {
286     func();
287     *once |= 2;
288   }
289   else
290   {
291     while(!(*once & 2))
292       NXThreadYield();
293   }
294   return 0;
295 }
296
297 static inline int
298 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
299 {
300   return NXKeyCreate (dtor, NULL, key);
301 }
302
303 static inline int
304 __gthread_key_dtor (__gthread_key_t key, void *ptr)
305 {
306   /* Just reset the key value to zero.  */
307   if (ptr)
308     return NXKeySetValue (key, NULL);
309   return 0;
310 }
311
312 static inline int
313 __gthread_key_delete (__gthread_key_t key)
314 {
315   return NXKeyDelete (key);
316 }
317
318 static inline void *
319 __gthread_getspecific (__gthread_key_t key)
320 {
321   void *value;
322
323   if (NXKeyGetValue(key, &value) == 0)
324     return value;
325   return NULL;
326 }
327
328 static inline int
329 __gthread_setspecific (__gthread_key_t key, const void *ptr)
330 {
331   return NXKeySetValue(key, (void *)ptr);
332 }
333
334 static inline void
335 __gthread_mutex_init_function (__gthread_mutex_t *mutex)
336 {
337   static const NX_LOCK_INFO_ALLOC(info, "GTHREADS", 0);
338
339   *mutex = NXMutexAlloc (NX_MUTEX_RECURSIVE/*???*/, 0, &info);
340 }
341
342 static inline int
343 __gthread_mutex_lock (__gthread_mutex_t *mutex)
344 {
345   return NXLock(*mutex);
346 }
347
348 static inline int
349 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
350 {
351   if (NXTryLock(*mutex))
352     return 0;
353   return -1;
354 }
355
356 static inline int
357 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
358 {
359   return NXUnlock(*mutex);
360 }
361
362 #endif /* _LIBOBJC */
363
364 #endif /* not __gthr_nks_h */