* config/h8300/h8300.md (*andorqi3): New.
[official-gcc.git] / gcc / gthr-solaris.h
blob6d7ff2538cd8451fbf7d9e02ce3ee252ecc7e7c6
1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000 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 2, or (at your option) any later
10 version.
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.
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 the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
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. */
29 #ifndef GCC_GTHR_SOLARIS_H
30 #define GCC_GTHR_SOLARIS_H
32 /* Solaris threads as found in Solaris 2.[456].
33 Actually these are Unix International (UI) threads, but I don't
34 know if anyone else implements these. */
36 #define __GTHREADS 1
38 #include <thread.h>
39 #include <errno.h>
41 typedef thread_key_t __gthread_key_t;
42 typedef struct
44 mutex_t mutex;
45 int once;
46 } __gthread_once_t;
47 typedef mutex_t __gthread_mutex_t;
49 #define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
50 #define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
52 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
54 #pragma weak thr_keycreate
55 #pragma weak thr_getspecific
56 #pragma weak thr_setspecific
57 #pragma weak thr_create
59 #pragma weak mutex_lock
60 #pragma weak mutex_trylock
61 #pragma weak mutex_unlock
63 #ifdef _LIBOBJC
64 #pragma weak thr_exit
65 #pragma weak thr_keycreate
66 #pragma weak thr_getprio
67 #pragma weak thr_self
68 #pragma weak thr_setprio
69 #pragma weak thr_yield
71 #pragma weak cond_init
72 #pragma weak cond_destroy
73 #pragma weak cond_wait
74 #pragma weak cond_broadcast
75 #pragma weak cond_signal
77 #pragma weak mutex_init
78 #pragma weak mutex_destroy
79 #endif
81 /* This will not actually work in Solaris 2.5, since libc contains
82 dummy symbols of all thr_* routines. */
84 static inline int
85 __gthread_active_p (void)
87 static void *const __gthread_active_ptr = (void *) &thr_create;
88 return __gthread_active_ptr != 0;
91 #else /* not SUPPORTS_WEAK */
93 static inline int
94 __gthread_active_p (void)
96 return 1;
99 #endif /* SUPPORTS_WEAK */
101 #ifdef _LIBOBJC
103 /* Key structure for maintaining thread specific storage */
104 static thread_key_t _objc_thread_storage;
106 /* Thread local storage for a single thread */
107 static void *thread_local_storage = NULL;
109 /* Backend initialization functions */
111 /* Initialize the threads subsystem. */
112 static inline int
113 __gthread_objc_init_thread_system(void)
115 /* Initialize the thread storage key */
116 if (__gthread_active_p ()
117 && thr_keycreate(&_objc_thread_storage, NULL) == 0)
118 return 0;
120 return -1;
123 /* Close the threads subsystem. */
124 static inline int
125 __gthread_objc_close_thread_system(void)
127 if (__gthread_active_p ())
128 return 0;
129 else
130 return -1;
133 /* Backend thread functions */
135 /* Create a new thread of execution. */
136 static inline objc_thread_t
137 __gthread_objc_thread_detach(void (*func)(void *), void *arg)
139 objc_thread_t thread_id;
140 thread_t new_thread_id = 0;
142 if (!__gthread_active_p ())
143 return NULL;
145 if (thr_create(NULL, 0, (void *)func, arg,
146 THR_DETACHED | THR_NEW_LWP,
147 &new_thread_id) == 0)
148 thread_id = *(objc_thread_t *)&new_thread_id;
149 else
150 thread_id = NULL;
152 return thread_id;
155 /* Set the current thread's priority. */
156 static inline int
157 __gthread_objc_thread_set_priority(int priority)
159 int sys_priority = 0;
161 if (!__gthread_active_p ())
162 return -1;
164 switch (priority)
166 case OBJC_THREAD_INTERACTIVE_PRIORITY:
167 sys_priority = 300;
168 break;
169 default:
170 case OBJC_THREAD_BACKGROUND_PRIORITY:
171 sys_priority = 200;
172 break;
173 case OBJC_THREAD_LOW_PRIORITY:
174 sys_priority = 1000;
175 break;
178 /* Change priority */
179 if (thr_setprio(thr_self(), sys_priority) == 0)
180 return 0;
181 else
182 return -1;
185 /* Return the current thread's priority. */
186 static inline int
187 __gthread_objc_thread_get_priority(void)
189 int sys_priority;
191 if (!__gthread_active_p ())
192 return OBJC_THREAD_INTERACTIVE_PRIORITY;
194 if (thr_getprio(thr_self(), &sys_priority) == 0)
196 if (sys_priority >= 250)
197 return OBJC_THREAD_INTERACTIVE_PRIORITY;
198 else if (sys_priority >= 150)
199 return OBJC_THREAD_BACKGROUND_PRIORITY;
200 return OBJC_THREAD_LOW_PRIORITY;
203 /* Couldn't get priority. */
204 return -1;
207 /* Yield our process time to another thread. */
208 static inline void
209 __gthread_objc_thread_yield(void)
211 if (__gthread_active_p ())
212 thr_yield();
215 /* Terminate the current thread. */
216 static inline int
217 __gthread_objc_thread_exit(void)
219 if (__gthread_active_p ())
220 /* exit the thread */
221 thr_exit(&__objc_thread_exit_status);
223 /* Failed if we reached here */
224 return -1;
227 /* Returns an integer value which uniquely describes a thread. */
228 static inline objc_thread_t
229 __gthread_objc_thread_id(void)
231 if (__gthread_active_p ())
232 return (objc_thread_t)thr_self();
233 else
234 return (objc_thread_t)1;
237 /* Sets the thread's local storage pointer. */
238 static inline int
239 __gthread_objc_thread_set_data(void *value)
241 if (__gthread_active_p ())
243 if (thr_setspecific(_objc_thread_storage, value) == 0)
244 return 0;
245 else
246 return -1;
248 else
250 thread_local_storage = value;
251 return 0;
255 /* Returns the thread's local storage pointer. */
256 static inline void *
257 __gthread_objc_thread_get_data(void)
259 void *value = NULL;
261 if (__gthread_active_p ())
263 if (thr_getspecific(_objc_thread_storage, &value) == 0)
264 return value;
265 else
266 return NULL;
268 else
269 return thread_local_storage;
272 /* Backend mutex functions */
274 /* Allocate a mutex. */
275 static inline int
276 __gthread_objc_mutex_allocate(objc_mutex_t mutex)
278 if (__gthread_active_p ()
279 && mutex_init( (mutex_t *)(&(mutex->backend)), USYNC_THREAD, 0))
280 return -1;
282 return 0;
285 /* Deallocate a mutex. */
286 static inline int
287 __gthread_objc_mutex_deallocate(objc_mutex_t mutex)
289 if (__gthread_active_p ())
290 mutex_destroy((mutex_t *)(&(mutex->backend)));
292 return 0;
295 /* Grab a lock on a mutex. */
296 static inline int
297 __gthread_objc_mutex_lock(objc_mutex_t mutex)
299 if (__gthread_active_p ()
300 && mutex_lock((mutex_t *)(&(mutex->backend))) != 0)
301 return -1;
303 return 0;
306 /* Try to grab a lock on a mutex. */
307 static inline int
308 __gthread_objc_mutex_trylock(objc_mutex_t mutex)
310 if (__gthread_active_p ()
311 && mutex_trylock((mutex_t *)(&(mutex->backend))) != 0)
312 return -1;
314 return 0;
317 /* Unlock the mutex */
318 static inline int
319 __gthread_objc_mutex_unlock(objc_mutex_t mutex)
321 if (__gthread_active_p ()
322 && mutex_unlock((mutex_t *)(&(mutex->backend))) != 0)
323 return -1;
325 return 0;
328 /* Backend condition mutex functions */
330 /* Allocate a condition. */
331 static inline int
332 __gthread_objc_condition_allocate(objc_condition_t condition)
334 if (__gthread_active_p ())
335 return cond_init((cond_t *)(&(condition->backend)), USYNC_THREAD,
336 NULL);
337 else
338 return 0;
341 /* Deallocate a condition. */
342 static inline int
343 __gthread_objc_condition_deallocate(objc_condition_t condition)
345 if (__gthread_active_p ())
346 return cond_destroy((cond_t *)(&(condition->backend)));
347 else
348 return 0;
351 /* Wait on the condition */
352 static inline int
353 __gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
355 if (__gthread_active_p ())
356 return cond_wait((cond_t *)(&(condition->backend)),
357 (mutex_t *)(&(mutex->backend)));
358 else
359 return 0;
362 /* Wake up all threads waiting on this condition. */
363 static inline int
364 __gthread_objc_condition_broadcast(objc_condition_t condition)
366 if (__gthread_active_p ())
367 return cond_broadcast((cond_t *)(&(condition->backend)));
368 else
369 return 0;
372 /* Wake up one thread waiting on this condition. */
373 static inline int
374 __gthread_objc_condition_signal(objc_condition_t condition)
376 if (__gthread_active_p ())
377 return cond_signal((cond_t *)(&(condition->backend)));
378 else
379 return 0;
382 #else /* _LIBOBJC */
384 static inline int
385 __gthread_once (__gthread_once_t *once, void (*func) (void))
387 if (! __gthread_active_p ())
388 return -1;
390 if (once == 0 || func == 0)
391 return EINVAL;
393 if (once->once == 0)
395 int status = mutex_lock (&once->mutex);
396 if (status != 0)
397 return status;
398 if (once->once == 0)
400 (*func) ();
401 once->once ++;
403 mutex_unlock (&once->mutex);
405 return 0;
408 static inline int
409 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
411 /* Solaris 2.5 contains thr_* routines no-op in libc, so test if we actually
412 got a reasonable key value, and if not, fail. */
413 *key = -1;
414 if (thr_keycreate (key, dtor) != 0 || *key == -1)
415 return -1;
416 else
417 return 0;
420 static inline int
421 __gthread_key_dtor (__gthread_key_t key, void *ptr)
423 /* Nothing needed. */
424 return 0;
427 static inline int
428 __gthread_key_delete (__gthread_key_t key)
430 /* Not possible. */
431 return -1;
434 static inline void *
435 __gthread_getspecific (__gthread_key_t key)
437 void *ptr;
438 if (thr_getspecific (key, &ptr) == 0)
439 return ptr;
440 else
441 return 0;
444 static inline int
445 __gthread_setspecific (__gthread_key_t key, const void *ptr)
447 return thr_setspecific (key, (void *) ptr);
450 static inline int
451 __gthread_mutex_lock (__gthread_mutex_t *mutex)
453 if (__gthread_active_p ())
454 return mutex_lock (mutex);
455 else
456 return 0;
459 static inline int
460 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
462 if (__gthread_active_p ())
463 return mutex_trylock (mutex);
464 else
465 return 0;
468 static inline int
469 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
471 if (__gthread_active_p ())
472 return mutex_unlock (mutex);
473 else
474 return 0;
477 #endif /* _LIBOBJC */
479 #endif /* ! GCC_GTHR_SOLARIS_H */