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,type) \
63 static __typeof(type) name __attribute__ ((__weakref__(#name2)));
64 # define __gthrw_(name) __gthrw_ ## name
66 # define __gthrw2(name,name2,type)
67 # define __gthrw_(name) name
70 /* Typically, __gthrw_foo is a weak reference to symbol foo. */
71 #define __gthrw(name) __gthrw2(__gthrw_ ## name,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 #define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
78 __gthrw3(pthread_once
)
79 __gthrw3(pthread_getspecific
)
80 __gthrw3(pthread_setspecific
)
81 __gthrw3(pthread_create
)
82 __gthrw3(pthread_cancel
)
83 __gthrw3(pthread_mutex_lock
)
84 __gthrw3(pthread_mutex_trylock
)
85 __gthrw3(pthread_mutex_unlock
)
86 __gthrw3(pthread_mutex_init
)
89 __gthrw(pthread_getspecific
)
90 __gthrw(pthread_setspecific
)
91 __gthrw(pthread_create
)
92 __gthrw(pthread_cancel
)
93 __gthrw(pthread_mutex_lock
)
94 __gthrw(pthread_mutex_trylock
)
95 __gthrw(pthread_mutex_unlock
)
96 __gthrw(pthread_mutex_init
)
99 __gthrw(pthread_key_create
)
100 __gthrw(pthread_key_delete
)
101 __gthrw(pthread_mutexattr_init
)
102 __gthrw(pthread_mutexattr_settype
)
103 __gthrw(pthread_mutexattr_destroy
)
106 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
108 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
109 __gthrw3(pthread_cond_broadcast
)
110 __gthrw3(pthread_cond_destroy
)
111 __gthrw3(pthread_cond_init
)
112 __gthrw3(pthread_cond_signal
)
113 __gthrw3(pthread_cond_wait
)
114 __gthrw3(pthread_exit
)
115 __gthrw3(pthread_mutex_destroy
)
116 __gthrw3(pthread_self
)
118 __gthrw(pthread_cond_broadcast
)
119 __gthrw(pthread_cond_destroy
)
120 __gthrw(pthread_cond_init
)
121 __gthrw(pthread_cond_signal
)
122 __gthrw(pthread_cond_wait
)
123 __gthrw(pthread_exit
)
124 __gthrw(pthread_mutex_destroy
)
125 __gthrw(pthread_self
)
126 #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
127 #ifdef _POSIX_PRIORITY_SCHEDULING
128 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
129 __gthrw(sched_get_priority_max
)
130 __gthrw(sched_get_priority_min
)
131 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
132 #endif /* _POSIX_PRIORITY_SCHEDULING */
134 __gthrw(pthread_attr_destroy
)
135 __gthrw(pthread_attr_init
)
136 __gthrw(pthread_attr_setdetachstate
)
137 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
138 __gthrw(pthread_getschedparam
)
139 __gthrw(pthread_setschedparam
)
140 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
141 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
143 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
146 __gthread_active_p (void)
148 static void *const __gthread_active_ptr
149 = __extension__ (void *) &__gthrw_(pthread_cancel
);
150 return __gthread_active_ptr
!= 0;
153 #else /* not SUPPORTS_WEAK */
156 __gthread_active_p (void)
161 #endif /* SUPPORTS_WEAK */
165 /* This is the config.h file in libobjc/ */
172 /* Key structure for maintaining thread specific storage */
173 static pthread_key_t _objc_thread_storage
;
174 static pthread_attr_t _objc_thread_attribs
;
176 /* Thread local storage for a single thread */
177 static void *thread_local_storage
= NULL
;
179 /* Backend initialization functions */
181 /* Initialize the threads subsystem. */
183 __gthread_objc_init_thread_system (void)
185 if (__gthread_active_p ())
187 /* Initialize the thread storage key. */
188 if (__gthrw_(pthread_key_create
) (&_objc_thread_storage
, NULL
) == 0)
190 /* The normal default detach state for threads is
191 * PTHREAD_CREATE_JOINABLE which causes threads to not die
192 * when you think they should. */
193 if (__gthrw_(pthread_attr_init
) (&_objc_thread_attribs
) == 0
194 && __gthrw_(pthread_attr_setdetachstate
) (&_objc_thread_attribs
,
195 PTHREAD_CREATE_DETACHED
) == 0)
203 /* Close the threads subsystem. */
205 __gthread_objc_close_thread_system (void)
207 if (__gthread_active_p ()
208 && __gthrw_(pthread_key_delete
) (_objc_thread_storage
) == 0
209 && __gthrw_(pthread_attr_destroy
) (&_objc_thread_attribs
) == 0)
215 /* Backend thread functions */
217 /* Create a new thread of execution. */
218 static inline objc_thread_t
219 __gthread_objc_thread_detach (void (*func
)(void *), void *arg
)
221 objc_thread_t thread_id
;
222 pthread_t new_thread_handle
;
224 if (!__gthread_active_p ())
227 if (!(__gthrw_(pthread_create
) (&new_thread_handle
, NULL
, (void *) func
, arg
)))
228 thread_id
= (objc_thread_t
) new_thread_handle
;
235 /* Set the current thread's priority. */
237 __gthread_objc_thread_set_priority (int priority
)
239 if (!__gthread_active_p ())
243 #ifdef _POSIX_PRIORITY_SCHEDULING
244 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
245 pthread_t thread_id
= __gthrw_(pthread_self
) ();
247 struct sched_param params
;
248 int priority_min
, priority_max
;
250 if (__gthrw_(pthread_getschedparam
) (thread_id
, &policy
, ¶ms
) == 0)
252 if ((priority_max
= __gthrw_(sched_get_priority_max
) (policy
)) == -1)
255 if ((priority_min
= __gthrw_(sched_get_priority_min
) (policy
)) == -1)
258 if (priority
> priority_max
)
259 priority
= priority_max
;
260 else if (priority
< priority_min
)
261 priority
= priority_min
;
262 params
.sched_priority
= priority
;
265 * The solaris 7 and several other man pages incorrectly state that
266 * this should be a pointer to policy but pthread.h is universally
269 if (__gthrw_(pthread_setschedparam
) (thread_id
, policy
, ¶ms
) == 0)
272 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
273 #endif /* _POSIX_PRIORITY_SCHEDULING */
278 /* Return the current thread's priority. */
280 __gthread_objc_thread_get_priority (void)
282 #ifdef _POSIX_PRIORITY_SCHEDULING
283 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
284 if (__gthread_active_p ())
287 struct sched_param params
;
289 if (__gthrw_(pthread_getschedparam
) (__gthrw_(pthread_self
) (), &policy
, ¶ms
) == 0)
290 return params
.sched_priority
;
295 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
296 #endif /* _POSIX_PRIORITY_SCHEDULING */
297 return OBJC_THREAD_INTERACTIVE_PRIORITY
;
300 /* Yield our process time to another thread. */
302 __gthread_objc_thread_yield (void)
304 if (__gthread_active_p ())
305 __gthrw_(sched_yield
) ();
308 /* Terminate the current thread. */
310 __gthread_objc_thread_exit (void)
312 if (__gthread_active_p ())
313 /* exit the thread */
314 __gthrw_(pthread_exit
) (&__objc_thread_exit_status
);
316 /* Failed if we reached here */
320 /* Returns an integer value which uniquely describes a thread. */
321 static inline objc_thread_t
322 __gthread_objc_thread_id (void)
324 if (__gthread_active_p ())
325 return (objc_thread_t
) __gthrw_(pthread_self
) ();
327 return (objc_thread_t
) 1;
330 /* Sets the thread's local storage pointer. */
332 __gthread_objc_thread_set_data (void *value
)
334 if (__gthread_active_p ())
335 return __gthrw_(pthread_setspecific
) (_objc_thread_storage
, value
);
338 thread_local_storage
= value
;
343 /* Returns the thread's local storage pointer. */
345 __gthread_objc_thread_get_data (void)
347 if (__gthread_active_p ())
348 return __gthrw_(pthread_getspecific
) (_objc_thread_storage
);
350 return thread_local_storage
;
353 /* Backend mutex functions */
355 /* Allocate a mutex. */
357 __gthread_objc_mutex_allocate (objc_mutex_t mutex
)
359 if (__gthread_active_p ())
361 mutex
->backend
= objc_malloc (sizeof (pthread_mutex_t
));
363 if (__gthrw_(pthread_mutex_init
) ((pthread_mutex_t
*) mutex
->backend
, NULL
))
365 objc_free (mutex
->backend
);
366 mutex
->backend
= NULL
;
374 /* Deallocate a mutex. */
376 __gthread_objc_mutex_deallocate (objc_mutex_t mutex
)
378 if (__gthread_active_p ())
383 * Posix Threads specifically require that the thread be unlocked
384 * for __gthrw_(pthread_mutex_destroy) to work.
389 count
= __gthrw_(pthread_mutex_unlock
) ((pthread_mutex_t
*) mutex
->backend
);
395 if (__gthrw_(pthread_mutex_destroy
) ((pthread_mutex_t
*) mutex
->backend
))
398 objc_free (mutex
->backend
);
399 mutex
->backend
= NULL
;
404 /* Grab a lock on a mutex. */
406 __gthread_objc_mutex_lock (objc_mutex_t mutex
)
408 if (__gthread_active_p ()
409 && __gthrw_(pthread_mutex_lock
) ((pthread_mutex_t
*) mutex
->backend
) != 0)
417 /* Try to grab a lock on a mutex. */
419 __gthread_objc_mutex_trylock (objc_mutex_t mutex
)
421 if (__gthread_active_p ()
422 && __gthrw_(pthread_mutex_trylock
) ((pthread_mutex_t
*) mutex
->backend
) != 0)
430 /* Unlock the mutex */
432 __gthread_objc_mutex_unlock (objc_mutex_t mutex
)
434 if (__gthread_active_p ()
435 && __gthrw_(pthread_mutex_unlock
) ((pthread_mutex_t
*) mutex
->backend
) != 0)
443 /* Backend condition mutex functions */
445 /* Allocate a condition. */
447 __gthread_objc_condition_allocate (objc_condition_t condition
)
449 if (__gthread_active_p ())
451 condition
->backend
= objc_malloc (sizeof (pthread_cond_t
));
453 if (__gthrw_(pthread_cond_init
) ((pthread_cond_t
*) condition
->backend
, NULL
))
455 objc_free (condition
->backend
);
456 condition
->backend
= NULL
;
464 /* Deallocate a condition. */
466 __gthread_objc_condition_deallocate (objc_condition_t condition
)
468 if (__gthread_active_p ())
470 if (__gthrw_(pthread_cond_destroy
) ((pthread_cond_t
*) condition
->backend
))
473 objc_free (condition
->backend
);
474 condition
->backend
= NULL
;
479 /* Wait on the condition */
481 __gthread_objc_condition_wait (objc_condition_t condition
, objc_mutex_t mutex
)
483 if (__gthread_active_p ())
484 return __gthrw_(pthread_cond_wait
) ((pthread_cond_t
*) condition
->backend
,
485 (pthread_mutex_t
*) mutex
->backend
);
490 /* Wake up all threads waiting on this condition. */
492 __gthread_objc_condition_broadcast (objc_condition_t condition
)
494 if (__gthread_active_p ())
495 return __gthrw_(pthread_cond_broadcast
) ((pthread_cond_t
*) condition
->backend
);
500 /* Wake up one thread waiting on this condition. */
502 __gthread_objc_condition_signal (objc_condition_t condition
)
504 if (__gthread_active_p ())
505 return __gthrw_(pthread_cond_signal
) ((pthread_cond_t
*) condition
->backend
);
513 __gthread_once (__gthread_once_t
*once
, void (*func
) (void))
515 if (__gthread_active_p ())
516 return __gthrw_(pthread_once
) (once
, func
);
522 __gthread_key_create (__gthread_key_t
*key
, void (*dtor
) (void *))
524 return __gthrw_(pthread_key_create
) (key
, dtor
);
528 __gthread_key_delete (__gthread_key_t key
)
530 return __gthrw_(pthread_key_delete
) (key
);
534 __gthread_getspecific (__gthread_key_t key
)
536 return __gthrw_(pthread_getspecific
) (key
);
540 __gthread_setspecific (__gthread_key_t key
, const void *ptr
)
542 return __gthrw_(pthread_setspecific
) (key
, ptr
);
546 __gthread_mutex_lock (__gthread_mutex_t
*mutex
)
548 if (__gthread_active_p ())
549 return __gthrw_(pthread_mutex_lock
) (mutex
);
555 __gthread_mutex_trylock (__gthread_mutex_t
*mutex
)
557 if (__gthread_active_p ())
558 return __gthrw_(pthread_mutex_trylock
) (mutex
);
564 __gthread_mutex_unlock (__gthread_mutex_t
*mutex
)
566 if (__gthread_active_p ())
567 return __gthrw_(pthread_mutex_unlock
) (mutex
);
572 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
574 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t
*mutex
)
576 if (__gthread_active_p ())
578 pthread_mutexattr_t attr
;
581 r
= __gthrw_(pthread_mutexattr_init
) (&attr
);
583 r
= __gthrw_(pthread_mutexattr_settype
) (&attr
, PTHREAD_MUTEX_RECURSIVE
);
585 r
= __gthrw_(pthread_mutex_init
) (mutex
, &attr
);
587 r
= __gthrw_(pthread_mutexattr_destroy
) (&attr
);
595 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t
*mutex
)
597 return __gthread_mutex_lock (mutex
);
601 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t
*mutex
)
603 return __gthread_mutex_trylock (mutex
);
607 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t
*mutex
)
609 return __gthread_mutex_unlock (mutex
);
612 #endif /* _LIBOBJC */
614 #endif /* ! GCC_GTHR_POSIX_H */