gcc/
[official-gcc.git] / gcc / gthr-solaris.h
blob5aed7ad0dfdc81bd1318c3a8d918fbe5fc79b8e5
1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000, 2004, 2005, 2006, 2008, 2009
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #ifndef GCC_GTHR_SOLARIS_H
28 #define GCC_GTHR_SOLARIS_H
30 /* Solaris threads as found in Solaris 2.[456].
31 Actually these are Unix International (UI) threads, but I don't
32 know if anyone else implements these. */
34 #define __GTHREADS 1
36 #include <thread.h>
37 #include <errno.h>
39 #ifdef __cplusplus
40 #define UNUSED(x)
41 #else
42 #define UNUSED(x) x __attribute__((unused))
43 #endif
45 typedef thread_key_t __gthread_key_t;
46 typedef struct {
47 mutex_t mutex;
48 int once;
49 } __gthread_once_t;
50 typedef mutex_t __gthread_mutex_t;
52 typedef struct {
53 long depth;
54 thread_t owner;
55 mutex_t actual;
56 } __gthread_recursive_mutex_t;
58 #define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
59 #define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
60 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
62 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
63 # define __gthrw(name) \
64 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
65 # define __gthrw_(name) __gthrw_ ## name
66 #else
67 # define __gthrw(name)
68 # define __gthrw_(name) name
69 #endif
71 __gthrw(thr_keycreate)
72 __gthrw(thr_getspecific)
73 __gthrw(thr_setspecific)
74 __gthrw(thr_create)
75 __gthrw(thr_self)
77 __gthrw(mutex_init)
78 __gthrw(mutex_destroy)
79 __gthrw(mutex_lock)
80 __gthrw(mutex_trylock)
81 __gthrw(mutex_unlock)
83 #ifdef _LIBOBJC
84 __gthrw(thr_exit)
85 __gthrw(thr_getprio)
86 __gthrw(thr_setprio)
87 __gthrw(thr_yield)
89 __gthrw(cond_init)
90 __gthrw(cond_destroy)
91 __gthrw(cond_wait)
92 __gthrw(cond_broadcast)
93 __gthrw(cond_signal)
95 #endif
97 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
99 /* This will not actually work in Solaris 2.5, since libc contains
100 dummy symbols of all thr_* routines. */
102 static inline int
103 __gthread_active_p (void)
105 static void *const __gthread_active_ptr
106 = __extension__ (void *) &__gthrw_(thr_create);
107 return __gthread_active_ptr != 0;
110 #else /* not SUPPORTS_WEAK */
112 static inline int
113 __gthread_active_p (void)
115 return 1;
118 #endif /* SUPPORTS_WEAK */
120 #ifdef _LIBOBJC
122 /* Key structure for maintaining thread specific storage */
123 static thread_key_t _objc_thread_storage;
125 /* Thread local storage for a single thread */
126 static void *thread_local_storage = NULL;
128 /* Backend initialization functions */
130 /* Initialize the threads subsystem. */
131 static inline int
132 __gthread_objc_init_thread_system (void)
134 /* Initialize the thread storage key. */
135 if (__gthread_active_p ()
136 && __gthrw_(thr_keycreate) (&_objc_thread_storage, NULL) == 0)
137 return 0;
139 return -1;
142 /* Close the threads subsystem. */
143 static inline int
144 __gthread_objc_close_thread_system (void)
146 if (__gthread_active_p ())
147 return 0;
148 else
149 return -1;
152 /* Backend thread functions */
154 /* Create a new thread of execution. */
155 static inline objc_thread_t
156 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
158 objc_thread_t thread_id;
159 thread_t new_thread_id = 0;
161 if (!__gthread_active_p ())
162 return NULL;
164 if (__gthrw_(thr_create) (NULL, 0, (void *) func, arg,
165 THR_DETACHED | THR_NEW_LWP,
166 &new_thread_id) == 0)
167 thread_id = *(objc_thread_t *) &new_thread_id;
168 else
169 thread_id = NULL;
171 return thread_id;
174 /* Set the current thread's priority. */
175 static inline int
176 __gthread_objc_thread_set_priority (int priority)
178 int sys_priority = 0;
180 if (!__gthread_active_p ())
181 return -1;
183 switch (priority)
185 case OBJC_THREAD_INTERACTIVE_PRIORITY:
186 sys_priority = 300;
187 break;
188 default:
189 case OBJC_THREAD_BACKGROUND_PRIORITY:
190 sys_priority = 200;
191 break;
192 case OBJC_THREAD_LOW_PRIORITY:
193 sys_priority = 1000;
194 break;
197 /* Change priority */
198 if (__gthrw_(thr_setprio) (__gthrw_(thr_self) (), sys_priority) == 0)
199 return 0;
200 else
201 return -1;
204 /* Return the current thread's priority. */
205 static inline int
206 __gthread_objc_thread_get_priority (void)
208 int sys_priority;
210 if (!__gthread_active_p ())
211 return OBJC_THREAD_INTERACTIVE_PRIORITY;
213 if (__gthrw_(thr_getprio) (__gthrw_(thr_self) (), &sys_priority) == 0)
215 if (sys_priority >= 250)
216 return OBJC_THREAD_INTERACTIVE_PRIORITY;
217 else if (sys_priority >= 150)
218 return OBJC_THREAD_BACKGROUND_PRIORITY;
219 return OBJC_THREAD_LOW_PRIORITY;
222 /* Couldn't get priority. */
223 return -1;
226 /* Yield our process time to another thread. */
227 static inline void
228 __gthread_objc_thread_yield (void)
230 if (__gthread_active_p ())
231 __gthrw_(thr_yield) ();
234 /* Terminate the current thread. */
235 static inline int
236 __gthread_objc_thread_exit (void)
238 if (__gthread_active_p ())
239 /* exit the thread */
240 __gthrw_(thr_exit) (&__objc_thread_exit_status);
242 /* Failed if we reached here */
243 return -1;
246 /* Returns an integer value which uniquely describes a thread. */
247 static inline objc_thread_t
248 __gthread_objc_thread_id (void)
250 if (__gthread_active_p ())
251 return (objc_thread_t) __gthrw_(thr_self) ();
252 else
253 return (objc_thread_t) 1;
256 /* Sets the thread's local storage pointer. */
257 static inline int
258 __gthread_objc_thread_set_data (void *value)
260 if (__gthread_active_p ())
262 if (__gthrw_(thr_setspecific) (_objc_thread_storage, value) == 0)
263 return 0;
264 else
265 return -1;
267 else
269 thread_local_storage = value;
270 return 0;
274 /* Returns the thread's local storage pointer. */
275 static inline void *
276 __gthread_objc_thread_get_data (void)
278 void *value = NULL;
280 if (__gthread_active_p ())
282 if (__gthrw_(thr_getspecific) (_objc_thread_storage, &value) == 0)
283 return value;
284 else
285 return NULL;
287 else
288 return thread_local_storage;
291 /* Backend mutex functions */
293 /* Allocate a mutex. */
294 static inline int
295 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
297 if (__gthread_active_p ()
298 && __gthrw_(mutex_init) ((mutex_t *) (&(mutex->backend)), USYNC_THREAD, 0))
299 return -1;
301 return 0;
304 /* Deallocate a mutex. */
305 static inline int
306 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
308 if (__gthread_active_p ())
309 __gthrw_(mutex_destroy) ((mutex_t *) (&(mutex->backend)));
311 return 0;
314 /* Grab a lock on a mutex. */
315 static inline int
316 __gthread_objc_mutex_lock (objc_mutex_t mutex)
318 if (__gthread_active_p ()
319 && __gthrw_(mutex_lock) ((mutex_t *) (&(mutex->backend))) != 0)
320 return -1;
322 return 0;
325 /* Try to grab a lock on a mutex. */
326 static inline int
327 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
329 if (__gthread_active_p ()
330 && __gthrw_(mutex_trylock) ((mutex_t *) (&(mutex->backend))) != 0)
331 return -1;
333 return 0;
336 /* Unlock the mutex */
337 static inline int
338 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
340 if (__gthread_active_p ()
341 && __gthrw_(mutex_unlock) ((mutex_t *) (&(mutex->backend))) != 0)
342 return -1;
344 return 0;
347 /* Backend condition mutex functions */
349 /* Allocate a condition. */
350 static inline int
351 __gthread_objc_condition_allocate (objc_condition_t condition)
353 if (__gthread_active_p ())
354 return __gthrw_(cond_init) ((cond_t *) (&(condition->backend)), USYNC_THREAD,
355 NULL);
356 else
357 return 0;
360 /* Deallocate a condition. */
361 static inline int
362 __gthread_objc_condition_deallocate (objc_condition_t condition)
364 if (__gthread_active_p ())
365 return __gthrw_(cond_destroy) ((cond_t *) (&(condition->backend)));
366 else
367 return 0;
370 /* Wait on the condition */
371 static inline int
372 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
374 if (__gthread_active_p ())
375 return __gthrw_(cond_wait) ((cond_t *) (&(condition->backend)),
376 (mutex_t *) (&(mutex->backend)));
377 else
378 return 0;
381 /* Wake up all threads waiting on this condition. */
382 static inline int
383 __gthread_objc_condition_broadcast (objc_condition_t condition)
385 if (__gthread_active_p ())
386 return __gthrw_(cond_broadcast) ((cond_t *) (&(condition->backend)));
387 else
388 return 0;
391 /* Wake up one thread waiting on this condition. */
392 static inline int
393 __gthread_objc_condition_signal (objc_condition_t condition)
395 if (__gthread_active_p ())
396 return __gthrw_(cond_signal) ((cond_t *) (&(condition->backend)));
397 else
398 return 0;
401 #else /* _LIBOBJC */
403 static inline int
404 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
406 if (! __gthread_active_p ())
407 return -1;
409 if (__once == 0 || __func == 0)
410 return EINVAL;
412 if (__once->once == 0)
414 int __status = __gthrw_(mutex_lock) (&__once->mutex);
415 if (__status != 0)
416 return __status;
417 if (__once->once == 0)
419 (*__func) ();
420 __once->once++;
422 __gthrw_(mutex_unlock) (&__once->mutex);
424 return 0;
427 static inline int
428 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
430 /* Solaris 2.5 contains thr_* routines no-op in libc, so test if we actually
431 got a reasonable key value, and if not, fail. */
432 *__key = (__gthread_key_t)-1;
433 if (__gthrw_(thr_keycreate) (__key, __dtor) != 0
434 || *__key == (__gthread_key_t)-1)
435 return -1;
436 else
437 return 0;
440 static inline int
441 __gthread_key_delete (__gthread_key_t UNUSED (__key))
443 /* Not possible. */
444 return -1;
447 static inline void *
448 __gthread_getspecific (__gthread_key_t __key)
450 void *__ptr;
451 if (__gthrw_(thr_getspecific) (__key, &__ptr) == 0)
452 return __ptr;
453 else
454 return 0;
457 static inline int
458 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
460 return __gthrw_(thr_setspecific) (__key, (void *) __ptr);
463 static inline int
464 __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
466 if (__gthread_active_p ())
467 return __gthrw_(mutex_destroy) (__mutex);
468 else
469 return 0;
472 static inline int
473 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
475 if (__gthread_active_p ())
476 return __gthrw_(mutex_lock) (__mutex);
477 else
478 return 0;
481 static inline int
482 __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
484 if (__gthread_active_p ())
485 return __gthrw_(mutex_trylock) (__mutex);
486 else
487 return 0;
490 static inline int
491 __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
493 if (__gthread_active_p ())
494 return __gthrw_(mutex_unlock) (__mutex);
495 else
496 return 0;
499 static inline int
500 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
502 __mutex->depth = 0;
503 __mutex->owner = (thread_t) 0;
504 return __gthrw_(mutex_init) (&__mutex->actual, USYNC_THREAD, 0);
507 static inline int
508 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
510 if (__gthread_active_p ())
512 thread_t __me = __gthrw_(thr_self) ();
514 if (__mutex->owner != __me)
516 __gthrw_(mutex_lock) (&__mutex->actual);
517 __mutex->owner = __me;
520 __mutex->depth++;
522 return 0;
525 static inline int
526 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
528 if (__gthread_active_p ())
530 thread_t __me = __gthrw_(thr_self) ();
532 if (__mutex->owner != __me)
534 if (__gthrw_(mutex_trylock) (&__mutex->actual))
535 return 1;
536 __mutex->owner = __me;
539 __mutex->depth++;
541 return 0;
544 static inline int
545 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
547 if (__gthread_active_p ())
549 if (--__mutex->depth == 0)
551 __mutex->owner = (thread_t) 0;
552 __gthrw_(mutex_unlock) (&__mutex->actual);
555 return 0;
558 #endif /* _LIBOBJC */
560 #undef UNUSED
562 #endif /* ! GCC_GTHR_SOLARIS_H */