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
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
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. */
34 #define NKS_NO_INLINE_FUNCS
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
46 __gthread_active_p (void)
53 /* This is the config.h file in libobjc/ */
60 /* Key structure for maintaining thread specific storage */
61 static NXKey_t _objc_thread_storage
;
63 /* Backend initialization functions */
65 /* Initialize the threads subsystem. */
67 __gthread_objc_init_thread_system (void)
69 /* Initialize the thread storage key. */
70 if (NXKeyCreate (NULL
, NULL
, &_objc_thread_storage
) == 0)
75 /* Close the threads subsystem. */
77 __gthread_objc_close_thread_system (void)
79 if (NXKeyDelete (_objc_thread_storage
) == 0)
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
;
92 NXThreadId_t new_thread_handle
;
95 if ((context
= NXContextAlloc (func
, arg
, NX_PRIO_MED
, 0, 0, 0, &err
)) == NULL
)
97 else if (NXThreadCreate (context
, NX_THR_DETACHED
, &new_thread_handle
) == 0)
98 thread_id
= (objc_thread_t
) new_thread_handle
;
100 NXContextFree (context
);
107 /* Set the current thread's priority. */
109 __gthread_objc_thread_set_priority (int priority
)
111 if (NXThreadSetPriority (NXThreadGetId (), priority
) == 0)
116 /* Return the current thread's priority. */
118 __gthread_objc_thread_get_priority (void)
122 if (NXThreadGetPriority (NXThreadGetId (), &priority
) == 0)
127 /* Yield our process time to another thread. */
129 __gthread_objc_thread_yield (void)
134 /* Terminate the current thread. */
136 __gthread_objc_thread_exit (void)
138 /* exit the thread */
139 NXThreadExit (&__objc_thread_exit_status
);
141 /* Failed if we reached here */
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. */
154 __gthread_objc_thread_set_data (void *value
)
156 return NXKeySetValue (_objc_thread_storage
, value
);
159 /* Returns the thread's local storage pointer. */
161 __gthread_objc_thread_get_data (void)
165 if (NXKeyGetValue (_objc_thread_storage
, &value
) == 0)
170 /* Backend mutex functions */
172 /* Allocate a mutex. */
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
)
183 /* Deallocate a mutex. */
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)
191 mutex
->backend
= NULL
;
195 /* Grab a lock on a mutex. */
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. */
204 __gthread_objc_mutex_trylock (objc_mutex_t mutex
)
206 if (!NXTryLock ((NXMutex_t
*)mutex
->backend
))
211 /* Unlock the mutex */
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. */
222 __gthread_objc_condition_allocate (objc_condition_t condition
)
224 condition
->backend
= NXCondAlloc (NULL
);
225 if (condition
->backend
== NULL
)
231 /* Deallocate a condition. */
233 __gthread_objc_condition_deallocate (objc_condition_t condition
)
235 if (NXCondFree ((NXCond_t
*)condition
->backend
) != 0)
237 condition
->backend
= NULL
;
241 /* Wait on the condition */
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. */
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. */
257 __gthread_objc_condition_signal (objc_condition_t condition
)
259 return NXCondSignal ((NXCond_t
*)condition
->backend
);
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>
276 typedef volatile long __gthread_once_t
;
278 #define __GTHREAD_ONCE_INIT 0
281 __gthread_once (__gthread_once_t
*__once
, void (*__func
) (void))
283 if (__compare_and_swap (__once
, 0, 1))
290 while (!(*__once
& 2))
297 __gthread_key_create (__gthread_key_t
*__key
, void (*__dtor
) (void *))
299 return NXKeyCreate (__dtor
, NULL
, __key
);
303 __gthread_key_dtor (__gthread_key_t __key
, void *__ptr
)
305 /* Just reset the key value to zero. */
307 return NXKeySetValue (__key
, NULL
);
312 __gthread_key_delete (__gthread_key_t __key
)
314 return NXKeyDelete (__key
);
318 __gthread_getspecific (__gthread_key_t __key
)
322 if (NXKeyGetValue (__key
, &__value
) == 0)
328 __gthread_setspecific (__gthread_key_t __key
, const void *__ptr
)
330 return NXKeySetValue (__key
, (void *)__ptr
);
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
);
342 __gthread_mutex_destroy (__gthread_mutex_t
* UNUSED(__mutex
))
348 __gthread_mutex_lock (__gthread_mutex_t
*__mutex
)
350 return NXLock (*__mutex
);
354 __gthread_mutex_trylock (__gthread_mutex_t
*__mutex
)
356 if (NXTryLock (*__mutex
))
362 __gthread_mutex_unlock (__gthread_mutex_t
*__mutex
)
364 return NXUnlock (*__mutex
);
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
);
376 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t
*__mutex
)
378 return NXLock (*__mutex
);
382 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t
*__mutex
)
384 if (NXTryLock (*__mutex
))
390 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t
*__mutex
)
392 return NXUnlock (*__mutex
);
395 #endif /* _LIBOBJC */
397 #endif /* not GCC_GTHR_NKS_H */