1256106Sdes/* Threads compatibility routines for libgcc2 and libobjc.  */
2256106Sdes/* Compile this one with gcc.  */
3256106Sdes/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
4256106Sdes
5256106SdesThis file is part of GCC.
6256106Sdes
7256106SdesGCC is free software; you can redistribute it and/or modify it under
8256106Sdesthe terms of the GNU General Public License as published by the Free
9256106SdesSoftware Foundation; either version 2, or (at your option) any later
10256106Sdesversion.
11256106Sdes
12256106SdesGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13256106SdesWARRANTY; without even the implied warranty of MERCHANTABILITY or
14256106SdesFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15256106Sdesfor more details.
16256106Sdes
17256106SdesYou should have received a copy of the GNU General Public License
18256106Sdesalong with GCC; see the file COPYING.  If not, write to the Free
19256106SdesSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20256106Sdes02110-1301, USA.  */
21256106Sdes
22256106Sdes/* As a special exception, if you link this library with other files,
23256106Sdes   some of which are compiled with GCC, to produce an executable,
24256106Sdes   this library does not by itself cause the resulting executable
25256106Sdes   to be covered by the GNU General Public License.
26256106Sdes   This exception does not however invalidate any other reasons why
27256106Sdes   the executable file might be covered by the GNU General Public License.  */
28256106Sdes
29256106Sdes#ifndef GCC_GTHR_NKS_H
30256106Sdes#define GCC_GTHR_NKS_H
31256106Sdes
32256106Sdes/* NKS threads specific definitions.
33256106Sdes   Easy, since the interface is mostly one-to-one mapping.  */
34256106Sdes
35256106Sdes#define __GTHREADS 1
36256106Sdes
37256106Sdes#define NKS_NO_INLINE_FUNCS
38256106Sdes#include <nksapi.h>
39256106Sdes#include <string.h>
40256106Sdes
41256106Sdestypedef NXKey_t __gthread_key_t;
42256106Sdestypedef NXMutex_t *__gthread_mutex_t;
43256106Sdestypedef NXMutex_t *__gthread_recursive_mutex_t;
44256106Sdes
45256106Sdes#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
46256106Sdes#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
47256106Sdes
48256106Sdesstatic inline int
49256106Sdes__gthread_active_p (void)
50256106Sdes{
51256106Sdes  return 1;
52256106Sdes}
53256106Sdes
54256106Sdes#ifdef _LIBOBJC
55256106Sdes
56256106Sdes/* This is the config.h file in libobjc/ */
57256106Sdes#include <config.h>
58256106Sdes
59256106Sdes#ifdef HAVE_SCHED_H
60256106Sdes# include <sched.h>
61256106Sdes#endif
62256106Sdes
63256106Sdes/* Key structure for maintaining thread specific storage */
64256106Sdesstatic NXKey_t _objc_thread_storage;
65256106Sdes
66256106Sdes/* Backend initialization functions */
67256106Sdes
68256106Sdes/* Initialize the threads subsystem.  */
69256106Sdesstatic inline int
70256106Sdes__gthread_objc_init_thread_system (void)
71256106Sdes{
72256106Sdes  /* Initialize the thread storage key.  */
73256106Sdes  if (NXKeyCreate (NULL, NULL, &_objc_thread_storage) == 0)
74256106Sdes    return 0;
75256106Sdes  return -1;
76256106Sdes}
77256106Sdes
78256106Sdes/* Close the threads subsystem.  */
79256106Sdesstatic inline int
80256106Sdes__gthread_objc_close_thread_system (void)
81256106Sdes{
82256106Sdes  if (NXKeyDelete (_objc_thread_storage) == 0)
83256106Sdes    return 0;
84256106Sdes  return -1;
85256106Sdes}
86256106Sdes
87256106Sdes/* Backend thread functions */
88256106Sdes
89256106Sdes/* Create a new thread of execution.  */
90256106Sdesstatic inline objc_thread_t
91256106Sdes__gthread_objc_thread_detach (void (*func)(void *), void *arg)
92256106Sdes{
93256106Sdes  objc_thread_t thread_id;
94256106Sdes  NXContext_t context;
95256106Sdes  NXThreadId_t new_thread_handle;
96256106Sdes  int err;
97256106Sdes
98256106Sdes  if ((context = NXContextAlloc (func, arg, NX_PRIO_MED, 0, 0, 0, &err)) == NULL)
99256106Sdes    thread_id = NULL;
100256106Sdes  else if (NXThreadCreate (context, NX_THR_DETACHED, &new_thread_handle) == 0)
101256106Sdes    thread_id = (objc_thread_t) new_thread_handle;
102256106Sdes  else {
103256241Sdes    NXContextFree (context);
104256106Sdes    thread_id = NULL;
105256106Sdes  }
106256106Sdes
107256106Sdes  return thread_id;
108256106Sdes}
109256241Sdes
110256106Sdes/* Set the current thread's priority.  */
111256106Sdesstatic inline int
112256106Sdes__gthread_objc_thread_set_priority (int priority)
113256106Sdes{
114256106Sdes  if (NXThreadSetPriority (NXThreadGetId (), priority) == 0)
115256106Sdes    return 0;
116256106Sdes  return -1;
117256106Sdes}
118256106Sdes
119256106Sdes/* Return the current thread's priority.  */
120256106Sdesstatic inline int
121256106Sdes__gthread_objc_thread_get_priority (void)
122256106Sdes{
123256106Sdes  int priority;
124307403Ssevan
125  if (NXThreadGetPriority (NXThreadGetId (), &priority) == 0)
126    return priority;
127  return -1;
128}
129
130/* Yield our process time to another thread.  */
131static inline void
132__gthread_objc_thread_yield (void)
133{
134  NXThreadYield ();
135}
136
137/* Terminate the current thread.  */
138static 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.  */
149static 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.  */
156static 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.  */
163static 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.  */
176static 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.  */
187static 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.  */
199static 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.  */
206static 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 */
215static 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.  */
224static 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.  */
235static 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 */
245static 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.  */
252static 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.  */
259static 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
279typedef volatile long __gthread_once_t;
280
281#define __GTHREAD_ONCE_INIT 0
282
283static 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
299static inline int
300__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
301{
302  return NXKeyCreate (dtor, NULL, key);
303}
304
305static 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
314static inline int
315__gthread_key_delete (__gthread_key_t key)
316{
317  return NXKeyDelete (key);
318}
319
320static 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
330static inline int
331__gthread_setspecific (__gthread_key_t key, const void *ptr)
332{
333  return NXKeySetValue (key, (void *)ptr);
334}
335
336static 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
344static inline int
345__gthread_mutex_lock (__gthread_mutex_t *mutex)
346{
347  return NXLock (*mutex);
348}
349
350static inline int
351__gthread_mutex_trylock (__gthread_mutex_t *mutex)
352{
353  if (NXTryLock (*mutex))
354    return 0;
355  return -1;
356}
357
358static inline int
359__gthread_mutex_unlock (__gthread_mutex_t *mutex)
360{
361  return NXUnlock (*mutex);
362}
363
364static 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
372static inline int
373__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
374{
375  return NXLock (*mutex);
376}
377
378static 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
386static 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 */
395