1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000, 2004, 2005, 2006
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
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
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
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. */
45 #define UNUSED(x) x __attribute__((unused))
48 typedef thread_key_t __gthread_key_t
;
53 typedef mutex_t __gthread_mutex_t
;
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
70 # define __gthrw(name)
71 # define __gthrw_(name) name
74 __gthrw(thr_keycreate
)
75 __gthrw(thr_getspecific
)
76 __gthrw(thr_setspecific
)
81 __gthrw(mutex_destroy
)
83 __gthrw(mutex_trylock
)
95 __gthrw(cond_broadcast
)
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. */
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 */
115 __gthread_active_p (void)
120 #endif /* SUPPORTS_WEAK */
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. */
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)
144 /* Close the threads subsystem. */
146 __gthread_objc_close_thread_system (void)
148 if (__gthread_active_p ())
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 ())
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
;
176 /* Set the current thread's priority. */
178 __gthread_objc_thread_set_priority (int priority
)
180 int sys_priority
= 0;
182 if (!__gthread_active_p ())
187 case OBJC_THREAD_INTERACTIVE_PRIORITY
:
191 case OBJC_THREAD_BACKGROUND_PRIORITY
:
194 case OBJC_THREAD_LOW_PRIORITY
:
199 /* Change priority */
200 if (__gthrw_(thr_setprio
) (__gthrw_(thr_self
) (), sys_priority
) == 0)
206 /* Return the current thread's priority. */
208 __gthread_objc_thread_get_priority (void)
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. */
228 /* Yield our process time to another thread. */
230 __gthread_objc_thread_yield (void)
232 if (__gthread_active_p ())
233 __gthrw_(thr_yield
) ();
236 /* Terminate the current thread. */
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 */
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
) ();
255 return (objc_thread_t
) 1;
258 /* Sets the thread's local storage pointer. */
260 __gthread_objc_thread_set_data (void *value
)
262 if (__gthread_active_p ())
264 if (__gthrw_(thr_setspecific
) (_objc_thread_storage
, value
) == 0)
271 thread_local_storage
= value
;
276 /* Returns the thread's local storage pointer. */
278 __gthread_objc_thread_get_data (void)
282 if (__gthread_active_p ())
284 if (__gthrw_(thr_getspecific
) (_objc_thread_storage
, &value
) == 0)
290 return thread_local_storage
;
293 /* Backend mutex functions */
295 /* Allocate a mutex. */
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))
306 /* Deallocate a mutex. */
308 __gthread_objc_mutex_deallocate (objc_mutex_t mutex
)
310 if (__gthread_active_p ())
311 __gthrw_(mutex_destroy
) ((mutex_t
*) (&(mutex
->backend
)));
316 /* Grab a lock on a mutex. */
318 __gthread_objc_mutex_lock (objc_mutex_t mutex
)
320 if (__gthread_active_p ()
321 && __gthrw_(mutex_lock
) ((mutex_t
*) (&(mutex
->backend
))) != 0)
327 /* Try to grab a lock on a mutex. */
329 __gthread_objc_mutex_trylock (objc_mutex_t mutex
)
331 if (__gthread_active_p ()
332 && __gthrw_(mutex_trylock
) ((mutex_t
*) (&(mutex
->backend
))) != 0)
338 /* Unlock the mutex */
340 __gthread_objc_mutex_unlock (objc_mutex_t mutex
)
342 if (__gthread_active_p ()
343 && __gthrw_(mutex_unlock
) ((mutex_t
*) (&(mutex
->backend
))) != 0)
349 /* Backend condition mutex functions */
351 /* Allocate a condition. */
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
,
362 /* Deallocate a condition. */
364 __gthread_objc_condition_deallocate (objc_condition_t condition
)
366 if (__gthread_active_p ())
367 return __gthrw_(cond_destroy
) ((cond_t
*) (&(condition
->backend
)));
372 /* Wait on the condition */
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
)));
383 /* Wake up all threads waiting on this condition. */
385 __gthread_objc_condition_broadcast (objc_condition_t condition
)
387 if (__gthread_active_p ())
388 return __gthrw_(cond_broadcast
) ((cond_t
*) (&(condition
->backend
)));
393 /* Wake up one thread waiting on this condition. */
395 __gthread_objc_condition_signal (objc_condition_t condition
)
397 if (__gthread_active_p ())
398 return __gthrw_(cond_signal
) ((cond_t
*) (&(condition
->backend
)));
406 __gthread_once (__gthread_once_t
*once
, void (*func
) (void))
408 if (! __gthread_active_p ())
411 if (once
== 0 || func
== 0)
416 int status
= __gthrw_(mutex_lock
) (&once
->mutex
);
424 __gthrw_(mutex_unlock
) (&once
->mutex
);
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 || *key
== (__gthread_key_t
)-1)
442 __gthread_key_delete (__gthread_key_t
UNUSED (key
))
449 __gthread_getspecific (__gthread_key_t key
)
452 if (__gthrw_(thr_getspecific
) (key
, &ptr
) == 0)
459 __gthread_setspecific (__gthread_key_t key
, const void *ptr
)
461 return __gthrw_(thr_setspecific
) (key
, (void *) ptr
);
465 __gthread_mutex_destroy (__gthread_mutex_t
* UNUSED(mutex
))
467 if (__gthread_active_p ())
468 return __gthrw_(mutex_destroy
) (mutex
);
474 __gthread_mutex_lock (__gthread_mutex_t
*mutex
)
476 if (__gthread_active_p ())
477 return __gthrw_(mutex_lock
) (mutex
);
483 __gthread_mutex_trylock (__gthread_mutex_t
*mutex
)
485 if (__gthread_active_p ())
486 return __gthrw_(mutex_trylock
) (mutex
);
492 __gthread_mutex_unlock (__gthread_mutex_t
*mutex
)
494 if (__gthread_active_p ())
495 return __gthrw_(mutex_unlock
) (mutex
);
501 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t
*mutex
)
504 mutex
->owner
= (thread_t
) 0;
505 return __gthrw_(mutex_init
) (&mutex
->actual
, USYNC_THREAD
, 0);
509 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t
*mutex
)
511 if (__gthread_active_p ())
513 thread_t me
= __gthrw_(thr_self
) ();
515 if (mutex
->owner
!= me
)
517 __gthrw_(mutex_lock
) (&mutex
->actual
);
527 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t
*mutex
)
529 if (__gthread_active_p ())
531 thread_t me
= __gthrw_(thr_self
) ();
533 if (mutex
->owner
!= me
)
535 if (__gthrw_(mutex_trylock
) (&mutex
->actual
))
546 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t
*mutex
)
548 if (__gthread_active_p ())
550 if (--mutex
->depth
== 0)
552 mutex
->owner
= (thread_t
) 0;
553 __gthrw_(mutex_unlock
) (&mutex
->actual
);
559 #endif /* _LIBOBJC */
563 #endif /* ! GCC_GTHR_SOLARIS_H */