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
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 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. */
42 #define UNUSED(x) x __attribute__((unused))
45 typedef thread_key_t __gthread_key_t
;
50 typedef mutex_t __gthread_mutex_t
;
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
67 # define __gthrw(name)
68 # define __gthrw_(name) name
71 __gthrw(thr_keycreate
)
72 __gthrw(thr_getspecific
)
73 __gthrw(thr_setspecific
)
78 __gthrw(mutex_destroy
)
80 __gthrw(mutex_trylock
)
92 __gthrw(cond_broadcast
)
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. */
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 */
113 __gthread_active_p (void)
118 #endif /* SUPPORTS_WEAK */
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. */
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)
142 /* Close the threads subsystem. */
144 __gthread_objc_close_thread_system (void)
146 if (__gthread_active_p ())
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 ())
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
;
174 /* Set the current thread's priority. */
176 __gthread_objc_thread_set_priority (int priority
)
178 int sys_priority
= 0;
180 if (!__gthread_active_p ())
185 case OBJC_THREAD_INTERACTIVE_PRIORITY
:
189 case OBJC_THREAD_BACKGROUND_PRIORITY
:
192 case OBJC_THREAD_LOW_PRIORITY
:
197 /* Change priority */
198 if (__gthrw_(thr_setprio
) (__gthrw_(thr_self
) (), sys_priority
) == 0)
204 /* Return the current thread's priority. */
206 __gthread_objc_thread_get_priority (void)
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. */
226 /* Yield our process time to another thread. */
228 __gthread_objc_thread_yield (void)
230 if (__gthread_active_p ())
231 __gthrw_(thr_yield
) ();
234 /* Terminate the current thread. */
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 */
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
) ();
253 return (objc_thread_t
) 1;
256 /* Sets the thread's local storage pointer. */
258 __gthread_objc_thread_set_data (void *value
)
260 if (__gthread_active_p ())
262 if (__gthrw_(thr_setspecific
) (_objc_thread_storage
, value
) == 0)
269 thread_local_storage
= value
;
274 /* Returns the thread's local storage pointer. */
276 __gthread_objc_thread_get_data (void)
280 if (__gthread_active_p ())
282 if (__gthrw_(thr_getspecific
) (_objc_thread_storage
, &value
) == 0)
288 return thread_local_storage
;
291 /* Backend mutex functions */
293 /* Allocate a mutex. */
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))
304 /* Deallocate a mutex. */
306 __gthread_objc_mutex_deallocate (objc_mutex_t mutex
)
308 if (__gthread_active_p ())
309 __gthrw_(mutex_destroy
) ((mutex_t
*) (&(mutex
->backend
)));
314 /* Grab a lock on a mutex. */
316 __gthread_objc_mutex_lock (objc_mutex_t mutex
)
318 if (__gthread_active_p ()
319 && __gthrw_(mutex_lock
) ((mutex_t
*) (&(mutex
->backend
))) != 0)
325 /* Try to grab a lock on a mutex. */
327 __gthread_objc_mutex_trylock (objc_mutex_t mutex
)
329 if (__gthread_active_p ()
330 && __gthrw_(mutex_trylock
) ((mutex_t
*) (&(mutex
->backend
))) != 0)
336 /* Unlock the mutex */
338 __gthread_objc_mutex_unlock (objc_mutex_t mutex
)
340 if (__gthread_active_p ()
341 && __gthrw_(mutex_unlock
) ((mutex_t
*) (&(mutex
->backend
))) != 0)
347 /* Backend condition mutex functions */
349 /* Allocate a condition. */
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
,
360 /* Deallocate a condition. */
362 __gthread_objc_condition_deallocate (objc_condition_t condition
)
364 if (__gthread_active_p ())
365 return __gthrw_(cond_destroy
) ((cond_t
*) (&(condition
->backend
)));
370 /* Wait on the condition */
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
)));
381 /* Wake up all threads waiting on this condition. */
383 __gthread_objc_condition_broadcast (objc_condition_t condition
)
385 if (__gthread_active_p ())
386 return __gthrw_(cond_broadcast
) ((cond_t
*) (&(condition
->backend
)));
391 /* Wake up one thread waiting on this condition. */
393 __gthread_objc_condition_signal (objc_condition_t condition
)
395 if (__gthread_active_p ())
396 return __gthrw_(cond_signal
) ((cond_t
*) (&(condition
->backend
)));
404 __gthread_once (__gthread_once_t
*__once
, void (*__func
) (void))
406 if (! __gthread_active_p ())
409 if (__once
== 0 || __func
== 0)
412 if (__once
->once
== 0)
414 int __status
= __gthrw_(mutex_lock
) (&__once
->mutex
);
417 if (__once
->once
== 0)
422 __gthrw_(mutex_unlock
) (&__once
->mutex
);
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)
441 __gthread_key_delete (__gthread_key_t
UNUSED (__key
))
448 __gthread_getspecific (__gthread_key_t __key
)
451 if (__gthrw_(thr_getspecific
) (__key
, &__ptr
) == 0)
458 __gthread_setspecific (__gthread_key_t __key
, const void *__ptr
)
460 return __gthrw_(thr_setspecific
) (__key
, (void *) __ptr
);
464 __gthread_mutex_destroy (__gthread_mutex_t
*__mutex
)
466 if (__gthread_active_p ())
467 return __gthrw_(mutex_destroy
) (__mutex
);
473 __gthread_mutex_lock (__gthread_mutex_t
*__mutex
)
475 if (__gthread_active_p ())
476 return __gthrw_(mutex_lock
) (__mutex
);
482 __gthread_mutex_trylock (__gthread_mutex_t
*__mutex
)
484 if (__gthread_active_p ())
485 return __gthrw_(mutex_trylock
) (__mutex
);
491 __gthread_mutex_unlock (__gthread_mutex_t
*__mutex
)
493 if (__gthread_active_p ())
494 return __gthrw_(mutex_unlock
) (__mutex
);
500 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t
*__mutex
)
503 __mutex
->owner
= (thread_t
) 0;
504 return __gthrw_(mutex_init
) (&__mutex
->actual
, USYNC_THREAD
, 0);
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
;
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
))
536 __mutex
->owner
= __me
;
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
);
558 #endif /* _LIBOBJC */
562 #endif /* ! GCC_GTHR_SOLARIS_H */