2009-02-19 Richard Guenther <rguenther@suse.de>
[official-gcc.git] / gcc / gthr-solaris.h
blob083a43346a4646d567bd3db9639623690a46f4ff
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 2, 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 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA. */
23 /* As a special exception, if you link this library with other files,
24 some of which are compiled with GCC, to produce an executable,
25 this library does not by itself cause the resulting executable
26 to be covered by the GNU General Public License.
27 This exception does not however invalidate any other reasons why
28 the executable file might be covered by the GNU General Public License. */
30 #ifndef GCC_GTHR_SOLARIS_H
31 #define GCC_GTHR_SOLARIS_H
33 /* Solaris threads as found in Solaris 2.[456].
34 Actually these are Unix International (UI) threads, but I don't
35 know if anyone else implements these. */
37 #define __GTHREADS 1
39 #include <thread.h>
40 #include <errno.h>
42 #ifdef __cplusplus
43 #define UNUSED(x)
44 #else
45 #define UNUSED(x) x __attribute__((unused))
46 #endif
48 typedef thread_key_t __gthread_key_t;
49 typedef struct {
50 mutex_t mutex;
51 int once;
52 } __gthread_once_t;
53 typedef mutex_t __gthread_mutex_t;
55 typedef struct {
56 long depth;
57 thread_t owner;
58 mutex_t actual;
59 } __gthread_recursive_mutex_t;
61 #define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
62 #define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
63 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
65 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
66 # define __gthrw(name) \
67 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
68 # define __gthrw_(name) __gthrw_ ## name
69 #else
70 # define __gthrw(name)
71 # define __gthrw_(name) name
72 #endif
74 __gthrw(thr_keycreate)
75 __gthrw(thr_getspecific)
76 __gthrw(thr_setspecific)
77 __gthrw(thr_create)
78 __gthrw(thr_self)
80 __gthrw(mutex_init)
81 __gthrw(mutex_destroy)
82 __gthrw(mutex_lock)
83 __gthrw(mutex_trylock)
84 __gthrw(mutex_unlock)
86 #ifdef _LIBOBJC
87 __gthrw(thr_exit)
88 __gthrw(thr_getprio)
89 __gthrw(thr_setprio)
90 __gthrw(thr_yield)
92 __gthrw(cond_init)
93 __gthrw(cond_destroy)
94 __gthrw(cond_wait)
95 __gthrw(cond_broadcast)
96 __gthrw(cond_signal)
98 #endif
100 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
102 /* This will not actually work in Solaris 2.5, since libc contains
103 dummy symbols of all thr_* routines. */
105 static inline int
106 __gthread_active_p (void)
108 static void *const __gthread_active_ptr = (void *) &__gthrw_(thr_create);
109 return __gthread_active_ptr != 0;
112 #else /* not SUPPORTS_WEAK */
114 static inline int
115 __gthread_active_p (void)
117 return 1;
120 #endif /* SUPPORTS_WEAK */
122 #ifdef _LIBOBJC
124 /* Key structure for maintaining thread specific storage */
125 static thread_key_t _objc_thread_storage;
127 /* Thread local storage for a single thread */
128 static void *thread_local_storage = NULL;
130 /* Backend initialization functions */
132 /* Initialize the threads subsystem. */
133 static inline int
134 __gthread_objc_init_thread_system (void)
136 /* Initialize the thread storage key. */
137 if (__gthread_active_p ()
138 && __gthrw_(thr_keycreate) (&_objc_thread_storage, NULL) == 0)
139 return 0;
141 return -1;
144 /* Close the threads subsystem. */
145 static inline int
146 __gthread_objc_close_thread_system (void)
148 if (__gthread_active_p ())
149 return 0;
150 else
151 return -1;
154 /* Backend thread functions */
156 /* Create a new thread of execution. */
157 static inline objc_thread_t
158 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
160 objc_thread_t thread_id;
161 thread_t new_thread_id = 0;
163 if (!__gthread_active_p ())
164 return NULL;
166 if (__gthrw_(thr_create) (NULL, 0, (void *) func, arg,
167 THR_DETACHED | THR_NEW_LWP,
168 &new_thread_id) == 0)
169 thread_id = *(objc_thread_t *) &new_thread_id;
170 else
171 thread_id = NULL;
173 return thread_id;
176 /* Set the current thread's priority. */
177 static inline int
178 __gthread_objc_thread_set_priority (int priority)
180 int sys_priority = 0;
182 if (!__gthread_active_p ())
183 return -1;
185 switch (priority)
187 case OBJC_THREAD_INTERACTIVE_PRIORITY:
188 sys_priority = 300;
189 break;
190 default:
191 case OBJC_THREAD_BACKGROUND_PRIORITY:
192 sys_priority = 200;
193 break;
194 case OBJC_THREAD_LOW_PRIORITY:
195 sys_priority = 1000;
196 break;
199 /* Change priority */
200 if (__gthrw_(thr_setprio) (__gthrw_(thr_self) (), sys_priority) == 0)
201 return 0;
202 else
203 return -1;
206 /* Return the current thread's priority. */
207 static inline int
208 __gthread_objc_thread_get_priority (void)
210 int sys_priority;
212 if (!__gthread_active_p ())
213 return OBJC_THREAD_INTERACTIVE_PRIORITY;
215 if (__gthrw_(thr_getprio) (__gthrw_(thr_self) (), &sys_priority) == 0)
217 if (sys_priority >= 250)
218 return OBJC_THREAD_INTERACTIVE_PRIORITY;
219 else if (sys_priority >= 150)
220 return OBJC_THREAD_BACKGROUND_PRIORITY;
221 return OBJC_THREAD_LOW_PRIORITY;
224 /* Couldn't get priority. */
225 return -1;
228 /* Yield our process time to another thread. */
229 static inline void
230 __gthread_objc_thread_yield (void)
232 if (__gthread_active_p ())
233 __gthrw_(thr_yield) ();
236 /* Terminate the current thread. */
237 static inline int
238 __gthread_objc_thread_exit (void)
240 if (__gthread_active_p ())
241 /* exit the thread */
242 __gthrw_(thr_exit) (&__objc_thread_exit_status);
244 /* Failed if we reached here */
245 return -1;
248 /* Returns an integer value which uniquely describes a thread. */
249 static inline objc_thread_t
250 __gthread_objc_thread_id (void)
252 if (__gthread_active_p ())
253 return (objc_thread_t) __gthrw_(thr_self) ();
254 else
255 return (objc_thread_t) 1;
258 /* Sets the thread's local storage pointer. */
259 static inline int
260 __gthread_objc_thread_set_data (void *value)
262 if (__gthread_active_p ())
264 if (__gthrw_(thr_setspecific) (_objc_thread_storage, value) == 0)
265 return 0;
266 else
267 return -1;
269 else
271 thread_local_storage = value;
272 return 0;
276 /* Returns the thread's local storage pointer. */
277 static inline void *
278 __gthread_objc_thread_get_data (void)
280 void *value = NULL;
282 if (__gthread_active_p ())
284 if (__gthrw_(thr_getspecific) (_objc_thread_storage, &value) == 0)
285 return value;
286 else
287 return NULL;
289 else
290 return thread_local_storage;
293 /* Backend mutex functions */
295 /* Allocate a mutex. */
296 static inline int
297 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
299 if (__gthread_active_p ()
300 && __gthrw_(mutex_init) ((mutex_t *) (&(mutex->backend)), USYNC_THREAD, 0))
301 return -1;
303 return 0;
306 /* Deallocate a mutex. */
307 static inline int
308 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
310 if (__gthread_active_p ())
311 __gthrw_(mutex_destroy) ((mutex_t *) (&(mutex->backend)));
313 return 0;
316 /* Grab a lock on a mutex. */
317 static inline int
318 __gthread_objc_mutex_lock (objc_mutex_t mutex)
320 if (__gthread_active_p ()
321 && __gthrw_(mutex_lock) ((mutex_t *) (&(mutex->backend))) != 0)
322 return -1;
324 return 0;
327 /* Try to grab a lock on a mutex. */
328 static inline int
329 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
331 if (__gthread_active_p ()
332 && __gthrw_(mutex_trylock) ((mutex_t *) (&(mutex->backend))) != 0)
333 return -1;
335 return 0;
338 /* Unlock the mutex */
339 static inline int
340 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
342 if (__gthread_active_p ()
343 && __gthrw_(mutex_unlock) ((mutex_t *) (&(mutex->backend))) != 0)
344 return -1;
346 return 0;
349 /* Backend condition mutex functions */
351 /* Allocate a condition. */
352 static inline int
353 __gthread_objc_condition_allocate (objc_condition_t condition)
355 if (__gthread_active_p ())
356 return __gthrw_(cond_init) ((cond_t *) (&(condition->backend)), USYNC_THREAD,
357 NULL);
358 else
359 return 0;
362 /* Deallocate a condition. */
363 static inline int
364 __gthread_objc_condition_deallocate (objc_condition_t condition)
366 if (__gthread_active_p ())
367 return __gthrw_(cond_destroy) ((cond_t *) (&(condition->backend)));
368 else
369 return 0;
372 /* Wait on the condition */
373 static inline int
374 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
376 if (__gthread_active_p ())
377 return __gthrw_(cond_wait) ((cond_t *) (&(condition->backend)),
378 (mutex_t *) (&(mutex->backend)));
379 else
380 return 0;
383 /* Wake up all threads waiting on this condition. */
384 static inline int
385 __gthread_objc_condition_broadcast (objc_condition_t condition)
387 if (__gthread_active_p ())
388 return __gthrw_(cond_broadcast) ((cond_t *) (&(condition->backend)));
389 else
390 return 0;
393 /* Wake up one thread waiting on this condition. */
394 static inline int
395 __gthread_objc_condition_signal (objc_condition_t condition)
397 if (__gthread_active_p ())
398 return __gthrw_(cond_signal) ((cond_t *) (&(condition->backend)));
399 else
400 return 0;
403 #else /* _LIBOBJC */
405 static inline int
406 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
408 if (! __gthread_active_p ())
409 return -1;
411 if (__once == 0 || __func == 0)
412 return EINVAL;
414 if (__once->once == 0)
416 int __status = __gthrw_(mutex_lock) (&__once->mutex);
417 if (__status != 0)
418 return __status;
419 if (__once->once == 0)
421 (*__func) ();
422 __once->once++;
424 __gthrw_(mutex_unlock) (&__once->mutex);
426 return 0;
429 static inline int
430 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
432 /* Solaris 2.5 contains thr_* routines no-op in libc, so test if we actually
433 got a reasonable key value, and if not, fail. */
434 *__key = (__gthread_key_t)-1;
435 if (__gthrw_(thr_keycreate) (__key, __dtor) != 0
436 || *__key == (__gthread_key_t)-1)
437 return -1;
438 else
439 return 0;
442 static inline int
443 __gthread_key_delete (__gthread_key_t UNUSED (__key))
445 /* Not possible. */
446 return -1;
449 static inline void *
450 __gthread_getspecific (__gthread_key_t __key)
452 void *__ptr;
453 if (__gthrw_(thr_getspecific) (__key, &__ptr) == 0)
454 return __ptr;
455 else
456 return 0;
459 static inline int
460 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
462 return __gthrw_(thr_setspecific) (__key, (void *) __ptr);
465 static inline int
466 __gthread_mutex_destroy (__gthread_mutex_t * UNUSED(__mutex))
468 if (__gthread_active_p ())
469 return __gthrw_(mutex_destroy) (__mutex);
470 else
471 return 0;
474 static inline int
475 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
477 if (__gthread_active_p ())
478 return __gthrw_(mutex_lock) (__mutex);
479 else
480 return 0;
483 static inline int
484 __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
486 if (__gthread_active_p ())
487 return __gthrw_(mutex_trylock) (__mutex);
488 else
489 return 0;
492 static inline int
493 __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
495 if (__gthread_active_p ())
496 return __gthrw_(mutex_unlock) (__mutex);
497 else
498 return 0;
501 static inline int
502 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
504 __mutex->depth = 0;
505 __mutex->owner = (thread_t) 0;
506 return __gthrw_(mutex_init) (&__mutex->actual, USYNC_THREAD, 0);
509 static inline int
510 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
512 if (__gthread_active_p ())
514 thread_t __me = __gthrw_(thr_self) ();
516 if (__mutex->owner != __me)
518 __gthrw_(mutex_lock) (&__mutex->actual);
519 __mutex->owner = __me;
522 __mutex->depth++;
524 return 0;
527 static inline int
528 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
530 if (__gthread_active_p ())
532 thread_t __me = __gthrw_(thr_self) ();
534 if (__mutex->owner != __me)
536 if (__gthrw_(mutex_trylock) (&__mutex->actual))
537 return 1;
538 __mutex->owner = __me;
541 __mutex->depth++;
543 return 0;
546 static inline int
547 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
549 if (__gthread_active_p ())
551 if (--__mutex->depth == 0)
553 __mutex->owner = (thread_t) 0;
554 __gthrw_(mutex_unlock) (&__mutex->actual);
557 return 0;
560 #endif /* _LIBOBJC */
562 #undef UNUSED
564 #endif /* ! GCC_GTHR_SOLARIS_H */