1*e4b17023SJohn Marino /* Threads compatibility routines for libgcc2 and libobjc. */
2*e4b17023SJohn Marino /* Compile this one with gcc. */
3*e4b17023SJohn Marino /* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4*e4b17023SJohn Marino 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
5*e4b17023SJohn Marino
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino
18*e4b17023SJohn Marino Under Section 7 of GPL version 3, you are granted additional
19*e4b17023SJohn Marino permissions described in the GCC Runtime Library Exception, version
20*e4b17023SJohn Marino 3.1, as published by the Free Software Foundation.
21*e4b17023SJohn Marino
22*e4b17023SJohn Marino You should have received a copy of the GNU General Public License and
23*e4b17023SJohn Marino a copy of the GCC Runtime Library Exception along with this program;
24*e4b17023SJohn Marino see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
26*e4b17023SJohn Marino
27*e4b17023SJohn Marino #ifndef GCC_GTHR_POSIX_H
28*e4b17023SJohn Marino #define GCC_GTHR_POSIX_H
29*e4b17023SJohn Marino
30*e4b17023SJohn Marino /* POSIX threads specific definitions.
31*e4b17023SJohn Marino Easy, since the interface is just one-to-one mapping. */
32*e4b17023SJohn Marino
33*e4b17023SJohn Marino #define __GTHREADS 1
34*e4b17023SJohn Marino #define __GTHREADS_CXX0X 1
35*e4b17023SJohn Marino
36*e4b17023SJohn Marino /* Some implementations of <pthread.h> require this to be defined. */
37*e4b17023SJohn Marino #if !defined(_REENTRANT) && defined(__osf__)
38*e4b17023SJohn Marino #define _REENTRANT 1
39*e4b17023SJohn Marino #endif
40*e4b17023SJohn Marino
41*e4b17023SJohn Marino #include <pthread.h>
42*e4b17023SJohn Marino
43*e4b17023SJohn Marino #if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \
44*e4b17023SJohn Marino || !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK))
45*e4b17023SJohn Marino # include <unistd.h>
46*e4b17023SJohn Marino # if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 0
47*e4b17023SJohn Marino # define _GTHREAD_USE_MUTEX_TIMEDLOCK 1
48*e4b17023SJohn Marino # else
49*e4b17023SJohn Marino # define _GTHREAD_USE_MUTEX_TIMEDLOCK 0
50*e4b17023SJohn Marino # endif
51*e4b17023SJohn Marino #endif
52*e4b17023SJohn Marino
53*e4b17023SJohn Marino typedef pthread_t __gthread_t;
54*e4b17023SJohn Marino typedef pthread_key_t __gthread_key_t;
55*e4b17023SJohn Marino typedef pthread_once_t __gthread_once_t;
56*e4b17023SJohn Marino typedef pthread_mutex_t __gthread_mutex_t;
57*e4b17023SJohn Marino typedef pthread_mutex_t __gthread_recursive_mutex_t;
58*e4b17023SJohn Marino typedef pthread_cond_t __gthread_cond_t;
59*e4b17023SJohn Marino typedef struct timespec __gthread_time_t;
60*e4b17023SJohn Marino
61*e4b17023SJohn Marino /* POSIX like conditional variables are supported. Please look at comments
62*e4b17023SJohn Marino in gthr.h for details. */
63*e4b17023SJohn Marino #define __GTHREAD_HAS_COND 1
64*e4b17023SJohn Marino
65*e4b17023SJohn Marino #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
66*e4b17023SJohn Marino #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
67*e4b17023SJohn Marino #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
68*e4b17023SJohn Marino #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
69*e4b17023SJohn Marino #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
70*e4b17023SJohn Marino #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
71*e4b17023SJohn Marino #else
72*e4b17023SJohn Marino #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
73*e4b17023SJohn Marino #endif
74*e4b17023SJohn Marino #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
75*e4b17023SJohn Marino #define __GTHREAD_TIME_INIT {0,0}
76*e4b17023SJohn Marino
77*e4b17023SJohn Marino #ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
78*e4b17023SJohn Marino # undef __GTHREAD_MUTEX_INIT
79*e4b17023SJohn Marino # define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
80*e4b17023SJohn Marino #endif
81*e4b17023SJohn Marino #ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC
82*e4b17023SJohn Marino # undef __GTHREAD_RECURSIVE_MUTEX_INIT
83*e4b17023SJohn Marino # undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
84*e4b17023SJohn Marino # define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
85*e4b17023SJohn Marino #endif
86*e4b17023SJohn Marino #ifdef _GTHREAD_USE_COND_INIT_FUNC
87*e4b17023SJohn Marino # undef __GTHREAD_COND_INIT
88*e4b17023SJohn Marino # define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
89*e4b17023SJohn Marino #endif
90*e4b17023SJohn Marino
91*e4b17023SJohn Marino #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
92*e4b17023SJohn Marino # ifndef __gthrw_pragma
93*e4b17023SJohn Marino # define __gthrw_pragma(pragma)
94*e4b17023SJohn Marino # endif
95*e4b17023SJohn Marino # define __gthrw2(name,name2,type) \
96*e4b17023SJohn Marino static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
97*e4b17023SJohn Marino __gthrw_pragma(weak type)
98*e4b17023SJohn Marino # define __gthrw_(name) __gthrw_ ## name
99*e4b17023SJohn Marino #else
100*e4b17023SJohn Marino # define __gthrw2(name,name2,type)
101*e4b17023SJohn Marino # define __gthrw_(name) name
102*e4b17023SJohn Marino #endif
103*e4b17023SJohn Marino
104*e4b17023SJohn Marino /* Typically, __gthrw_foo is a weak reference to symbol foo. */
105*e4b17023SJohn Marino #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
106*e4b17023SJohn Marino
107*e4b17023SJohn Marino /* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
108*e4b17023SJohn Marino map a subset of the POSIX pthread API to mangled versions of their
109*e4b17023SJohn Marino names. */
110*e4b17023SJohn Marino #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
111*e4b17023SJohn Marino #define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
112*e4b17023SJohn Marino __gthrw3(pthread_once)
113*e4b17023SJohn Marino __gthrw3(pthread_getspecific)
114*e4b17023SJohn Marino __gthrw3(pthread_setspecific)
115*e4b17023SJohn Marino
116*e4b17023SJohn Marino __gthrw3(pthread_create)
117*e4b17023SJohn Marino __gthrw3(pthread_join)
118*e4b17023SJohn Marino __gthrw3(pthread_detach)
119*e4b17023SJohn Marino __gthrw3(pthread_equal)
120*e4b17023SJohn Marino __gthrw3(pthread_self)
121*e4b17023SJohn Marino __gthrw3(pthread_cancel)
122*e4b17023SJohn Marino __gthrw3(sched_yield)
123*e4b17023SJohn Marino
124*e4b17023SJohn Marino __gthrw3(pthread_mutex_lock)
125*e4b17023SJohn Marino __gthrw3(pthread_mutex_trylock)
126*e4b17023SJohn Marino #if _GTHREAD_USE_MUTEX_TIMEDLOCK
127*e4b17023SJohn Marino __gthrw3(pthread_mutex_timedlock)
128*e4b17023SJohn Marino #endif
129*e4b17023SJohn Marino __gthrw3(pthread_mutex_unlock)
130*e4b17023SJohn Marino __gthrw3(pthread_mutex_init)
131*e4b17023SJohn Marino __gthrw3(pthread_mutex_destroy)
132*e4b17023SJohn Marino
133*e4b17023SJohn Marino __gthrw3(pthread_cond_init)
134*e4b17023SJohn Marino __gthrw3(pthread_cond_broadcast)
135*e4b17023SJohn Marino __gthrw3(pthread_cond_signal)
136*e4b17023SJohn Marino __gthrw3(pthread_cond_wait)
137*e4b17023SJohn Marino __gthrw3(pthread_cond_timedwait)
138*e4b17023SJohn Marino __gthrw3(pthread_cond_destroy)
139*e4b17023SJohn Marino #else
140*e4b17023SJohn Marino __gthrw(pthread_once)
141*e4b17023SJohn Marino __gthrw(pthread_getspecific)
142*e4b17023SJohn Marino __gthrw(pthread_setspecific)
143*e4b17023SJohn Marino
144*e4b17023SJohn Marino __gthrw(pthread_create)
145*e4b17023SJohn Marino __gthrw(pthread_join)
146*e4b17023SJohn Marino __gthrw(pthread_equal)
147*e4b17023SJohn Marino __gthrw(pthread_self)
148*e4b17023SJohn Marino __gthrw(pthread_detach)
149*e4b17023SJohn Marino #ifndef __BIONIC__
150*e4b17023SJohn Marino __gthrw(pthread_cancel)
151*e4b17023SJohn Marino #endif
152*e4b17023SJohn Marino __gthrw(sched_yield)
153*e4b17023SJohn Marino
154*e4b17023SJohn Marino __gthrw(pthread_mutex_lock)
155*e4b17023SJohn Marino __gthrw(pthread_mutex_trylock)
156*e4b17023SJohn Marino #if _GTHREAD_USE_MUTEX_TIMEDLOCK
157*e4b17023SJohn Marino __gthrw(pthread_mutex_timedlock)
158*e4b17023SJohn Marino #endif
159*e4b17023SJohn Marino __gthrw(pthread_mutex_unlock)
160*e4b17023SJohn Marino __gthrw(pthread_mutex_init)
161*e4b17023SJohn Marino __gthrw(pthread_mutex_destroy)
162*e4b17023SJohn Marino
163*e4b17023SJohn Marino __gthrw(pthread_cond_init)
164*e4b17023SJohn Marino __gthrw(pthread_cond_broadcast)
165*e4b17023SJohn Marino __gthrw(pthread_cond_signal)
166*e4b17023SJohn Marino __gthrw(pthread_cond_wait)
167*e4b17023SJohn Marino __gthrw(pthread_cond_timedwait)
168*e4b17023SJohn Marino __gthrw(pthread_cond_destroy)
169*e4b17023SJohn Marino #endif
170*e4b17023SJohn Marino
171*e4b17023SJohn Marino __gthrw(pthread_key_create)
172*e4b17023SJohn Marino __gthrw(pthread_key_delete)
173*e4b17023SJohn Marino __gthrw(pthread_mutexattr_init)
174*e4b17023SJohn Marino __gthrw(pthread_mutexattr_settype)
175*e4b17023SJohn Marino __gthrw(pthread_mutexattr_destroy)
176*e4b17023SJohn Marino
177*e4b17023SJohn Marino
178*e4b17023SJohn Marino #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
179*e4b17023SJohn Marino /* Objective-C. */
180*e4b17023SJohn Marino #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
181*e4b17023SJohn Marino __gthrw3(pthread_exit)
182*e4b17023SJohn Marino #else
183*e4b17023SJohn Marino __gthrw(pthread_exit)
184*e4b17023SJohn Marino #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
185*e4b17023SJohn Marino #ifdef _POSIX_PRIORITY_SCHEDULING
186*e4b17023SJohn Marino #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
187*e4b17023SJohn Marino __gthrw(sched_get_priority_max)
188*e4b17023SJohn Marino __gthrw(sched_get_priority_min)
189*e4b17023SJohn Marino #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
190*e4b17023SJohn Marino #endif /* _POSIX_PRIORITY_SCHEDULING */
191*e4b17023SJohn Marino __gthrw(pthread_attr_destroy)
192*e4b17023SJohn Marino __gthrw(pthread_attr_init)
193*e4b17023SJohn Marino __gthrw(pthread_attr_setdetachstate)
194*e4b17023SJohn Marino #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
195*e4b17023SJohn Marino __gthrw(pthread_getschedparam)
196*e4b17023SJohn Marino __gthrw(pthread_setschedparam)
197*e4b17023SJohn Marino #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
198*e4b17023SJohn Marino #endif /* _LIBOBJC || _LIBOBJC_WEAK */
199*e4b17023SJohn Marino
200*e4b17023SJohn Marino #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
201*e4b17023SJohn Marino
202*e4b17023SJohn Marino /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
203*e4b17023SJohn Marino -pthreads is not specified. The functions are dummies and most return an
204*e4b17023SJohn Marino error value. However pthread_once returns 0 without invoking the routine
205*e4b17023SJohn Marino it is passed so we cannot pretend that the interface is active if -pthreads
206*e4b17023SJohn Marino is not specified. On Solaris 2.5.1, the interface is not exposed at all so
207*e4b17023SJohn Marino we need to play the usual game with weak symbols. On Solaris 10 and up, a
208*e4b17023SJohn Marino working interface is always exposed. On FreeBSD 6 and later, libc also
209*e4b17023SJohn Marino exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
210*e4b17023SJohn Marino to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
211*e4b17023SJohn Marino which means the alternate __gthread_active_p below cannot be used there. */
212*e4b17023SJohn Marino
213*e4b17023SJohn Marino #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
214*e4b17023SJohn Marino
215*e4b17023SJohn Marino static volatile int __gthread_active = -1;
216*e4b17023SJohn Marino
217*e4b17023SJohn Marino static void
__gthread_trigger(void)218*e4b17023SJohn Marino __gthread_trigger (void)
219*e4b17023SJohn Marino {
220*e4b17023SJohn Marino __gthread_active = 1;
221*e4b17023SJohn Marino }
222*e4b17023SJohn Marino
223*e4b17023SJohn Marino static inline int
__gthread_active_p(void)224*e4b17023SJohn Marino __gthread_active_p (void)
225*e4b17023SJohn Marino {
226*e4b17023SJohn Marino static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
227*e4b17023SJohn Marino static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
228*e4b17023SJohn Marino
229*e4b17023SJohn Marino /* Avoid reading __gthread_active twice on the main code path. */
230*e4b17023SJohn Marino int __gthread_active_latest_value = __gthread_active;
231*e4b17023SJohn Marino
232*e4b17023SJohn Marino /* This test is not protected to avoid taking a lock on the main code
233*e4b17023SJohn Marino path so every update of __gthread_active in a threaded program must
234*e4b17023SJohn Marino be atomic with regard to the result of the test. */
235*e4b17023SJohn Marino if (__builtin_expect (__gthread_active_latest_value < 0, 0))
236*e4b17023SJohn Marino {
237*e4b17023SJohn Marino if (__gthrw_(pthread_once))
238*e4b17023SJohn Marino {
239*e4b17023SJohn Marino /* If this really is a threaded program, then we must ensure that
240*e4b17023SJohn Marino __gthread_active has been set to 1 before exiting this block. */
241*e4b17023SJohn Marino __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
242*e4b17023SJohn Marino __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
243*e4b17023SJohn Marino __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
244*e4b17023SJohn Marino }
245*e4b17023SJohn Marino
246*e4b17023SJohn Marino /* Make sure we'll never enter this block again. */
247*e4b17023SJohn Marino if (__gthread_active < 0)
248*e4b17023SJohn Marino __gthread_active = 0;
249*e4b17023SJohn Marino
250*e4b17023SJohn Marino __gthread_active_latest_value = __gthread_active;
251*e4b17023SJohn Marino }
252*e4b17023SJohn Marino
253*e4b17023SJohn Marino return __gthread_active_latest_value != 0;
254*e4b17023SJohn Marino }
255*e4b17023SJohn Marino
256*e4b17023SJohn Marino #else /* neither FreeBSD nor Solaris */
257*e4b17023SJohn Marino
258*e4b17023SJohn Marino static inline int
259*e4b17023SJohn Marino __gthread_active_p (void)
260*e4b17023SJohn Marino {
261*e4b17023SJohn Marino /* Android's C library does not provide pthread_cancel, check for
262*e4b17023SJohn Marino `pthread_create' instead. */
263*e4b17023SJohn Marino #ifndef __BIONIC__
264*e4b17023SJohn Marino static void *const __gthread_active_ptr
265*e4b17023SJohn Marino = __extension__ (void *) &__gthrw_(pthread_cancel);
266*e4b17023SJohn Marino #else
267*e4b17023SJohn Marino static void *const __gthread_active_ptr
268*e4b17023SJohn Marino = __extension__ (void *) &__gthrw_(pthread_create);
269*e4b17023SJohn Marino #endif
270*e4b17023SJohn Marino return __gthread_active_ptr != 0;
271*e4b17023SJohn Marino }
272*e4b17023SJohn Marino
273*e4b17023SJohn Marino #endif /* FreeBSD or Solaris */
274*e4b17023SJohn Marino
275*e4b17023SJohn Marino #else /* not SUPPORTS_WEAK */
276*e4b17023SJohn Marino
277*e4b17023SJohn Marino /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
278*e4b17023SJohn Marino calls in shared flavors of the HP-UX C library. Most of the stubs
279*e4b17023SJohn Marino have no functionality. The details are described in the "libc cumulative
280*e4b17023SJohn Marino patch" for each subversion of HP-UX 11. There are two special interfaces
281*e4b17023SJohn Marino provided for checking whether an application is linked to a shared pthread
282*e4b17023SJohn Marino library or not. However, these interfaces aren't available in early
283*e4b17023SJohn Marino libpthread libraries. We also need a test that works for archive
284*e4b17023SJohn Marino libraries. We can't use pthread_once as some libc versions call the
285*e4b17023SJohn Marino init function. We also can't use pthread_create or pthread_attr_init
286*e4b17023SJohn Marino as these create a thread and thereby prevent changing the default stack
287*e4b17023SJohn Marino size. The function pthread_default_stacksize_np is available in both
288*e4b17023SJohn Marino the archive and shared versions of libpthread. It can be used to
289*e4b17023SJohn Marino determine the default pthread stack size. There is a stub in some
290*e4b17023SJohn Marino shared libc versions which returns a zero size if pthreads are not
291*e4b17023SJohn Marino active. We provide an equivalent stub to handle cases where libc
292*e4b17023SJohn Marino doesn't provide one. */
293*e4b17023SJohn Marino
294*e4b17023SJohn Marino #if defined(__hppa__) && defined(__hpux__)
295*e4b17023SJohn Marino
296*e4b17023SJohn Marino static volatile int __gthread_active = -1;
297*e4b17023SJohn Marino
298*e4b17023SJohn Marino static inline int
299*e4b17023SJohn Marino __gthread_active_p (void)
300*e4b17023SJohn Marino {
301*e4b17023SJohn Marino /* Avoid reading __gthread_active twice on the main code path. */
302*e4b17023SJohn Marino int __gthread_active_latest_value = __gthread_active;
303*e4b17023SJohn Marino size_t __s;
304*e4b17023SJohn Marino
305*e4b17023SJohn Marino if (__builtin_expect (__gthread_active_latest_value < 0, 0))
306*e4b17023SJohn Marino {
307*e4b17023SJohn Marino pthread_default_stacksize_np (0, &__s);
308*e4b17023SJohn Marino __gthread_active = __s ? 1 : 0;
309*e4b17023SJohn Marino __gthread_active_latest_value = __gthread_active;
310*e4b17023SJohn Marino }
311*e4b17023SJohn Marino
312*e4b17023SJohn Marino return __gthread_active_latest_value != 0;
313*e4b17023SJohn Marino }
314*e4b17023SJohn Marino
315*e4b17023SJohn Marino #else /* not hppa-hpux */
316*e4b17023SJohn Marino
317*e4b17023SJohn Marino static inline int
318*e4b17023SJohn Marino __gthread_active_p (void)
319*e4b17023SJohn Marino {
320*e4b17023SJohn Marino return 1;
321*e4b17023SJohn Marino }
322*e4b17023SJohn Marino
323*e4b17023SJohn Marino #endif /* hppa-hpux */
324*e4b17023SJohn Marino
325*e4b17023SJohn Marino #endif /* SUPPORTS_WEAK */
326*e4b17023SJohn Marino
327*e4b17023SJohn Marino #ifdef _LIBOBJC
328*e4b17023SJohn Marino
329*e4b17023SJohn Marino /* This is the config.h file in libobjc/ */
330*e4b17023SJohn Marino #include <config.h>
331*e4b17023SJohn Marino
332*e4b17023SJohn Marino #ifdef HAVE_SCHED_H
333*e4b17023SJohn Marino # include <sched.h>
334*e4b17023SJohn Marino #endif
335*e4b17023SJohn Marino
336*e4b17023SJohn Marino /* Key structure for maintaining thread specific storage */
337*e4b17023SJohn Marino static pthread_key_t _objc_thread_storage;
338*e4b17023SJohn Marino static pthread_attr_t _objc_thread_attribs;
339*e4b17023SJohn Marino
340*e4b17023SJohn Marino /* Thread local storage for a single thread */
341*e4b17023SJohn Marino static void *thread_local_storage = NULL;
342*e4b17023SJohn Marino
343*e4b17023SJohn Marino /* Backend initialization functions */
344*e4b17023SJohn Marino
345*e4b17023SJohn Marino /* Initialize the threads subsystem. */
346*e4b17023SJohn Marino static inline int
__gthread_objc_init_thread_system(void)347*e4b17023SJohn Marino __gthread_objc_init_thread_system (void)
348*e4b17023SJohn Marino {
349*e4b17023SJohn Marino if (__gthread_active_p ())
350*e4b17023SJohn Marino {
351*e4b17023SJohn Marino /* Initialize the thread storage key. */
352*e4b17023SJohn Marino if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
353*e4b17023SJohn Marino {
354*e4b17023SJohn Marino /* The normal default detach state for threads is
355*e4b17023SJohn Marino * PTHREAD_CREATE_JOINABLE which causes threads to not die
356*e4b17023SJohn Marino * when you think they should. */
357*e4b17023SJohn Marino if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
358*e4b17023SJohn Marino && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
359*e4b17023SJohn Marino PTHREAD_CREATE_DETACHED) == 0)
360*e4b17023SJohn Marino return 0;
361*e4b17023SJohn Marino }
362*e4b17023SJohn Marino }
363*e4b17023SJohn Marino
364*e4b17023SJohn Marino return -1;
365*e4b17023SJohn Marino }
366*e4b17023SJohn Marino
367*e4b17023SJohn Marino /* Close the threads subsystem. */
368*e4b17023SJohn Marino static inline int
__gthread_objc_close_thread_system(void)369*e4b17023SJohn Marino __gthread_objc_close_thread_system (void)
370*e4b17023SJohn Marino {
371*e4b17023SJohn Marino if (__gthread_active_p ()
372*e4b17023SJohn Marino && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
373*e4b17023SJohn Marino && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
374*e4b17023SJohn Marino return 0;
375*e4b17023SJohn Marino
376*e4b17023SJohn Marino return -1;
377*e4b17023SJohn Marino }
378*e4b17023SJohn Marino
379*e4b17023SJohn Marino /* Backend thread functions */
380*e4b17023SJohn Marino
381*e4b17023SJohn Marino /* Create a new thread of execution. */
382*e4b17023SJohn Marino static inline objc_thread_t
__gthread_objc_thread_detach(void (* func)(void *),void * arg)383*e4b17023SJohn Marino __gthread_objc_thread_detach (void (*func)(void *), void *arg)
384*e4b17023SJohn Marino {
385*e4b17023SJohn Marino objc_thread_t thread_id;
386*e4b17023SJohn Marino pthread_t new_thread_handle;
387*e4b17023SJohn Marino
388*e4b17023SJohn Marino if (!__gthread_active_p ())
389*e4b17023SJohn Marino return NULL;
390*e4b17023SJohn Marino
391*e4b17023SJohn Marino if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs,
392*e4b17023SJohn Marino (void *) func, arg)))
393*e4b17023SJohn Marino thread_id = (objc_thread_t) new_thread_handle;
394*e4b17023SJohn Marino else
395*e4b17023SJohn Marino thread_id = NULL;
396*e4b17023SJohn Marino
397*e4b17023SJohn Marino return thread_id;
398*e4b17023SJohn Marino }
399*e4b17023SJohn Marino
400*e4b17023SJohn Marino /* Set the current thread's priority. */
401*e4b17023SJohn Marino static inline int
__gthread_objc_thread_set_priority(int priority)402*e4b17023SJohn Marino __gthread_objc_thread_set_priority (int priority)
403*e4b17023SJohn Marino {
404*e4b17023SJohn Marino if (!__gthread_active_p ())
405*e4b17023SJohn Marino return -1;
406*e4b17023SJohn Marino else
407*e4b17023SJohn Marino {
408*e4b17023SJohn Marino #ifdef _POSIX_PRIORITY_SCHEDULING
409*e4b17023SJohn Marino #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
410*e4b17023SJohn Marino pthread_t thread_id = __gthrw_(pthread_self) ();
411*e4b17023SJohn Marino int policy;
412*e4b17023SJohn Marino struct sched_param params;
413*e4b17023SJohn Marino int priority_min, priority_max;
414*e4b17023SJohn Marino
415*e4b17023SJohn Marino if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0)
416*e4b17023SJohn Marino {
417*e4b17023SJohn Marino if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
418*e4b17023SJohn Marino return -1;
419*e4b17023SJohn Marino
420*e4b17023SJohn Marino if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
421*e4b17023SJohn Marino return -1;
422*e4b17023SJohn Marino
423*e4b17023SJohn Marino if (priority > priority_max)
424*e4b17023SJohn Marino priority = priority_max;
425*e4b17023SJohn Marino else if (priority < priority_min)
426*e4b17023SJohn Marino priority = priority_min;
427*e4b17023SJohn Marino params.sched_priority = priority;
428*e4b17023SJohn Marino
429*e4b17023SJohn Marino /*
430*e4b17023SJohn Marino * The solaris 7 and several other man pages incorrectly state that
431*e4b17023SJohn Marino * this should be a pointer to policy but pthread.h is universally
432*e4b17023SJohn Marino * at odds with this.
433*e4b17023SJohn Marino */
434*e4b17023SJohn Marino if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0)
435*e4b17023SJohn Marino return 0;
436*e4b17023SJohn Marino }
437*e4b17023SJohn Marino #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
438*e4b17023SJohn Marino #endif /* _POSIX_PRIORITY_SCHEDULING */
439*e4b17023SJohn Marino return -1;
440*e4b17023SJohn Marino }
441*e4b17023SJohn Marino }
442*e4b17023SJohn Marino
443*e4b17023SJohn Marino /* Return the current thread's priority. */
444*e4b17023SJohn Marino static inline int
__gthread_objc_thread_get_priority(void)445*e4b17023SJohn Marino __gthread_objc_thread_get_priority (void)
446*e4b17023SJohn Marino {
447*e4b17023SJohn Marino #ifdef _POSIX_PRIORITY_SCHEDULING
448*e4b17023SJohn Marino #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
449*e4b17023SJohn Marino if (__gthread_active_p ())
450*e4b17023SJohn Marino {
451*e4b17023SJohn Marino int policy;
452*e4b17023SJohn Marino struct sched_param params;
453*e4b17023SJohn Marino
454*e4b17023SJohn Marino if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0)
455*e4b17023SJohn Marino return params.sched_priority;
456*e4b17023SJohn Marino else
457*e4b17023SJohn Marino return -1;
458*e4b17023SJohn Marino }
459*e4b17023SJohn Marino else
460*e4b17023SJohn Marino #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
461*e4b17023SJohn Marino #endif /* _POSIX_PRIORITY_SCHEDULING */
462*e4b17023SJohn Marino return OBJC_THREAD_INTERACTIVE_PRIORITY;
463*e4b17023SJohn Marino }
464*e4b17023SJohn Marino
465*e4b17023SJohn Marino /* Yield our process time to another thread. */
466*e4b17023SJohn Marino static inline void
__gthread_objc_thread_yield(void)467*e4b17023SJohn Marino __gthread_objc_thread_yield (void)
468*e4b17023SJohn Marino {
469*e4b17023SJohn Marino if (__gthread_active_p ())
470*e4b17023SJohn Marino __gthrw_(sched_yield) ();
471*e4b17023SJohn Marino }
472*e4b17023SJohn Marino
473*e4b17023SJohn Marino /* Terminate the current thread. */
474*e4b17023SJohn Marino static inline int
__gthread_objc_thread_exit(void)475*e4b17023SJohn Marino __gthread_objc_thread_exit (void)
476*e4b17023SJohn Marino {
477*e4b17023SJohn Marino if (__gthread_active_p ())
478*e4b17023SJohn Marino /* exit the thread */
479*e4b17023SJohn Marino __gthrw_(pthread_exit) (&__objc_thread_exit_status);
480*e4b17023SJohn Marino
481*e4b17023SJohn Marino /* Failed if we reached here */
482*e4b17023SJohn Marino return -1;
483*e4b17023SJohn Marino }
484*e4b17023SJohn Marino
485*e4b17023SJohn Marino /* Returns an integer value which uniquely describes a thread. */
486*e4b17023SJohn Marino static inline objc_thread_t
__gthread_objc_thread_id(void)487*e4b17023SJohn Marino __gthread_objc_thread_id (void)
488*e4b17023SJohn Marino {
489*e4b17023SJohn Marino if (__gthread_active_p ())
490*e4b17023SJohn Marino return (objc_thread_t) __gthrw_(pthread_self) ();
491*e4b17023SJohn Marino else
492*e4b17023SJohn Marino return (objc_thread_t) 1;
493*e4b17023SJohn Marino }
494*e4b17023SJohn Marino
495*e4b17023SJohn Marino /* Sets the thread's local storage pointer. */
496*e4b17023SJohn Marino static inline int
__gthread_objc_thread_set_data(void * value)497*e4b17023SJohn Marino __gthread_objc_thread_set_data (void *value)
498*e4b17023SJohn Marino {
499*e4b17023SJohn Marino if (__gthread_active_p ())
500*e4b17023SJohn Marino return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
501*e4b17023SJohn Marino else
502*e4b17023SJohn Marino {
503*e4b17023SJohn Marino thread_local_storage = value;
504*e4b17023SJohn Marino return 0;
505*e4b17023SJohn Marino }
506*e4b17023SJohn Marino }
507*e4b17023SJohn Marino
508*e4b17023SJohn Marino /* Returns the thread's local storage pointer. */
509*e4b17023SJohn Marino static inline void *
__gthread_objc_thread_get_data(void)510*e4b17023SJohn Marino __gthread_objc_thread_get_data (void)
511*e4b17023SJohn Marino {
512*e4b17023SJohn Marino if (__gthread_active_p ())
513*e4b17023SJohn Marino return __gthrw_(pthread_getspecific) (_objc_thread_storage);
514*e4b17023SJohn Marino else
515*e4b17023SJohn Marino return thread_local_storage;
516*e4b17023SJohn Marino }
517*e4b17023SJohn Marino
518*e4b17023SJohn Marino /* Backend mutex functions */
519*e4b17023SJohn Marino
520*e4b17023SJohn Marino /* Allocate a mutex. */
521*e4b17023SJohn Marino static inline int
__gthread_objc_mutex_allocate(objc_mutex_t mutex)522*e4b17023SJohn Marino __gthread_objc_mutex_allocate (objc_mutex_t mutex)
523*e4b17023SJohn Marino {
524*e4b17023SJohn Marino if (__gthread_active_p ())
525*e4b17023SJohn Marino {
526*e4b17023SJohn Marino mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
527*e4b17023SJohn Marino
528*e4b17023SJohn Marino if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
529*e4b17023SJohn Marino {
530*e4b17023SJohn Marino objc_free (mutex->backend);
531*e4b17023SJohn Marino mutex->backend = NULL;
532*e4b17023SJohn Marino return -1;
533*e4b17023SJohn Marino }
534*e4b17023SJohn Marino }
535*e4b17023SJohn Marino
536*e4b17023SJohn Marino return 0;
537*e4b17023SJohn Marino }
538*e4b17023SJohn Marino
539*e4b17023SJohn Marino /* Deallocate a mutex. */
540*e4b17023SJohn Marino static inline int
__gthread_objc_mutex_deallocate(objc_mutex_t mutex)541*e4b17023SJohn Marino __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
542*e4b17023SJohn Marino {
543*e4b17023SJohn Marino if (__gthread_active_p ())
544*e4b17023SJohn Marino {
545*e4b17023SJohn Marino int count;
546*e4b17023SJohn Marino
547*e4b17023SJohn Marino /*
548*e4b17023SJohn Marino * Posix Threads specifically require that the thread be unlocked
549*e4b17023SJohn Marino * for __gthrw_(pthread_mutex_destroy) to work.
550*e4b17023SJohn Marino */
551*e4b17023SJohn Marino
552*e4b17023SJohn Marino do
553*e4b17023SJohn Marino {
554*e4b17023SJohn Marino count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
555*e4b17023SJohn Marino if (count < 0)
556*e4b17023SJohn Marino return -1;
557*e4b17023SJohn Marino }
558*e4b17023SJohn Marino while (count);
559*e4b17023SJohn Marino
560*e4b17023SJohn Marino if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
561*e4b17023SJohn Marino return -1;
562*e4b17023SJohn Marino
563*e4b17023SJohn Marino objc_free (mutex->backend);
564*e4b17023SJohn Marino mutex->backend = NULL;
565*e4b17023SJohn Marino }
566*e4b17023SJohn Marino return 0;
567*e4b17023SJohn Marino }
568*e4b17023SJohn Marino
569*e4b17023SJohn Marino /* Grab a lock on a mutex. */
570*e4b17023SJohn Marino static inline int
__gthread_objc_mutex_lock(objc_mutex_t mutex)571*e4b17023SJohn Marino __gthread_objc_mutex_lock (objc_mutex_t mutex)
572*e4b17023SJohn Marino {
573*e4b17023SJohn Marino if (__gthread_active_p ()
574*e4b17023SJohn Marino && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
575*e4b17023SJohn Marino {
576*e4b17023SJohn Marino return -1;
577*e4b17023SJohn Marino }
578*e4b17023SJohn Marino
579*e4b17023SJohn Marino return 0;
580*e4b17023SJohn Marino }
581*e4b17023SJohn Marino
582*e4b17023SJohn Marino /* Try to grab a lock on a mutex. */
583*e4b17023SJohn Marino static inline int
__gthread_objc_mutex_trylock(objc_mutex_t mutex)584*e4b17023SJohn Marino __gthread_objc_mutex_trylock (objc_mutex_t mutex)
585*e4b17023SJohn Marino {
586*e4b17023SJohn Marino if (__gthread_active_p ()
587*e4b17023SJohn Marino && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
588*e4b17023SJohn Marino {
589*e4b17023SJohn Marino return -1;
590*e4b17023SJohn Marino }
591*e4b17023SJohn Marino
592*e4b17023SJohn Marino return 0;
593*e4b17023SJohn Marino }
594*e4b17023SJohn Marino
595*e4b17023SJohn Marino /* Unlock the mutex */
596*e4b17023SJohn Marino static inline int
__gthread_objc_mutex_unlock(objc_mutex_t mutex)597*e4b17023SJohn Marino __gthread_objc_mutex_unlock (objc_mutex_t mutex)
598*e4b17023SJohn Marino {
599*e4b17023SJohn Marino if (__gthread_active_p ()
600*e4b17023SJohn Marino && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
601*e4b17023SJohn Marino {
602*e4b17023SJohn Marino return -1;
603*e4b17023SJohn Marino }
604*e4b17023SJohn Marino
605*e4b17023SJohn Marino return 0;
606*e4b17023SJohn Marino }
607*e4b17023SJohn Marino
608*e4b17023SJohn Marino /* Backend condition mutex functions */
609*e4b17023SJohn Marino
610*e4b17023SJohn Marino /* Allocate a condition. */
611*e4b17023SJohn Marino static inline int
__gthread_objc_condition_allocate(objc_condition_t condition)612*e4b17023SJohn Marino __gthread_objc_condition_allocate (objc_condition_t condition)
613*e4b17023SJohn Marino {
614*e4b17023SJohn Marino if (__gthread_active_p ())
615*e4b17023SJohn Marino {
616*e4b17023SJohn Marino condition->backend = objc_malloc (sizeof (pthread_cond_t));
617*e4b17023SJohn Marino
618*e4b17023SJohn Marino if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
619*e4b17023SJohn Marino {
620*e4b17023SJohn Marino objc_free (condition->backend);
621*e4b17023SJohn Marino condition->backend = NULL;
622*e4b17023SJohn Marino return -1;
623*e4b17023SJohn Marino }
624*e4b17023SJohn Marino }
625*e4b17023SJohn Marino
626*e4b17023SJohn Marino return 0;
627*e4b17023SJohn Marino }
628*e4b17023SJohn Marino
629*e4b17023SJohn Marino /* Deallocate a condition. */
630*e4b17023SJohn Marino static inline int
__gthread_objc_condition_deallocate(objc_condition_t condition)631*e4b17023SJohn Marino __gthread_objc_condition_deallocate (objc_condition_t condition)
632*e4b17023SJohn Marino {
633*e4b17023SJohn Marino if (__gthread_active_p ())
634*e4b17023SJohn Marino {
635*e4b17023SJohn Marino if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
636*e4b17023SJohn Marino return -1;
637*e4b17023SJohn Marino
638*e4b17023SJohn Marino objc_free (condition->backend);
639*e4b17023SJohn Marino condition->backend = NULL;
640*e4b17023SJohn Marino }
641*e4b17023SJohn Marino return 0;
642*e4b17023SJohn Marino }
643*e4b17023SJohn Marino
644*e4b17023SJohn Marino /* Wait on the condition */
645*e4b17023SJohn Marino static inline int
__gthread_objc_condition_wait(objc_condition_t condition,objc_mutex_t mutex)646*e4b17023SJohn Marino __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
647*e4b17023SJohn Marino {
648*e4b17023SJohn Marino if (__gthread_active_p ())
649*e4b17023SJohn Marino return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
650*e4b17023SJohn Marino (pthread_mutex_t *) mutex->backend);
651*e4b17023SJohn Marino else
652*e4b17023SJohn Marino return 0;
653*e4b17023SJohn Marino }
654*e4b17023SJohn Marino
655*e4b17023SJohn Marino /* Wake up all threads waiting on this condition. */
656*e4b17023SJohn Marino static inline int
__gthread_objc_condition_broadcast(objc_condition_t condition)657*e4b17023SJohn Marino __gthread_objc_condition_broadcast (objc_condition_t condition)
658*e4b17023SJohn Marino {
659*e4b17023SJohn Marino if (__gthread_active_p ())
660*e4b17023SJohn Marino return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
661*e4b17023SJohn Marino else
662*e4b17023SJohn Marino return 0;
663*e4b17023SJohn Marino }
664*e4b17023SJohn Marino
665*e4b17023SJohn Marino /* Wake up one thread waiting on this condition. */
666*e4b17023SJohn Marino static inline int
__gthread_objc_condition_signal(objc_condition_t condition)667*e4b17023SJohn Marino __gthread_objc_condition_signal (objc_condition_t condition)
668*e4b17023SJohn Marino {
669*e4b17023SJohn Marino if (__gthread_active_p ())
670*e4b17023SJohn Marino return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
671*e4b17023SJohn Marino else
672*e4b17023SJohn Marino return 0;
673*e4b17023SJohn Marino }
674*e4b17023SJohn Marino
675*e4b17023SJohn Marino #else /* _LIBOBJC */
676*e4b17023SJohn Marino
677*e4b17023SJohn Marino static inline int
__gthread_create(__gthread_t * __threadid,void * (* __func)(void *),void * __args)678*e4b17023SJohn Marino __gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
679*e4b17023SJohn Marino void *__args)
680*e4b17023SJohn Marino {
681*e4b17023SJohn Marino return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
682*e4b17023SJohn Marino }
683*e4b17023SJohn Marino
684*e4b17023SJohn Marino static inline int
__gthread_join(__gthread_t __threadid,void ** __value_ptr)685*e4b17023SJohn Marino __gthread_join (__gthread_t __threadid, void **__value_ptr)
686*e4b17023SJohn Marino {
687*e4b17023SJohn Marino return __gthrw_(pthread_join) (__threadid, __value_ptr);
688*e4b17023SJohn Marino }
689*e4b17023SJohn Marino
690*e4b17023SJohn Marino static inline int
__gthread_detach(__gthread_t __threadid)691*e4b17023SJohn Marino __gthread_detach (__gthread_t __threadid)
692*e4b17023SJohn Marino {
693*e4b17023SJohn Marino return __gthrw_(pthread_detach) (__threadid);
694*e4b17023SJohn Marino }
695*e4b17023SJohn Marino
696*e4b17023SJohn Marino static inline int
__gthread_equal(__gthread_t __t1,__gthread_t __t2)697*e4b17023SJohn Marino __gthread_equal (__gthread_t __t1, __gthread_t __t2)
698*e4b17023SJohn Marino {
699*e4b17023SJohn Marino return __gthrw_(pthread_equal) (__t1, __t2);
700*e4b17023SJohn Marino }
701*e4b17023SJohn Marino
702*e4b17023SJohn Marino static inline __gthread_t
__gthread_self(void)703*e4b17023SJohn Marino __gthread_self (void)
704*e4b17023SJohn Marino {
705*e4b17023SJohn Marino return __gthrw_(pthread_self) ();
706*e4b17023SJohn Marino }
707*e4b17023SJohn Marino
708*e4b17023SJohn Marino static inline int
__gthread_yield(void)709*e4b17023SJohn Marino __gthread_yield (void)
710*e4b17023SJohn Marino {
711*e4b17023SJohn Marino return __gthrw_(sched_yield) ();
712*e4b17023SJohn Marino }
713*e4b17023SJohn Marino
714*e4b17023SJohn Marino static inline int
__gthread_once(__gthread_once_t * __once,void (* __func)(void))715*e4b17023SJohn Marino __gthread_once (__gthread_once_t *__once, void (*__func) (void))
716*e4b17023SJohn Marino {
717*e4b17023SJohn Marino if (__gthread_active_p ())
718*e4b17023SJohn Marino return __gthrw_(pthread_once) (__once, __func);
719*e4b17023SJohn Marino else
720*e4b17023SJohn Marino return -1;
721*e4b17023SJohn Marino }
722*e4b17023SJohn Marino
723*e4b17023SJohn Marino static inline int
__gthread_key_create(__gthread_key_t * __key,void (* __dtor)(void *))724*e4b17023SJohn Marino __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
725*e4b17023SJohn Marino {
726*e4b17023SJohn Marino return __gthrw_(pthread_key_create) (__key, __dtor);
727*e4b17023SJohn Marino }
728*e4b17023SJohn Marino
729*e4b17023SJohn Marino static inline int
__gthread_key_delete(__gthread_key_t __key)730*e4b17023SJohn Marino __gthread_key_delete (__gthread_key_t __key)
731*e4b17023SJohn Marino {
732*e4b17023SJohn Marino return __gthrw_(pthread_key_delete) (__key);
733*e4b17023SJohn Marino }
734*e4b17023SJohn Marino
735*e4b17023SJohn Marino static inline void *
__gthread_getspecific(__gthread_key_t __key)736*e4b17023SJohn Marino __gthread_getspecific (__gthread_key_t __key)
737*e4b17023SJohn Marino {
738*e4b17023SJohn Marino return __gthrw_(pthread_getspecific) (__key);
739*e4b17023SJohn Marino }
740*e4b17023SJohn Marino
741*e4b17023SJohn Marino static inline int
__gthread_setspecific(__gthread_key_t __key,const void * __ptr)742*e4b17023SJohn Marino __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
743*e4b17023SJohn Marino {
744*e4b17023SJohn Marino return __gthrw_(pthread_setspecific) (__key, __ptr);
745*e4b17023SJohn Marino }
746*e4b17023SJohn Marino
747*e4b17023SJohn Marino #ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
748*e4b17023SJohn Marino static inline void
__gthread_mutex_init_function(__gthread_mutex_t * __mutex)749*e4b17023SJohn Marino __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
750*e4b17023SJohn Marino {
751*e4b17023SJohn Marino if (__gthread_active_p ())
752*e4b17023SJohn Marino __gthrw_(pthread_mutex_init) (__mutex, NULL);
753*e4b17023SJohn Marino }
754*e4b17023SJohn Marino #endif
755*e4b17023SJohn Marino
756*e4b17023SJohn Marino static inline int
__gthread_mutex_destroy(__gthread_mutex_t * __mutex)757*e4b17023SJohn Marino __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
758*e4b17023SJohn Marino {
759*e4b17023SJohn Marino if (__gthread_active_p ())
760*e4b17023SJohn Marino return __gthrw_(pthread_mutex_destroy) (__mutex);
761*e4b17023SJohn Marino else
762*e4b17023SJohn Marino return 0;
763*e4b17023SJohn Marino }
764*e4b17023SJohn Marino
765*e4b17023SJohn Marino static inline int
__gthread_mutex_lock(__gthread_mutex_t * __mutex)766*e4b17023SJohn Marino __gthread_mutex_lock (__gthread_mutex_t *__mutex)
767*e4b17023SJohn Marino {
768*e4b17023SJohn Marino if (__gthread_active_p ())
769*e4b17023SJohn Marino return __gthrw_(pthread_mutex_lock) (__mutex);
770*e4b17023SJohn Marino else
771*e4b17023SJohn Marino return 0;
772*e4b17023SJohn Marino }
773*e4b17023SJohn Marino
774*e4b17023SJohn Marino static inline int
__gthread_mutex_trylock(__gthread_mutex_t * __mutex)775*e4b17023SJohn Marino __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
776*e4b17023SJohn Marino {
777*e4b17023SJohn Marino if (__gthread_active_p ())
778*e4b17023SJohn Marino return __gthrw_(pthread_mutex_trylock) (__mutex);
779*e4b17023SJohn Marino else
780*e4b17023SJohn Marino return 0;
781*e4b17023SJohn Marino }
782*e4b17023SJohn Marino
783*e4b17023SJohn Marino #if _GTHREAD_USE_MUTEX_TIMEDLOCK
784*e4b17023SJohn Marino static inline int
__gthread_mutex_timedlock(__gthread_mutex_t * __mutex,const __gthread_time_t * __abs_timeout)785*e4b17023SJohn Marino __gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
786*e4b17023SJohn Marino const __gthread_time_t *__abs_timeout)
787*e4b17023SJohn Marino {
788*e4b17023SJohn Marino if (__gthread_active_p ())
789*e4b17023SJohn Marino return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout);
790*e4b17023SJohn Marino else
791*e4b17023SJohn Marino return 0;
792*e4b17023SJohn Marino }
793*e4b17023SJohn Marino #endif
794*e4b17023SJohn Marino
795*e4b17023SJohn Marino static inline int
__gthread_mutex_unlock(__gthread_mutex_t * __mutex)796*e4b17023SJohn Marino __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
797*e4b17023SJohn Marino {
798*e4b17023SJohn Marino if (__gthread_active_p ())
799*e4b17023SJohn Marino return __gthrw_(pthread_mutex_unlock) (__mutex);
800*e4b17023SJohn Marino else
801*e4b17023SJohn Marino return 0;
802*e4b17023SJohn Marino }
803*e4b17023SJohn Marino
804*e4b17023SJohn Marino #if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \
805*e4b17023SJohn Marino || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
806*e4b17023SJohn Marino static inline int
__gthread_recursive_mutex_init_function(__gthread_recursive_mutex_t * __mutex)807*e4b17023SJohn Marino __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
808*e4b17023SJohn Marino {
809*e4b17023SJohn Marino if (__gthread_active_p ())
810*e4b17023SJohn Marino {
811*e4b17023SJohn Marino pthread_mutexattr_t __attr;
812*e4b17023SJohn Marino int __r;
813*e4b17023SJohn Marino
814*e4b17023SJohn Marino __r = __gthrw_(pthread_mutexattr_init) (&__attr);
815*e4b17023SJohn Marino if (!__r)
816*e4b17023SJohn Marino __r = __gthrw_(pthread_mutexattr_settype) (&__attr,
817*e4b17023SJohn Marino PTHREAD_MUTEX_RECURSIVE);
818*e4b17023SJohn Marino if (!__r)
819*e4b17023SJohn Marino __r = __gthrw_(pthread_mutex_init) (__mutex, &__attr);
820*e4b17023SJohn Marino if (!__r)
821*e4b17023SJohn Marino __r = __gthrw_(pthread_mutexattr_destroy) (&__attr);
822*e4b17023SJohn Marino return __r;
823*e4b17023SJohn Marino }
824*e4b17023SJohn Marino return 0;
825*e4b17023SJohn Marino }
826*e4b17023SJohn Marino #endif
827*e4b17023SJohn Marino
828*e4b17023SJohn Marino static inline int
__gthread_recursive_mutex_lock(__gthread_recursive_mutex_t * __mutex)829*e4b17023SJohn Marino __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
830*e4b17023SJohn Marino {
831*e4b17023SJohn Marino return __gthread_mutex_lock (__mutex);
832*e4b17023SJohn Marino }
833*e4b17023SJohn Marino
834*e4b17023SJohn Marino static inline int
__gthread_recursive_mutex_trylock(__gthread_recursive_mutex_t * __mutex)835*e4b17023SJohn Marino __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
836*e4b17023SJohn Marino {
837*e4b17023SJohn Marino return __gthread_mutex_trylock (__mutex);
838*e4b17023SJohn Marino }
839*e4b17023SJohn Marino
840*e4b17023SJohn Marino #if _GTHREAD_USE_MUTEX_TIMEDLOCK
841*e4b17023SJohn Marino static inline int
__gthread_recursive_mutex_timedlock(__gthread_recursive_mutex_t * __mutex,const __gthread_time_t * __abs_timeout)842*e4b17023SJohn Marino __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
843*e4b17023SJohn Marino const __gthread_time_t *__abs_timeout)
844*e4b17023SJohn Marino {
845*e4b17023SJohn Marino return __gthread_mutex_timedlock (__mutex, __abs_timeout);
846*e4b17023SJohn Marino }
847*e4b17023SJohn Marino #endif
848*e4b17023SJohn Marino
849*e4b17023SJohn Marino static inline int
__gthread_recursive_mutex_unlock(__gthread_recursive_mutex_t * __mutex)850*e4b17023SJohn Marino __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
851*e4b17023SJohn Marino {
852*e4b17023SJohn Marino return __gthread_mutex_unlock (__mutex);
853*e4b17023SJohn Marino }
854*e4b17023SJohn Marino
855*e4b17023SJohn Marino #ifdef _GTHREAD_USE_COND_INIT_FUNC
856*e4b17023SJohn Marino static inline void
__gthread_cond_init_function(__gthread_cond_t * __cond)857*e4b17023SJohn Marino __gthread_cond_init_function (__gthread_cond_t *__cond)
858*e4b17023SJohn Marino {
859*e4b17023SJohn Marino if (__gthread_active_p ())
860*e4b17023SJohn Marino __gthrw_(pthread_cond_init) (__cond, NULL);
861*e4b17023SJohn Marino }
862*e4b17023SJohn Marino #endif
863*e4b17023SJohn Marino
864*e4b17023SJohn Marino static inline int
__gthread_cond_broadcast(__gthread_cond_t * __cond)865*e4b17023SJohn Marino __gthread_cond_broadcast (__gthread_cond_t *__cond)
866*e4b17023SJohn Marino {
867*e4b17023SJohn Marino return __gthrw_(pthread_cond_broadcast) (__cond);
868*e4b17023SJohn Marino }
869*e4b17023SJohn Marino
870*e4b17023SJohn Marino static inline int
__gthread_cond_signal(__gthread_cond_t * __cond)871*e4b17023SJohn Marino __gthread_cond_signal (__gthread_cond_t *__cond)
872*e4b17023SJohn Marino {
873*e4b17023SJohn Marino return __gthrw_(pthread_cond_signal) (__cond);
874*e4b17023SJohn Marino }
875*e4b17023SJohn Marino
876*e4b17023SJohn Marino static inline int
__gthread_cond_wait(__gthread_cond_t * __cond,__gthread_mutex_t * __mutex)877*e4b17023SJohn Marino __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
878*e4b17023SJohn Marino {
879*e4b17023SJohn Marino return __gthrw_(pthread_cond_wait) (__cond, __mutex);
880*e4b17023SJohn Marino }
881*e4b17023SJohn Marino
882*e4b17023SJohn Marino static inline int
__gthread_cond_timedwait(__gthread_cond_t * __cond,__gthread_mutex_t * __mutex,const __gthread_time_t * __abs_timeout)883*e4b17023SJohn Marino __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
884*e4b17023SJohn Marino const __gthread_time_t *__abs_timeout)
885*e4b17023SJohn Marino {
886*e4b17023SJohn Marino return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
887*e4b17023SJohn Marino }
888*e4b17023SJohn Marino
889*e4b17023SJohn Marino static inline int
__gthread_cond_wait_recursive(__gthread_cond_t * __cond,__gthread_recursive_mutex_t * __mutex)890*e4b17023SJohn Marino __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
891*e4b17023SJohn Marino __gthread_recursive_mutex_t *__mutex)
892*e4b17023SJohn Marino {
893*e4b17023SJohn Marino return __gthread_cond_wait (__cond, __mutex);
894*e4b17023SJohn Marino }
895*e4b17023SJohn Marino
896*e4b17023SJohn Marino static inline int
__gthread_cond_timedwait_recursive(__gthread_cond_t * __cond,__gthread_recursive_mutex_t * __mutex,const __gthread_time_t * __abs_timeout)897*e4b17023SJohn Marino __gthread_cond_timedwait_recursive (__gthread_cond_t *__cond,
898*e4b17023SJohn Marino __gthread_recursive_mutex_t *__mutex,
899*e4b17023SJohn Marino const __gthread_time_t *__abs_timeout)
900*e4b17023SJohn Marino {
901*e4b17023SJohn Marino return __gthread_cond_timedwait (__cond, __mutex, __abs_timeout);
902*e4b17023SJohn Marino }
903*e4b17023SJohn Marino
904*e4b17023SJohn Marino static inline int
__gthread_cond_destroy(__gthread_cond_t * __cond)905*e4b17023SJohn Marino __gthread_cond_destroy (__gthread_cond_t* __cond)
906*e4b17023SJohn Marino {
907*e4b17023SJohn Marino return __gthrw_(pthread_cond_destroy) (__cond);
908*e4b17023SJohn Marino }
909*e4b17023SJohn Marino
910*e4b17023SJohn Marino #endif /* _LIBOBJC */
911*e4b17023SJohn Marino
912*e4b17023SJohn Marino #endif /* ! GCC_GTHR_POSIX_H */
913