1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 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_POSIX_H
31 #define GCC_GTHR_POSIX_H
33 /* POSIX threads specific definitions.
34 Easy, since the interface is just one-to-one mapping. */
38 /* Some implementations of <pthread.h> require this to be defined. */
46 typedef pthread_key_t __gthread_key_t;
47 typedef pthread_once_t __gthread_once_t;
48 typedef pthread_mutex_t __gthread_mutex_t;
49 typedef pthread_mutex_t __gthread_recursive_mutex_t;
51 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
52 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
53 #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
54 #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
55 #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
56 #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
58 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
61 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
62 # define __gthrw2(name,name2) \
63 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name2)));
64 # define __gthrw_(name) __gthrw_ ## name
66 # define __gthrw2(name,name2)
67 # define __gthrw_(name) name
70 /* Typically, __gthrw_foo is a weak refernce to symbol foo. */
71 #define __gthrw(name) __gthrw2(name,name)
73 /* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
74 map a subset of the POSIX pthread API to mangled versions of their
76 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
77 __gthrw2(pthread_once,__pthread_once)
78 __gthrw2(pthread_getspecific,__pthread_getspecific)
79 __gthrw2(pthread_setspecific,__pthread_setspecific)
80 __gthrw2(pthread_create,__pthread_create)
81 __gthrw2(pthread_cancel,__pthread_cancel)
82 __gthrw2(pthread_mutex_lock,__pthread_mutex_lock)
83 __gthrw2(pthread_mutex_trylock,__pthread_mutex_trylock)
84 __gthrw2(pthread_mutex_unlock,__pthread_mutex_unlock)
85 __gthrw2(pthread_mutex_init,__pthread_mutex_init)
88 __gthrw(pthread_getspecific)
89 __gthrw(pthread_setspecific)
90 __gthrw(pthread_create)
91 __gthrw(pthread_cancel)
92 __gthrw(pthread_mutex_lock)
93 __gthrw(pthread_mutex_trylock)
94 __gthrw(pthread_mutex_unlock)
95 __gthrw(pthread_mutex_init)
98 __gthrw(pthread_key_create)
99 __gthrw(pthread_key_delete)
100 __gthrw(pthread_mutexattr_init)
101 __gthrw(pthread_mutexattr_settype)
102 __gthrw(pthread_mutexattr_destroy)
105 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
107 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
108 __gthrw2(pthread_cond_broadcast,__pthread_cond_broadcast)
109 __gthrw2(pthread_cond_destroy,__pthread_cond_destroy)
110 __gthrw2(pthread_cond_init,__pthread_cond_init)
111 __gthrw2(pthread_cond_signal,__pthread_cond_signal)
112 __gthrw2(pthread_cond_wait,__pthread_cond_wait)
113 __gthrw2(pthread_exit,__pthread_exit)
114 __gthrw2(pthread_mutex_destroy,__pthread_mutex_destroy)
115 __gthrw2(pthread_self,__pthread_self)
117 __gthrw(pthread_cond_broadcast)
118 __gthrw(pthread_cond_destroy)
119 __gthrw(pthread_cond_init)
120 __gthrw(pthread_cond_signal)
121 __gthrw(pthread_cond_wait)
122 __gthrw(pthread_exit)
123 __gthrw(pthread_mutex_destroy)
124 __gthrw(pthread_self)
125 #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
126 #ifdef _POSIX_PRIORITY_SCHEDULING
127 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
128 __gthrw(sched_get_priority_max)
129 __gthrw(sched_get_priority_min)
130 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
131 #endif /* _POSIX_PRIORITY_SCHEDULING */
133 __gthrw(pthread_attr_destroy)
134 __gthrw(pthread_attr_init)
135 __gthrw(pthread_attr_setdetachstate)
136 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
137 __gthrw(pthread_getschedparam)
138 __gthrw(pthread_setschedparam)
139 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
140 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
142 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
145 __gthread_active_p (void)
147 static void *const __gthread_active_ptr
148 = __extension__ (void *) &__gthrw_(pthread_cancel);
149 return __gthread_active_ptr != 0;
152 #else /* not SUPPORTS_WEAK */
155 __gthread_active_p (void)
160 #endif /* SUPPORTS_WEAK */
164 /* This is the config.h file in libobjc/ */
171 /* Key structure for maintaining thread specific storage */
172 static pthread_key_t _objc_thread_storage;
173 static pthread_attr_t _objc_thread_attribs;
175 /* Thread local storage for a single thread */
176 static void *thread_local_storage = NULL;
178 /* Backend initialization functions */
180 /* Initialize the threads subsystem. */
182 __gthread_objc_init_thread_system (void)
184 if (__gthread_active_p ())
186 /* Initialize the thread storage key. */
187 if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
189 /* The normal default detach state for threads is
190 * PTHREAD_CREATE_JOINABLE which causes threads to not die
191 * when you think they should. */
192 if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
193 && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
194 PTHREAD_CREATE_DETACHED) == 0)
202 /* Close the threads subsystem. */
204 __gthread_objc_close_thread_system (void)
206 if (__gthread_active_p ()
207 && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
208 && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
214 /* Backend thread functions */
216 /* Create a new thread of execution. */
217 static inline objc_thread_t
218 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
220 objc_thread_t thread_id;
221 pthread_t new_thread_handle;
223 if (!__gthread_active_p ())
226 if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
227 thread_id = (objc_thread_t) new_thread_handle;
234 /* Set the current thread's priority. */
236 __gthread_objc_thread_set_priority (int priority)
238 if (!__gthread_active_p ())
242 #ifdef _POSIX_PRIORITY_SCHEDULING
243 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
244 pthread_t thread_id = __gthrw_(pthread_self) ();
246 struct sched_param params;
247 int priority_min, priority_max;
249 if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0)
251 if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
254 if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
257 if (priority > priority_max)
258 priority = priority_max;
259 else if (priority < priority_min)
260 priority = priority_min;
261 params.sched_priority = priority;
264 * The solaris 7 and several other man pages incorrectly state that
265 * this should be a pointer to policy but pthread.h is universally
268 if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0)
271 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
272 #endif /* _POSIX_PRIORITY_SCHEDULING */
277 /* Return the current thread's priority. */
279 __gthread_objc_thread_get_priority (void)
281 #ifdef _POSIX_PRIORITY_SCHEDULING
282 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
283 if (__gthread_active_p ())
286 struct sched_param params;
288 if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0)
289 return params.sched_priority;
294 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
295 #endif /* _POSIX_PRIORITY_SCHEDULING */
296 return OBJC_THREAD_INTERACTIVE_PRIORITY;
299 /* Yield our process time to another thread. */
301 __gthread_objc_thread_yield (void)
303 if (__gthread_active_p ())
304 __gthrw_(sched_yield) ();
307 /* Terminate the current thread. */
309 __gthread_objc_thread_exit (void)
311 if (__gthread_active_p ())
312 /* exit the thread */
313 __gthrw_(pthread_exit) (&__objc_thread_exit_status);
315 /* Failed if we reached here */
319 /* Returns an integer value which uniquely describes a thread. */
320 static inline objc_thread_t
321 __gthread_objc_thread_id (void)
323 if (__gthread_active_p ())
324 return (objc_thread_t) __gthrw_(pthread_self) ();
326 return (objc_thread_t) 1;
329 /* Sets the thread's local storage pointer. */
331 __gthread_objc_thread_set_data (void *value)
333 if (__gthread_active_p ())
334 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
337 thread_local_storage = value;
342 /* Returns the thread's local storage pointer. */
344 __gthread_objc_thread_get_data (void)
346 if (__gthread_active_p ())
347 return __gthrw_(pthread_getspecific) (_objc_thread_storage);
349 return thread_local_storage;
352 /* Backend mutex functions */
354 /* Allocate a mutex. */
356 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
358 if (__gthread_active_p ())
360 mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
362 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
364 objc_free (mutex->backend);
365 mutex->backend = NULL;
373 /* Deallocate a mutex. */
375 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
377 if (__gthread_active_p ())
382 * Posix Threads specifically require that the thread be unlocked
383 * for __gthrw_(pthread_mutex_destroy) to work.
388 count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
394 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
397 objc_free (mutex->backend);
398 mutex->backend = NULL;
403 /* Grab a lock on a mutex. */
405 __gthread_objc_mutex_lock (objc_mutex_t mutex)
407 if (__gthread_active_p ()
408 && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
416 /* Try to grab a lock on a mutex. */
418 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
420 if (__gthread_active_p ()
421 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
429 /* Unlock the mutex */
431 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
433 if (__gthread_active_p ()
434 && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
442 /* Backend condition mutex functions */
444 /* Allocate a condition. */
446 __gthread_objc_condition_allocate (objc_condition_t condition)
448 if (__gthread_active_p ())
450 condition->backend = objc_malloc (sizeof (pthread_cond_t));
452 if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
454 objc_free (condition->backend);
455 condition->backend = NULL;
463 /* Deallocate a condition. */
465 __gthread_objc_condition_deallocate (objc_condition_t condition)
467 if (__gthread_active_p ())
469 if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
472 objc_free (condition->backend);
473 condition->backend = NULL;
478 /* Wait on the condition */
480 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
482 if (__gthread_active_p ())
483 return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
484 (pthread_mutex_t *) mutex->backend);
489 /* Wake up all threads waiting on this condition. */
491 __gthread_objc_condition_broadcast (objc_condition_t condition)
493 if (__gthread_active_p ())
494 return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
499 /* Wake up one thread waiting on this condition. */
501 __gthread_objc_condition_signal (objc_condition_t condition)
503 if (__gthread_active_p ())
504 return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
512 __gthread_once (__gthread_once_t *once, void (*func) (void))
514 if (__gthread_active_p ())
515 return __gthrw_(pthread_once) (once, func);
521 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
523 return __gthrw_(pthread_key_create) (key, dtor);
527 __gthread_key_delete (__gthread_key_t key)
529 return __gthrw_(pthread_key_delete) (key);
533 __gthread_getspecific (__gthread_key_t key)
535 return __gthrw_(pthread_getspecific) (key);
539 __gthread_setspecific (__gthread_key_t key, const void *ptr)
541 return __gthrw_(pthread_setspecific) (key, ptr);
545 __gthread_mutex_lock (__gthread_mutex_t *mutex)
547 if (__gthread_active_p ())
548 return __gthrw_(pthread_mutex_lock) (mutex);
554 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
556 if (__gthread_active_p ())
557 return __gthrw_(pthread_mutex_trylock) (mutex);
563 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
565 if (__gthread_active_p ())
566 return __gthrw_(pthread_mutex_unlock) (mutex);
571 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
573 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
575 if (__gthread_active_p ())
577 pthread_mutexattr_t attr;
580 r = __gthrw_(pthread_mutexattr_init) (&attr);
582 r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
584 r = __gthrw_(pthread_mutex_init) (mutex, &attr);
586 r = __gthrw_(pthread_mutexattr_destroy) (&attr);
594 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
596 return __gthread_mutex_lock (mutex);
600 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
602 return __gthread_mutex_trylock (mutex);
606 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
608 return __gthread_mutex_unlock (mutex);
611 #endif /* _LIBOBJC */
613 #endif /* ! GCC_GTHR_POSIX_H */