]>
Commit | Line | Data |
---|---|---|
61fec9ff JB |
1 | /* Threads compatibility routines for libgcc2 and libobjc. */ |
2 | /* Compile this one with gcc. */ | |
f199d860 | 3 | /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. |
61fec9ff JB |
4 | |
5 | This file is part of GCC. | |
6 | ||
f199d860 JB |
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. | |
61fec9ff | 11 | |
f199d860 JB |
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. | |
61fec9ff JB |
16 | |
17 | You should have received a copy of the GNU General Public License | |
f199d860 | 18 | along with GCC; see the file COPYING. If not, write to the Free |
366ccddb KC |
19 | Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA |
20 | 02110-1301, USA. */ | |
61fec9ff JB |
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 | ||
f199d860 JB |
29 | #ifndef GCC_GTHR_NKS_H |
30 | #define GCC_GTHR_NKS_H | |
61fec9ff JB |
31 | |
32 | /* NKS threads specific definitions. | |
8c27b7d4 | 33 | Easy, since the interface is mostly one-to-one mapping. */ |
61fec9ff JB |
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; | |
f199d860 | 43 | typedef NXMutex_t *__gthread_recursive_mutex_t; |
61fec9ff JB |
44 | |
45 | #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function | |
f199d860 | 46 | #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function |
61fec9ff JB |
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 | ||
8c27b7d4 | 68 | /* Initialize the threads subsystem. */ |
61fec9ff | 69 | static inline int |
f199d860 | 70 | __gthread_objc_init_thread_system (void) |
61fec9ff | 71 | { |
f199d860 JB |
72 | /* Initialize the thread storage key. */ |
73 | if (NXKeyCreate (NULL, NULL, &_objc_thread_storage) == 0) | |
61fec9ff JB |
74 | return 0; |
75 | return -1; | |
76 | } | |
77 | ||
8c27b7d4 | 78 | /* Close the threads subsystem. */ |
61fec9ff | 79 | static inline int |
f199d860 | 80 | __gthread_objc_close_thread_system (void) |
61fec9ff | 81 | { |
f199d860 | 82 | if (NXKeyDelete (_objc_thread_storage) == 0) |
61fec9ff JB |
83 | return 0; |
84 | return -1; | |
85 | } | |
86 | ||
87 | /* Backend thread functions */ | |
88 | ||
8c27b7d4 | 89 | /* Create a new thread of execution. */ |
61fec9ff | 90 | static inline objc_thread_t |
f199d860 | 91 | __gthread_objc_thread_detach (void (*func)(void *), void *arg) |
61fec9ff JB |
92 | { |
93 | objc_thread_t thread_id; | |
94 | NXContext_t context; | |
95 | NXThreadId_t new_thread_handle; | |
96 | int err; | |
97 | ||
f199d860 | 98 | if ((context = NXContextAlloc (func, arg, NX_PRIO_MED, 0, 0, 0, &err)) == NULL) |
61fec9ff | 99 | thread_id = NULL; |
f199d860 | 100 | else if (NXThreadCreate (context, NX_THR_DETACHED, &new_thread_handle) == 0) |
61fec9ff JB |
101 | thread_id = (objc_thread_t) new_thread_handle; |
102 | else { | |
f199d860 | 103 | NXContextFree (context); |
61fec9ff JB |
104 | thread_id = NULL; |
105 | } | |
106 | ||
107 | return thread_id; | |
108 | } | |
109 | ||
8c27b7d4 | 110 | /* Set the current thread's priority. */ |
61fec9ff | 111 | static inline int |
f199d860 | 112 | __gthread_objc_thread_set_priority (int priority) |
61fec9ff | 113 | { |
f199d860 | 114 | if (NXThreadSetPriority (NXThreadGetId (), priority) == 0) |
61fec9ff JB |
115 | return 0; |
116 | return -1; | |
117 | } | |
118 | ||
8c27b7d4 | 119 | /* Return the current thread's priority. */ |
61fec9ff | 120 | static inline int |
f199d860 | 121 | __gthread_objc_thread_get_priority (void) |
61fec9ff JB |
122 | { |
123 | int priority; | |
124 | ||
f199d860 | 125 | if (NXThreadGetPriority (NXThreadGetId (), &priority) == 0) |
61fec9ff JB |
126 | return priority; |
127 | return -1; | |
128 | } | |
129 | ||
8c27b7d4 | 130 | /* Yield our process time to another thread. */ |
61fec9ff | 131 | static inline void |
f199d860 | 132 | __gthread_objc_thread_yield (void) |
61fec9ff | 133 | { |
f199d860 | 134 | NXThreadYield (); |
61fec9ff JB |
135 | } |
136 | ||
8c27b7d4 | 137 | /* Terminate the current thread. */ |
61fec9ff | 138 | static inline int |
f199d860 | 139 | __gthread_objc_thread_exit (void) |
61fec9ff JB |
140 | { |
141 | /* exit the thread */ | |
f199d860 | 142 | NXThreadExit (&__objc_thread_exit_status); |
61fec9ff JB |
143 | |
144 | /* Failed if we reached here */ | |
145 | return -1; | |
146 | } | |
147 | ||
8c27b7d4 | 148 | /* Returns an integer value which uniquely describes a thread. */ |
61fec9ff | 149 | static inline objc_thread_t |
f199d860 | 150 | __gthread_objc_thread_id (void) |
61fec9ff | 151 | { |
f199d860 | 152 | (objc_thread_t) NXThreadGetId (); |
61fec9ff JB |
153 | } |
154 | ||
8c27b7d4 | 155 | /* Sets the thread's local storage pointer. */ |
61fec9ff | 156 | static inline int |
f199d860 | 157 | __gthread_objc_thread_set_data (void *value) |
61fec9ff | 158 | { |
f199d860 | 159 | return NXKeySetValue (_objc_thread_storage, value); |
61fec9ff JB |
160 | } |
161 | ||
8c27b7d4 | 162 | /* Returns the thread's local storage pointer. */ |
61fec9ff | 163 | static inline void * |
f199d860 | 164 | __gthread_objc_thread_get_data (void) |
61fec9ff JB |
165 | { |
166 | void *value; | |
167 | ||
f199d860 | 168 | if (NXKeyGetValue (_objc_thread_storage, &value) == 0) |
61fec9ff JB |
169 | return value; |
170 | return NULL; | |
171 | } | |
172 | ||
173 | /* Backend mutex functions */ | |
174 | ||
8c27b7d4 | 175 | /* Allocate a mutex. */ |
61fec9ff | 176 | static inline int |
f199d860 | 177 | __gthread_objc_mutex_allocate (objc_mutex_t mutex) |
61fec9ff | 178 | { |
f199d860 | 179 | static const NX_LOCK_INFO_ALLOC (info, "GNU ObjC", 0); |
61fec9ff | 180 | |
019275a2 | 181 | if ((mutex->backend = NXMutexAlloc (0, 0, &info)) == NULL) |
61fec9ff JB |
182 | return 0; |
183 | return -1; | |
184 | } | |
185 | ||
8c27b7d4 | 186 | /* Deallocate a mutex. */ |
61fec9ff | 187 | static inline int |
f199d860 | 188 | __gthread_objc_mutex_deallocate (objc_mutex_t mutex) |
61fec9ff | 189 | { |
f199d860 JB |
190 | while (NXMutexIsOwned ((NXMutex_t *)mutex->backend)) |
191 | NXUnlock ((NXMutex_t *)mutex->backend); | |
192 | if (NXMutexFree ((NXMutex_t *)mutex->backend) != 0) | |
61fec9ff JB |
193 | return -1; |
194 | mutex->backend = NULL; | |
195 | return 0; | |
196 | } | |
197 | ||
8c27b7d4 | 198 | /* Grab a lock on a mutex. */ |
61fec9ff | 199 | static inline int |
f199d860 | 200 | __gthread_objc_mutex_lock (objc_mutex_t mutex) |
61fec9ff | 201 | { |
f199d860 | 202 | return NXLock ((NXMutex_t *)mutex->backend); |
61fec9ff JB |
203 | } |
204 | ||
8c27b7d4 | 205 | /* Try to grab a lock on a mutex. */ |
61fec9ff | 206 | static inline int |
f199d860 | 207 | __gthread_objc_mutex_trylock (objc_mutex_t mutex) |
61fec9ff | 208 | { |
f199d860 | 209 | if (!NXTryLock ((NXMutex_t *)mutex->backend)) |
61fec9ff JB |
210 | return -1; |
211 | return 0; | |
212 | } | |
213 | ||
214 | /* Unlock the mutex */ | |
215 | static inline int | |
f199d860 | 216 | __gthread_objc_mutex_unlock (objc_mutex_t mutex) |
61fec9ff | 217 | { |
f199d860 | 218 | return NXUnlock ((NXMutex_t *)mutex->backend); |
61fec9ff JB |
219 | } |
220 | ||
221 | /* Backend condition mutex functions */ | |
222 | ||
8c27b7d4 | 223 | /* Allocate a condition. */ |
61fec9ff | 224 | static inline int |
f199d860 | 225 | __gthread_objc_condition_allocate (objc_condition_t condition) |
61fec9ff | 226 | { |
f199d860 | 227 | condition->backend = NXCondAlloc (NULL); |
61fec9ff JB |
228 | if (condition->backend == NULL) |
229 | return -1; | |
230 | ||
231 | return 0; | |
232 | } | |
233 | ||
8c27b7d4 | 234 | /* Deallocate a condition. */ |
61fec9ff | 235 | static inline int |
f199d860 | 236 | __gthread_objc_condition_deallocate (objc_condition_t condition) |
61fec9ff | 237 | { |
f199d860 | 238 | if (NXCondFree ((NXCond_t *)condition->backend) != 0) |
61fec9ff JB |
239 | return -1; |
240 | condition->backend = NULL; | |
241 | return 0; | |
242 | } | |
243 | ||
244 | /* Wait on the condition */ | |
245 | static inline int | |
f199d860 | 246 | __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) |
61fec9ff | 247 | { |
f199d860 | 248 | return NXCondWait ((NXCond_t *)condition->backend, (NXMutex_t *)mutex->backend); |
61fec9ff JB |
249 | } |
250 | ||
8c27b7d4 | 251 | /* Wake up all threads waiting on this condition. */ |
61fec9ff | 252 | static inline int |
f199d860 | 253 | __gthread_objc_condition_broadcast (objc_condition_t condition) |
61fec9ff | 254 | { |
f199d860 | 255 | return NXCondBroadcast ((NXCond_t *)condition->backend); |
61fec9ff JB |
256 | } |
257 | ||
8c27b7d4 | 258 | /* Wake up one thread waiting on this condition. */ |
61fec9ff | 259 | static inline int |
f199d860 | 260 | __gthread_objc_condition_signal (objc_condition_t condition) |
61fec9ff | 261 | { |
f199d860 | 262 | return NXCondSignal ((NXCond_t *)condition->backend); |
61fec9ff JB |
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 | { | |
f199d860 | 286 | if (__compare_and_swap (once, 0, 1)) |
61fec9ff JB |
287 | { |
288 | func(); | |
289 | *once |= 2; | |
290 | } | |
291 | else | |
292 | { | |
f199d860 JB |
293 | while (!(*once & 2)) |
294 | NXThreadYield (); | |
61fec9ff JB |
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 | { | |
f199d860 | 308 | /* Just reset the key value to zero. */ |
61fec9ff JB |
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 | ||
f199d860 | 325 | if (NXKeyGetValue (key, &value) == 0) |
61fec9ff JB |
326 | return value; |
327 | return NULL; | |
328 | } | |
329 | ||
330 | static inline int | |
331 | __gthread_setspecific (__gthread_key_t key, const void *ptr) | |
332 | { | |
f199d860 | 333 | return NXKeySetValue (key, (void *)ptr); |
61fec9ff JB |
334 | } |
335 | ||
336 | static inline void | |
337 | __gthread_mutex_init_function (__gthread_mutex_t *mutex) | |
338 | { | |
f199d860 | 339 | static const NX_LOCK_INFO_ALLOC (info, "GTHREADS", 0); |
61fec9ff | 340 | |
f199d860 | 341 | *mutex = NXMutexAlloc (0, 0, &info); |
61fec9ff JB |
342 | } |
343 | ||
4dabf736 JB |
344 | static inline int |
345 | __gthread_mutex_destroy (__gthread_mutex_t * UNUSED(mutex)) | |
346 | { | |
347 | return 0; | |
348 | } | |
349 | ||
61fec9ff JB |
350 | static inline int |
351 | __gthread_mutex_lock (__gthread_mutex_t *mutex) | |
352 | { | |
f199d860 | 353 | return NXLock (*mutex); |
61fec9ff JB |
354 | } |
355 | ||
356 | static inline int | |
357 | __gthread_mutex_trylock (__gthread_mutex_t *mutex) | |
358 | { | |
f199d860 | 359 | if (NXTryLock (*mutex)) |
61fec9ff JB |
360 | return 0; |
361 | return -1; | |
362 | } | |
363 | ||
364 | static inline int | |
365 | __gthread_mutex_unlock (__gthread_mutex_t *mutex) | |
366 | { | |
f199d860 JB |
367 | return NXUnlock (*mutex); |
368 | } | |
369 | ||
370 | static inline void | |
371 | __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) | |
372 | { | |
373 | static const NX_LOCK_INFO_ALLOC (info, "GTHREADS", 0); | |
374 | ||
375 | *mutex = NXMutexAlloc (NX_MUTEX_RECURSIVE, 0, &info); | |
376 | } | |
377 | ||
378 | static inline int | |
379 | __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) | |
380 | { | |
381 | return NXLock (*mutex); | |
382 | } | |
383 | ||
384 | static inline int | |
385 | __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) | |
386 | { | |
387 | if (NXTryLock (*mutex)) | |
388 | return 0; | |
389 | return -1; | |
390 | } | |
391 | ||
392 | static inline int | |
393 | __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) | |
394 | { | |
395 | return NXUnlock (*mutex); | |
61fec9ff JB |
396 | } |
397 | ||
398 | #endif /* _LIBOBJC */ | |
399 | ||
f199d860 | 400 | #endif /* not GCC_GTHR_NKS_H */ |