Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / gthr-solaris.h
blobca13da26511e99f457a541dd01fc146e1a40383f
1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000, 2004 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 {
43 mutex_t mutex;
44 int once;
45 } __gthread_once_t;
46 typedef mutex_t __gthread_mutex_t;
48 typedef struct {
49 long depth;
50 thread_t owner;
51 mutex_t actual;
52 } __gthread_recursive_mutex_t;
54 #define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
55 #define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
56 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
58 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
60 #pragma weak thr_keycreate
61 #pragma weak thr_getspecific
62 #pragma weak thr_setspecific
63 #pragma weak thr_create
65 #pragma weak mutex_lock
66 #pragma weak mutex_trylock
67 #pragma weak mutex_unlock
69 #ifdef _LIBOBJC
70 #pragma weak thr_exit
71 #pragma weak thr_keycreate
72 #pragma weak thr_getprio
73 #pragma weak thr_self
74 #pragma weak thr_setprio
75 #pragma weak thr_yield
77 #pragma weak cond_init
78 #pragma weak cond_destroy
79 #pragma weak cond_wait
80 #pragma weak cond_broadcast
81 #pragma weak cond_signal
83 #pragma weak mutex_init
84 #pragma weak mutex_destroy
85 #endif
87 /* This will not actually work in Solaris 2.5, since libc contains
88 dummy symbols of all thr_* routines. */
90 static inline int
91 __gthread_active_p (void)
93 static void *const __gthread_active_ptr = (void *) &thr_create;
94 return __gthread_active_ptr != 0;
97 #else /* not SUPPORTS_WEAK */
99 static inline int
100 __gthread_active_p (void)
102 return 1;
105 #endif /* SUPPORTS_WEAK */
107 #ifdef _LIBOBJC
109 /* Key structure for maintaining thread specific storage */
110 static thread_key_t _objc_thread_storage;
112 /* Thread local storage for a single thread */
113 static void *thread_local_storage = NULL;
115 /* Backend initialization functions */
117 /* Initialize the threads subsystem. */
118 static inline int
119 __gthread_objc_init_thread_system (void)
121 /* Initialize the thread storage key. */
122 if (__gthread_active_p ()
123 && thr_keycreate (&_objc_thread_storage, NULL) == 0)
124 return 0;
126 return -1;
129 /* Close the threads subsystem. */
130 static inline int
131 __gthread_objc_close_thread_system (void)
133 if (__gthread_active_p ())
134 return 0;
135 else
136 return -1;
139 /* Backend thread functions */
141 /* Create a new thread of execution. */
142 static inline objc_thread_t
143 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
145 objc_thread_t thread_id;
146 thread_t new_thread_id = 0;
148 if (!__gthread_active_p ())
149 return NULL;
151 if (thr_create (NULL, 0, (void *) func, arg,
152 THR_DETACHED | THR_NEW_LWP,
153 &new_thread_id) == 0)
154 thread_id = *(objc_thread_t *) &new_thread_id;
155 else
156 thread_id = NULL;
158 return thread_id;
161 /* Set the current thread's priority. */
162 static inline int
163 __gthread_objc_thread_set_priority (int priority)
165 int sys_priority = 0;
167 if (!__gthread_active_p ())
168 return -1;
170 switch (priority)
172 case OBJC_THREAD_INTERACTIVE_PRIORITY:
173 sys_priority = 300;
174 break;
175 default:
176 case OBJC_THREAD_BACKGROUND_PRIORITY:
177 sys_priority = 200;
178 break;
179 case OBJC_THREAD_LOW_PRIORITY:
180 sys_priority = 1000;
181 break;
184 /* Change priority */
185 if (thr_setprio (thr_self (), sys_priority) == 0)
186 return 0;
187 else
188 return -1;
191 /* Return the current thread's priority. */
192 static inline int
193 __gthread_objc_thread_get_priority (void)
195 int sys_priority;
197 if (!__gthread_active_p ())
198 return OBJC_THREAD_INTERACTIVE_PRIORITY;
200 if (thr_getprio (thr_self (), &sys_priority) == 0)
202 if (sys_priority >= 250)
203 return OBJC_THREAD_INTERACTIVE_PRIORITY;
204 else if (sys_priority >= 150)
205 return OBJC_THREAD_BACKGROUND_PRIORITY;
206 return OBJC_THREAD_LOW_PRIORITY;
209 /* Couldn't get priority. */
210 return -1;
213 /* Yield our process time to another thread. */
214 static inline void
215 __gthread_objc_thread_yield (void)
217 if (__gthread_active_p ())
218 thr_yield ();
221 /* Terminate the current thread. */
222 static inline int
223 __gthread_objc_thread_exit (void)
225 if (__gthread_active_p ())
226 /* exit the thread */
227 thr_exit (&__objc_thread_exit_status);
229 /* Failed if we reached here */
230 return -1;
233 /* Returns an integer value which uniquely describes a thread. */
234 static inline objc_thread_t
235 __gthread_objc_thread_id (void)
237 if (__gthread_active_p ())
238 return (objc_thread_t) thr_self ();
239 else
240 return (objc_thread_t) 1;
243 /* Sets the thread's local storage pointer. */
244 static inline int
245 __gthread_objc_thread_set_data (void *value)
247 if (__gthread_active_p ())
249 if (thr_setspecific (_objc_thread_storage, value) == 0)
250 return 0;
251 else
252 return -1;
254 else
256 thread_local_storage = value;
257 return 0;
261 /* Returns the thread's local storage pointer. */
262 static inline void *
263 __gthread_objc_thread_get_data (void)
265 void *value = NULL;
267 if (__gthread_active_p ())
269 if (thr_getspecific (_objc_thread_storage, &value) == 0)
270 return value;
271 else
272 return NULL;
274 else
275 return thread_local_storage;
278 /* Backend mutex functions */
280 /* Allocate a mutex. */
281 static inline int
282 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
284 if (__gthread_active_p ()
285 && mutex_init ((mutex_t *) (&(mutex->backend)), USYNC_THREAD, 0))
286 return -1;
288 return 0;
291 /* Deallocate a mutex. */
292 static inline int
293 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
295 if (__gthread_active_p ())
296 mutex_destroy ((mutex_t *) (&(mutex->backend)));
298 return 0;
301 /* Grab a lock on a mutex. */
302 static inline int
303 __gthread_objc_mutex_lock (objc_mutex_t mutex)
305 if (__gthread_active_p ()
306 && mutex_lock ((mutex_t *) (&(mutex->backend))) != 0)
307 return -1;
309 return 0;
312 /* Try to grab a lock on a mutex. */
313 static inline int
314 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
316 if (__gthread_active_p ()
317 && mutex_trylock ((mutex_t *) (&(mutex->backend))) != 0)
318 return -1;
320 return 0;
323 /* Unlock the mutex */
324 static inline int
325 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
327 if (__gthread_active_p ()
328 && mutex_unlock ((mutex_t *) (&(mutex->backend))) != 0)
329 return -1;
331 return 0;
334 /* Backend condition mutex functions */
336 /* Allocate a condition. */
337 static inline int
338 __gthread_objc_condition_allocate (objc_condition_t condition)
340 if (__gthread_active_p ())
341 return cond_init ((cond_t *) (&(condition->backend)), USYNC_THREAD,
342 NULL);
343 else
344 return 0;
347 /* Deallocate a condition. */
348 static inline int
349 __gthread_objc_condition_deallocate (objc_condition_t condition)
351 if (__gthread_active_p ())
352 return cond_destroy ((cond_t *) (&(condition->backend)));
353 else
354 return 0;
357 /* Wait on the condition */
358 static inline int
359 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
361 if (__gthread_active_p ())
362 return cond_wait ((cond_t *) (&(condition->backend)),
363 (mutex_t *) (&(mutex->backend)));
364 else
365 return 0;
368 /* Wake up all threads waiting on this condition. */
369 static inline int
370 __gthread_objc_condition_broadcast (objc_condition_t condition)
372 if (__gthread_active_p ())
373 return cond_broadcast ((cond_t *) (&(condition->backend)));
374 else
375 return 0;
378 /* Wake up one thread waiting on this condition. */
379 static inline int
380 __gthread_objc_condition_signal (objc_condition_t condition)
382 if (__gthread_active_p ())
383 return cond_signal ((cond_t *) (&(condition->backend)));
384 else
385 return 0;
388 #else /* _LIBOBJC */
390 static inline int
391 __gthread_once (__gthread_once_t *once, void (*func) (void))
393 if (! __gthread_active_p ())
394 return -1;
396 if (once == 0 || func == 0)
397 return EINVAL;
399 if (once->once == 0)
401 int status = mutex_lock (&once->mutex);
402 if (status != 0)
403 return status;
404 if (once->once == 0)
406 (*func) ();
407 once->once++;
409 mutex_unlock (&once->mutex);
411 return 0;
414 static inline int
415 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
417 /* Solaris 2.5 contains thr_* routines no-op in libc, so test if we actually
418 got a reasonable key value, and if not, fail. */
419 *key = (__gthread_key_t)-1;
420 if (thr_keycreate (key, dtor) != 0 || *key == (__gthread_key_t)-1)
421 return -1;
422 else
423 return 0;
426 static inline int
427 __gthread_key_delete (__gthread_key_t key)
429 /* Not possible. */
430 return -1;
433 static inline void *
434 __gthread_getspecific (__gthread_key_t key)
436 void *ptr;
437 if (thr_getspecific (key, &ptr) == 0)
438 return ptr;
439 else
440 return 0;
443 static inline int
444 __gthread_setspecific (__gthread_key_t key, const void *ptr)
446 return thr_setspecific (key, (void *) ptr);
449 static inline int
450 __gthread_mutex_lock (__gthread_mutex_t *mutex)
452 if (__gthread_active_p ())
453 return mutex_lock (mutex);
454 else
455 return 0;
458 static inline int
459 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
461 if (__gthread_active_p ())
462 return mutex_trylock (mutex);
463 else
464 return 0;
467 static inline int
468 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
470 if (__gthread_active_p ())
471 return mutex_unlock (mutex);
472 else
473 return 0;
476 static inline int
477 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
479 mutex->depth = 0;
480 mutex->owner = (thread_t) 0;
481 return mutex_init (&mutex->actual, USYNC_THREAD, 0);
484 static inline int
485 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
487 if (__gthread_active_p ())
489 thread_t me = thr_self ();
491 if (mutex->owner != me)
493 mutex_lock (&mutex->actual);
494 mutex->owner = me;
497 mutex->depth++;
499 return 0;
502 static inline int
503 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
505 if (__gthread_active_p ())
507 thread_t me = thr_self ();
509 if (mutex->owner != me)
511 if (mutex_trylock (&mutex->actual))
512 return 1;
513 mutex->owner = me;
516 mutex->depth++;
518 return 0;
521 static inline int
522 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
524 if (__gthread_active_p ())
526 if (--mutex->depth == 0)
528 mutex->owner = (thread_t) 0;
529 mutex_unlock (&mutex->actual);
532 return 0;
535 #endif /* _LIBOBJC */
537 #endif /* ! GCC_GTHR_SOLARIS_H */