OSDN Git Service

M68K TLS support.
[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, 2003, 2004, 2008, 2009 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 3, 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 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.
20
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/>.  */
25
26 #ifndef GCC_GTHR_NKS_H
27 #define GCC_GTHR_NKS_H
28
29 /* NKS threads specific definitions.
30    Easy, since the interface is mostly one-to-one mapping.  */
31
32 #define __GTHREADS 1
33
34 #define NKS_NO_INLINE_FUNCS
35 #include <nksapi.h>
36 #include <string.h>
37
38 typedef NXKey_t __gthread_key_t;
39 typedef NXMutex_t *__gthread_mutex_t;
40 typedef NXMutex_t *__gthread_recursive_mutex_t;
41
42 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
43 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
44
45 static inline int
46 __gthread_active_p (void)
47 {
48   return 1;
49 }
50
51 #ifdef _LIBOBJC
52
53 /* This is the config.h file in libobjc/ */
54 #include <config.h>
55
56 #ifdef HAVE_SCHED_H
57 # include <sched.h>
58 #endif
59
60 /* Key structure for maintaining thread specific storage */
61 static NXKey_t _objc_thread_storage;
62
63 /* Backend initialization functions */
64
65 /* Initialize the threads subsystem.  */
66 static inline int
67 __gthread_objc_init_thread_system (void)
68 {
69   /* Initialize the thread storage key.  */
70   if (NXKeyCreate (NULL, NULL, &_objc_thread_storage) == 0)
71     return 0;
72   return -1;
73 }
74
75 /* Close the threads subsystem.  */
76 static inline int
77 __gthread_objc_close_thread_system (void)
78 {
79   if (NXKeyDelete (_objc_thread_storage) == 0)
80     return 0;
81   return -1;
82 }
83
84 /* Backend thread functions */
85
86 /* Create a new thread of execution.  */
87 static inline objc_thread_t
88 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
89 {
90   objc_thread_t thread_id;
91   NXContext_t context;
92   NXThreadId_t new_thread_handle;
93   int err;
94
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;
102   }
103   
104   return thread_id;
105 }
106
107 /* Set the current thread's priority.  */
108 static inline int
109 __gthread_objc_thread_set_priority (int priority)
110 {
111   if (NXThreadSetPriority (NXThreadGetId (), priority) == 0)
112     return 0;
113   return -1;
114 }
115
116 /* Return the current thread's priority.  */
117 static inline int
118 __gthread_objc_thread_get_priority (void)
119 {
120   int priority;
121
122   if (NXThreadGetPriority (NXThreadGetId (), &priority) == 0)
123     return priority;
124   return -1;
125 }
126
127 /* Yield our process time to another thread.  */
128 static inline void
129 __gthread_objc_thread_yield (void)
130 {
131   NXThreadYield ();
132 }
133
134 /* Terminate the current thread.  */
135 static inline int
136 __gthread_objc_thread_exit (void)
137 {
138   /* exit the thread */
139   NXThreadExit (&__objc_thread_exit_status);
140
141   /* Failed if we reached here */
142   return -1;
143 }
144
145 /* Returns an integer value which uniquely describes a thread.  */
146 static inline objc_thread_t
147 __gthread_objc_thread_id (void)
148 {
149   (objc_thread_t) NXThreadGetId ();
150 }
151
152 /* Sets the thread's local storage pointer.  */
153 static inline int
154 __gthread_objc_thread_set_data (void *value)
155 {
156   return NXKeySetValue (_objc_thread_storage, value);
157 }
158
159 /* Returns the thread's local storage pointer.  */
160 static inline void *
161 __gthread_objc_thread_get_data (void)
162 {
163   void *value;
164
165   if (NXKeyGetValue (_objc_thread_storage, &value) == 0)
166     return value;
167   return NULL;
168 }
169
170 /* Backend mutex functions */
171
172 /* Allocate a mutex.  */
173 static inline int
174 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
175 {
176   static const NX_LOCK_INFO_ALLOC (info, "GNU ObjC", 0);
177
178   if ((mutex->backend = NXMutexAlloc (0, 0, &info)) == NULL)
179     return 0;
180   return -1;
181 }
182
183 /* Deallocate a mutex.  */
184 static inline int
185 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
186 {
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;
193 }
194
195 /* Grab a lock on a mutex.  */
196 static inline int
197 __gthread_objc_mutex_lock (objc_mutex_t mutex)
198 {
199   return NXLock ((NXMutex_t *)mutex->backend);
200 }
201
202 /* Try to grab a lock on a mutex.  */
203 static inline int
204 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
205 {
206   if (!NXTryLock ((NXMutex_t *)mutex->backend))
207     return -1;
208   return 0;
209 }
210
211 /* Unlock the mutex */
212 static inline int
213 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
214 {
215   return NXUnlock ((NXMutex_t *)mutex->backend);
216 }
217
218 /* Backend condition mutex functions */
219
220 /* Allocate a condition.  */
221 static inline int
222 __gthread_objc_condition_allocate (objc_condition_t condition)
223 {
224   condition->backend = NXCondAlloc (NULL);
225   if (condition->backend == NULL)
226     return -1;
227
228   return 0;
229 }
230
231 /* Deallocate a condition.  */
232 static inline int
233 __gthread_objc_condition_deallocate (objc_condition_t condition)
234 {
235    if (NXCondFree ((NXCond_t *)condition->backend) != 0)
236      return -1;
237    condition->backend = NULL;
238    return 0;
239 }
240
241 /* Wait on the condition */
242 static inline int
243 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
244 {
245   return NXCondWait ((NXCond_t *)condition->backend, (NXMutex_t *)mutex->backend);
246 }
247
248 /* Wake up all threads waiting on this condition.  */
249 static inline int
250 __gthread_objc_condition_broadcast (objc_condition_t condition)
251 {
252   return NXCondBroadcast ((NXCond_t *)condition->backend);
253 }
254
255 /* Wake up one thread waiting on this condition.  */
256 static inline int
257 __gthread_objc_condition_signal (objc_condition_t condition)
258 {
259   return NXCondSignal ((NXCond_t *)condition->backend);
260 }
261
262 #else /* _LIBOBJC */
263
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
275
276 typedef volatile long __gthread_once_t;
277
278 #define __GTHREAD_ONCE_INIT 0
279
280 static inline int
281 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
282 {
283   if (__compare_and_swap (__once, 0, 1))
284   {
285     __func ();
286     *__once |= 2;
287   }
288   else
289   {
290     while (!(*__once & 2))
291       NXThreadYield ();
292   }
293   return 0;
294 }
295
296 static inline int
297 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
298 {
299   return NXKeyCreate (__dtor, NULL, __key);
300 }
301
302 static inline int
303 __gthread_key_dtor (__gthread_key_t __key, void *__ptr)
304 {
305   /* Just reset the key value to zero. */
306   if (__ptr)
307     return NXKeySetValue (__key, NULL);
308   return 0;
309 }
310
311 static inline int
312 __gthread_key_delete (__gthread_key_t __key)
313 {
314   return NXKeyDelete (__key);
315 }
316
317 static inline void *
318 __gthread_getspecific (__gthread_key_t __key)
319 {
320   void *__value;
321
322   if (NXKeyGetValue (__key, &__value) == 0)
323     return __value;
324   return NULL;
325 }
326
327 static inline int
328 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
329 {
330   return NXKeySetValue (__key, (void *)__ptr);
331 }
332
333 static inline void
334 __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
335 {
336   static const NX_LOCK_INFO_ALLOC (__info, "GTHREADS", 0);
337
338   *__mutex = NXMutexAlloc (0, 0, &__info);
339 }
340
341 static inline int
342 __gthread_mutex_destroy (__gthread_mutex_t * UNUSED(__mutex))
343 {
344   return 0;
345 }
346
347 static inline int
348 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
349 {
350   return NXLock (*__mutex);
351 }
352
353 static inline int
354 __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
355 {
356   if (NXTryLock (*__mutex))
357     return 0;
358   return -1;
359 }
360
361 static inline int
362 __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
363 {
364   return NXUnlock (*__mutex);
365 }
366
367 static inline void
368 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
369 {
370   static const NX_LOCK_INFO_ALLOC (__info, "GTHREADS", 0);
371
372   *__mutex = NXMutexAlloc (NX_MUTEX_RECURSIVE, 0, &__info);
373 }
374
375 static inline int
376 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
377 {
378   return NXLock (*__mutex);
379 }
380
381 static inline int
382 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
383 {
384   if (NXTryLock (*__mutex))
385     return 0;
386   return -1;
387 }
388
389 static inline int
390 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
391 {
392   return NXUnlock (*__mutex);
393 }
394
395 #endif /* _LIBOBJC */
396
397 #endif /* not GCC_GTHR_NKS_H */