1404b540aSrobert /* Threads compatibility routines for libgcc2 and libobjc. */
2404b540aSrobert /* Compile this one with gcc. */
3404b540aSrobert /* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4404b540aSrobert
5404b540aSrobert This file is part of GCC.
6404b540aSrobert
7404b540aSrobert GCC is free software; you can redistribute it and/or modify it under
8404b540aSrobert the terms of the GNU General Public License as published by the Free
9404b540aSrobert Software Foundation; either version 2, or (at your option) any later
10404b540aSrobert version.
11404b540aSrobert
12404b540aSrobert GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13404b540aSrobert WARRANTY; without even the implied warranty of MERCHANTABILITY or
14404b540aSrobert FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15404b540aSrobert for more details.
16404b540aSrobert
17404b540aSrobert You should have received a copy of the GNU General Public License
18404b540aSrobert along with GCC; see the file COPYING. If not, write to the Free
19404b540aSrobert Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20404b540aSrobert 02110-1301, USA. */
21404b540aSrobert
22404b540aSrobert /* As a special exception, if you link this library with other files,
23404b540aSrobert some of which are compiled with GCC, to produce an executable,
24404b540aSrobert this library does not by itself cause the resulting executable
25404b540aSrobert to be covered by the GNU General Public License.
26404b540aSrobert This exception does not however invalidate any other reasons why
27404b540aSrobert the executable file might be covered by the GNU General Public License. */
28404b540aSrobert
29404b540aSrobert #ifndef GCC_GTHR_POSIX_H
30404b540aSrobert #define GCC_GTHR_POSIX_H
31404b540aSrobert
32404b540aSrobert /* POSIX threads specific definitions.
33404b540aSrobert Easy, since the interface is just one-to-one mapping. */
34404b540aSrobert
35404b540aSrobert #define __GTHREADS 1
36404b540aSrobert
37404b540aSrobert /* Some implementations of <pthread.h> require this to be defined. */
38404b540aSrobert #ifndef _REENTRANT
39404b540aSrobert #define _REENTRANT 1
40404b540aSrobert #endif
41404b540aSrobert
42404b540aSrobert #include <pthread.h>
43404b540aSrobert #include <unistd.h>
44404b540aSrobert
45404b540aSrobert typedef pthread_key_t __gthread_key_t;
46404b540aSrobert typedef pthread_once_t __gthread_once_t;
47404b540aSrobert typedef pthread_mutex_t __gthread_mutex_t;
48404b540aSrobert
49404b540aSrobert typedef struct {
50404b540aSrobert long depth;
51404b540aSrobert pthread_t owner;
52404b540aSrobert pthread_mutex_t actual;
53404b540aSrobert } __gthread_recursive_mutex_t;
54404b540aSrobert
55404b540aSrobert #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
56404b540aSrobert #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
57404b540aSrobert #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
58404b540aSrobert
59404b540aSrobert #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
60404b540aSrobert # define __gthrw(name) \
61404b540aSrobert static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
62404b540aSrobert # define __gthrw_(name) __gthrw_ ## name
63404b540aSrobert #else
64404b540aSrobert # define __gthrw(name)
65404b540aSrobert # define __gthrw_(name) name
66404b540aSrobert #endif
67404b540aSrobert
68404b540aSrobert __gthrw(pthread_once)
69404b540aSrobert __gthrw(pthread_key_create)
70404b540aSrobert __gthrw(pthread_key_delete)
71404b540aSrobert __gthrw(pthread_getspecific)
72404b540aSrobert __gthrw(pthread_setspecific)
73404b540aSrobert __gthrw(pthread_create)
74404b540aSrobert __gthrw(pthread_cancel)
75404b540aSrobert __gthrw(pthread_self)
76404b540aSrobert
77404b540aSrobert __gthrw(pthread_mutex_lock)
78404b540aSrobert __gthrw(pthread_mutex_trylock)
79404b540aSrobert __gthrw(pthread_mutex_unlock)
80404b540aSrobert __gthrw(pthread_mutexattr_init)
81404b540aSrobert __gthrw(pthread_mutexattr_destroy)
82404b540aSrobert
83404b540aSrobert __gthrw(pthread_mutex_init)
84404b540aSrobert
85404b540aSrobert #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
86404b540aSrobert /* Objective-C. */
87404b540aSrobert __gthrw(pthread_cond_broadcast)
88404b540aSrobert __gthrw(pthread_cond_destroy)
89404b540aSrobert __gthrw(pthread_cond_init)
90404b540aSrobert __gthrw(pthread_cond_signal)
91404b540aSrobert __gthrw(pthread_cond_wait)
92404b540aSrobert __gthrw(pthread_exit)
93404b540aSrobert __gthrw(pthread_mutex_destroy)
94*f4362409Smatthew #if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING > 0)
95*f4362409Smatthew #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
96404b540aSrobert __gthrw(sched_get_priority_max)
97404b540aSrobert __gthrw(sched_get_priority_min)
98404b540aSrobert #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
99404b540aSrobert #endif /* _POSIX_PRIORITY_SCHEDULING */
100404b540aSrobert __gthrw(sched_yield)
101404b540aSrobert __gthrw(pthread_attr_destroy)
102404b540aSrobert __gthrw(pthread_attr_init)
103404b540aSrobert __gthrw(pthread_attr_setdetachstate)
104*f4362409Smatthew #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
105404b540aSrobert __gthrw(pthread_getschedparam)
106404b540aSrobert __gthrw(pthread_setschedparam)
107404b540aSrobert #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
108404b540aSrobert #endif /* _LIBOBJC || _LIBOBJC_WEAK */
109404b540aSrobert
110404b540aSrobert #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
111404b540aSrobert
112404b540aSrobert /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
113404b540aSrobert -pthreads is not specified. The functions are dummies and most return an
114404b540aSrobert error value. However pthread_once returns 0 without invoking the routine
115404b540aSrobert it is passed so we cannot pretend that the interface is active if -pthreads
116404b540aSrobert is not specified. On Solaris 2.5.1, the interface is not exposed at all so
117404b540aSrobert we need to play the usual game with weak symbols. On Solaris 10 and up, a
118404b540aSrobert working interface is always exposed. */
119404b540aSrobert
120404b540aSrobert #if defined(__sun) && defined(__svr4__)
121404b540aSrobert
122404b540aSrobert static volatile int __gthread_active = -1;
123404b540aSrobert
124404b540aSrobert static void
__gthread_trigger(void)125404b540aSrobert __gthread_trigger (void)
126404b540aSrobert {
127404b540aSrobert __gthread_active = 1;
128404b540aSrobert }
129404b540aSrobert
130404b540aSrobert static inline int
__gthread_active_p(void)131404b540aSrobert __gthread_active_p (void)
132404b540aSrobert {
133404b540aSrobert static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
134404b540aSrobert static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
135404b540aSrobert
136404b540aSrobert /* Avoid reading __gthread_active twice on the main code path. */
137404b540aSrobert int __gthread_active_latest_value = __gthread_active;
138404b540aSrobert
139404b540aSrobert /* This test is not protected to avoid taking a lock on the main code
140404b540aSrobert path so every update of __gthread_active in a threaded program must
141404b540aSrobert be atomic with regard to the result of the test. */
142404b540aSrobert if (__builtin_expect (__gthread_active_latest_value < 0, 0))
143404b540aSrobert {
144404b540aSrobert if (__gthrw_(pthread_once))
145404b540aSrobert {
146404b540aSrobert /* If this really is a threaded program, then we must ensure that
147404b540aSrobert __gthread_active has been set to 1 before exiting this block. */
148404b540aSrobert __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
149404b540aSrobert __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
150404b540aSrobert __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
151404b540aSrobert }
152404b540aSrobert
153404b540aSrobert /* Make sure we'll never enter this block again. */
154404b540aSrobert if (__gthread_active < 0)
155404b540aSrobert __gthread_active = 0;
156404b540aSrobert
157404b540aSrobert __gthread_active_latest_value = __gthread_active;
158404b540aSrobert }
159404b540aSrobert
160404b540aSrobert return __gthread_active_latest_value != 0;
161404b540aSrobert }
162404b540aSrobert
163404b540aSrobert #else /* not Solaris */
164404b540aSrobert
165404b540aSrobert static inline int
166404b540aSrobert __gthread_active_p (void)
167404b540aSrobert {
168404b540aSrobert static void *const __gthread_active_ptr
169404b540aSrobert = __extension__ (void *) &__gthrw_(pthread_cancel);
170404b540aSrobert return __gthread_active_ptr != 0;
171404b540aSrobert }
172404b540aSrobert
173404b540aSrobert #endif /* Solaris */
174404b540aSrobert
175404b540aSrobert #else /* not SUPPORTS_WEAK */
176404b540aSrobert
177404b540aSrobert static inline int
178404b540aSrobert __gthread_active_p (void)
179404b540aSrobert {
180404b540aSrobert return 1;
181404b540aSrobert }
182404b540aSrobert
183404b540aSrobert #endif /* SUPPORTS_WEAK */
184404b540aSrobert
185404b540aSrobert #ifdef _LIBOBJC
186404b540aSrobert
187404b540aSrobert /* This is the config.h file in libobjc/ */
188404b540aSrobert #include <config.h>
189404b540aSrobert
190404b540aSrobert #ifdef HAVE_SCHED_H
191404b540aSrobert # include <sched.h>
192404b540aSrobert #endif
193404b540aSrobert
194404b540aSrobert /* Key structure for maintaining thread specific storage */
195404b540aSrobert static pthread_key_t _objc_thread_storage;
196404b540aSrobert static pthread_attr_t _objc_thread_attribs;
197404b540aSrobert
198404b540aSrobert /* Thread local storage for a single thread */
199404b540aSrobert static void *thread_local_storage = NULL;
200404b540aSrobert
201404b540aSrobert /* Backend initialization functions */
202404b540aSrobert
203404b540aSrobert /* Initialize the threads subsystem. */
204404b540aSrobert static inline int
__gthread_objc_init_thread_system(void)205404b540aSrobert __gthread_objc_init_thread_system (void)
206404b540aSrobert {
207404b540aSrobert if (__gthread_active_p ())
208404b540aSrobert {
209404b540aSrobert /* Initialize the thread storage key. */
210404b540aSrobert if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
211404b540aSrobert {
212404b540aSrobert /* The normal default detach state for threads is
213404b540aSrobert * PTHREAD_CREATE_JOINABLE which causes threads to not die
214404b540aSrobert * when you think they should. */
215404b540aSrobert if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
216404b540aSrobert && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
217404b540aSrobert PTHREAD_CREATE_DETACHED) == 0)
218404b540aSrobert return 0;
219404b540aSrobert }
220404b540aSrobert }
221404b540aSrobert
222404b540aSrobert return -1;
223404b540aSrobert }
224404b540aSrobert
225404b540aSrobert /* Close the threads subsystem. */
226404b540aSrobert static inline int
__gthread_objc_close_thread_system(void)227404b540aSrobert __gthread_objc_close_thread_system (void)
228404b540aSrobert {
229404b540aSrobert if (__gthread_active_p ()
230404b540aSrobert && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
231404b540aSrobert && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
232404b540aSrobert return 0;
233404b540aSrobert
234404b540aSrobert return -1;
235404b540aSrobert }
236404b540aSrobert
237404b540aSrobert /* Backend thread functions */
238404b540aSrobert
239404b540aSrobert /* Create a new thread of execution. */
240404b540aSrobert static inline objc_thread_t
__gthread_objc_thread_detach(void (* func)(void *),void * arg)241404b540aSrobert __gthread_objc_thread_detach (void (*func)(void *), void *arg)
242404b540aSrobert {
243404b540aSrobert objc_thread_t thread_id;
244404b540aSrobert pthread_t new_thread_handle;
245404b540aSrobert
246404b540aSrobert if (!__gthread_active_p ())
247404b540aSrobert return NULL;
248404b540aSrobert
249404b540aSrobert if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
250404b540aSrobert thread_id = (objc_thread_t) new_thread_handle;
251404b540aSrobert else
252404b540aSrobert thread_id = NULL;
253404b540aSrobert
254404b540aSrobert return thread_id;
255404b540aSrobert }
256404b540aSrobert
257404b540aSrobert /* Set the current thread's priority. */
258404b540aSrobert static inline int
__gthread_objc_thread_set_priority(int priority)259404b540aSrobert __gthread_objc_thread_set_priority (int priority)
260404b540aSrobert {
261404b540aSrobert if (!__gthread_active_p ())
262404b540aSrobert return -1;
263404b540aSrobert else
264404b540aSrobert {
265*f4362409Smatthew #if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING > 0)
266*f4362409Smatthew #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
267404b540aSrobert pthread_t thread_id = __gthrw_(pthread_self) ();
268404b540aSrobert int policy;
269404b540aSrobert struct sched_param params;
270404b540aSrobert int priority_min, priority_max;
271404b540aSrobert
272404b540aSrobert if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0)
273404b540aSrobert {
274404b540aSrobert if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
275404b540aSrobert return -1;
276404b540aSrobert
277404b540aSrobert if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
278404b540aSrobert return -1;
279404b540aSrobert
280404b540aSrobert if (priority > priority_max)
281404b540aSrobert priority = priority_max;
282404b540aSrobert else if (priority < priority_min)
283404b540aSrobert priority = priority_min;
284404b540aSrobert params.sched_priority = priority;
285404b540aSrobert
286404b540aSrobert /*
287404b540aSrobert * The solaris 7 and several other man pages incorrectly state that
288404b540aSrobert * this should be a pointer to policy but pthread.h is universally
289404b540aSrobert * at odds with this.
290404b540aSrobert */
291404b540aSrobert if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0)
292404b540aSrobert return 0;
293404b540aSrobert }
294404b540aSrobert #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
295404b540aSrobert #endif /* _POSIX_PRIORITY_SCHEDULING */
296404b540aSrobert return -1;
297404b540aSrobert }
298404b540aSrobert }
299404b540aSrobert
300404b540aSrobert /* Return the current thread's priority. */
301404b540aSrobert static inline int
__gthread_objc_thread_get_priority(void)302404b540aSrobert __gthread_objc_thread_get_priority (void)
303404b540aSrobert {
304*f4362409Smatthew #if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING > 0)
305*f4362409Smatthew #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
306404b540aSrobert if (__gthread_active_p ())
307404b540aSrobert {
308404b540aSrobert int policy;
309404b540aSrobert struct sched_param params;
310404b540aSrobert
311404b540aSrobert if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0)
312404b540aSrobert return params.sched_priority;
313404b540aSrobert else
314404b540aSrobert return -1;
315404b540aSrobert }
316404b540aSrobert else
317404b540aSrobert #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
318404b540aSrobert #endif /* _POSIX_PRIORITY_SCHEDULING */
319404b540aSrobert return OBJC_THREAD_INTERACTIVE_PRIORITY;
320404b540aSrobert }
321404b540aSrobert
322404b540aSrobert /* Yield our process time to another thread. */
323404b540aSrobert static inline void
__gthread_objc_thread_yield(void)324404b540aSrobert __gthread_objc_thread_yield (void)
325404b540aSrobert {
326404b540aSrobert if (__gthread_active_p ())
327404b540aSrobert __gthrw_(sched_yield) ();
328404b540aSrobert }
329404b540aSrobert
330404b540aSrobert /* Terminate the current thread. */
331404b540aSrobert static inline int
__gthread_objc_thread_exit(void)332404b540aSrobert __gthread_objc_thread_exit (void)
333404b540aSrobert {
334404b540aSrobert if (__gthread_active_p ())
335404b540aSrobert /* exit the thread */
336404b540aSrobert __gthrw_(pthread_exit) (&__objc_thread_exit_status);
337404b540aSrobert
338404b540aSrobert /* Failed if we reached here */
339404b540aSrobert return -1;
340404b540aSrobert }
341404b540aSrobert
342404b540aSrobert /* Returns an integer value which uniquely describes a thread. */
343404b540aSrobert static inline objc_thread_t
__gthread_objc_thread_id(void)344404b540aSrobert __gthread_objc_thread_id (void)
345404b540aSrobert {
346404b540aSrobert if (__gthread_active_p ())
347404b540aSrobert return (objc_thread_t) __gthrw_(pthread_self) ();
348404b540aSrobert else
349404b540aSrobert return (objc_thread_t) 1;
350404b540aSrobert }
351404b540aSrobert
352404b540aSrobert /* Sets the thread's local storage pointer. */
353404b540aSrobert static inline int
__gthread_objc_thread_set_data(void * value)354404b540aSrobert __gthread_objc_thread_set_data (void *value)
355404b540aSrobert {
356404b540aSrobert if (__gthread_active_p ())
357404b540aSrobert return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
358404b540aSrobert else
359404b540aSrobert {
360404b540aSrobert thread_local_storage = value;
361404b540aSrobert return 0;
362404b540aSrobert }
363404b540aSrobert }
364404b540aSrobert
365404b540aSrobert /* Returns the thread's local storage pointer. */
366404b540aSrobert static inline void *
__gthread_objc_thread_get_data(void)367404b540aSrobert __gthread_objc_thread_get_data (void)
368404b540aSrobert {
369404b540aSrobert if (__gthread_active_p ())
370404b540aSrobert return __gthrw_(pthread_getspecific) (_objc_thread_storage);
371404b540aSrobert else
372404b540aSrobert return thread_local_storage;
373404b540aSrobert }
374404b540aSrobert
375404b540aSrobert /* Backend mutex functions */
376404b540aSrobert
377404b540aSrobert /* Allocate a mutex. */
378404b540aSrobert static inline int
__gthread_objc_mutex_allocate(objc_mutex_t mutex)379404b540aSrobert __gthread_objc_mutex_allocate (objc_mutex_t mutex)
380404b540aSrobert {
381404b540aSrobert if (__gthread_active_p ())
382404b540aSrobert {
383404b540aSrobert mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
384404b540aSrobert
385404b540aSrobert if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
386404b540aSrobert {
387404b540aSrobert objc_free (mutex->backend);
388404b540aSrobert mutex->backend = NULL;
389404b540aSrobert return -1;
390404b540aSrobert }
391404b540aSrobert }
392404b540aSrobert
393404b540aSrobert return 0;
394404b540aSrobert }
395404b540aSrobert
396404b540aSrobert /* Deallocate a mutex. */
397404b540aSrobert static inline int
__gthread_objc_mutex_deallocate(objc_mutex_t mutex)398404b540aSrobert __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
399404b540aSrobert {
400404b540aSrobert if (__gthread_active_p ())
401404b540aSrobert {
402404b540aSrobert int count;
403404b540aSrobert
404404b540aSrobert /*
405404b540aSrobert * Posix Threads specifically require that the thread be unlocked
406404b540aSrobert * for __gthrw_(pthread_mutex_destroy) to work.
407404b540aSrobert */
408404b540aSrobert
409404b540aSrobert do
410404b540aSrobert {
411404b540aSrobert count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
412404b540aSrobert if (count < 0)
413404b540aSrobert return -1;
414404b540aSrobert }
415404b540aSrobert while (count);
416404b540aSrobert
417404b540aSrobert if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
418404b540aSrobert return -1;
419404b540aSrobert
420404b540aSrobert objc_free (mutex->backend);
421404b540aSrobert mutex->backend = NULL;
422404b540aSrobert }
423404b540aSrobert return 0;
424404b540aSrobert }
425404b540aSrobert
426404b540aSrobert /* Grab a lock on a mutex. */
427404b540aSrobert static inline int
__gthread_objc_mutex_lock(objc_mutex_t mutex)428404b540aSrobert __gthread_objc_mutex_lock (objc_mutex_t mutex)
429404b540aSrobert {
430404b540aSrobert if (__gthread_active_p ()
431404b540aSrobert && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
432404b540aSrobert {
433404b540aSrobert return -1;
434404b540aSrobert }
435404b540aSrobert
436404b540aSrobert return 0;
437404b540aSrobert }
438404b540aSrobert
439404b540aSrobert /* Try to grab a lock on a mutex. */
440404b540aSrobert static inline int
__gthread_objc_mutex_trylock(objc_mutex_t mutex)441404b540aSrobert __gthread_objc_mutex_trylock (objc_mutex_t mutex)
442404b540aSrobert {
443404b540aSrobert if (__gthread_active_p ()
444404b540aSrobert && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
445404b540aSrobert {
446404b540aSrobert return -1;
447404b540aSrobert }
448404b540aSrobert
449404b540aSrobert return 0;
450404b540aSrobert }
451404b540aSrobert
452404b540aSrobert /* Unlock the mutex */
453404b540aSrobert static inline int
__gthread_objc_mutex_unlock(objc_mutex_t mutex)454404b540aSrobert __gthread_objc_mutex_unlock (objc_mutex_t mutex)
455404b540aSrobert {
456404b540aSrobert if (__gthread_active_p ()
457404b540aSrobert && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
458404b540aSrobert {
459404b540aSrobert return -1;
460404b540aSrobert }
461404b540aSrobert
462404b540aSrobert return 0;
463404b540aSrobert }
464404b540aSrobert
465404b540aSrobert /* Backend condition mutex functions */
466404b540aSrobert
467404b540aSrobert /* Allocate a condition. */
468404b540aSrobert static inline int
__gthread_objc_condition_allocate(objc_condition_t condition)469404b540aSrobert __gthread_objc_condition_allocate (objc_condition_t condition)
470404b540aSrobert {
471404b540aSrobert if (__gthread_active_p ())
472404b540aSrobert {
473404b540aSrobert condition->backend = objc_malloc (sizeof (pthread_cond_t));
474404b540aSrobert
475404b540aSrobert if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
476404b540aSrobert {
477404b540aSrobert objc_free (condition->backend);
478404b540aSrobert condition->backend = NULL;
479404b540aSrobert return -1;
480404b540aSrobert }
481404b540aSrobert }
482404b540aSrobert
483404b540aSrobert return 0;
484404b540aSrobert }
485404b540aSrobert
486404b540aSrobert /* Deallocate a condition. */
487404b540aSrobert static inline int
__gthread_objc_condition_deallocate(objc_condition_t condition)488404b540aSrobert __gthread_objc_condition_deallocate (objc_condition_t condition)
489404b540aSrobert {
490404b540aSrobert if (__gthread_active_p ())
491404b540aSrobert {
492404b540aSrobert if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
493404b540aSrobert return -1;
494404b540aSrobert
495404b540aSrobert objc_free (condition->backend);
496404b540aSrobert condition->backend = NULL;
497404b540aSrobert }
498404b540aSrobert return 0;
499404b540aSrobert }
500404b540aSrobert
501404b540aSrobert /* Wait on the condition */
502404b540aSrobert static inline int
__gthread_objc_condition_wait(objc_condition_t condition,objc_mutex_t mutex)503404b540aSrobert __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
504404b540aSrobert {
505404b540aSrobert if (__gthread_active_p ())
506404b540aSrobert return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
507404b540aSrobert (pthread_mutex_t *) mutex->backend);
508404b540aSrobert else
509404b540aSrobert return 0;
510404b540aSrobert }
511404b540aSrobert
512404b540aSrobert /* Wake up all threads waiting on this condition. */
513404b540aSrobert static inline int
__gthread_objc_condition_broadcast(objc_condition_t condition)514404b540aSrobert __gthread_objc_condition_broadcast (objc_condition_t condition)
515404b540aSrobert {
516404b540aSrobert if (__gthread_active_p ())
517404b540aSrobert return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
518404b540aSrobert else
519404b540aSrobert return 0;
520404b540aSrobert }
521404b540aSrobert
522404b540aSrobert /* Wake up one thread waiting on this condition. */
523404b540aSrobert static inline int
__gthread_objc_condition_signal(objc_condition_t condition)524404b540aSrobert __gthread_objc_condition_signal (objc_condition_t condition)
525404b540aSrobert {
526404b540aSrobert if (__gthread_active_p ())
527404b540aSrobert return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
528404b540aSrobert else
529404b540aSrobert return 0;
530404b540aSrobert }
531404b540aSrobert
532404b540aSrobert #else /* _LIBOBJC */
533404b540aSrobert
534404b540aSrobert static inline int
__gthread_once(__gthread_once_t * once,void (* func)(void))535404b540aSrobert __gthread_once (__gthread_once_t *once, void (*func) (void))
536404b540aSrobert {
537404b540aSrobert if (__gthread_active_p ())
538404b540aSrobert return __gthrw_(pthread_once) (once, func);
539404b540aSrobert else
540404b540aSrobert return -1;
541404b540aSrobert }
542404b540aSrobert
543404b540aSrobert static inline int
__gthread_key_create(__gthread_key_t * key,void (* dtor)(void *))544404b540aSrobert __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
545404b540aSrobert {
546404b540aSrobert return __gthrw_(pthread_key_create) (key, dtor);
547404b540aSrobert }
548404b540aSrobert
549404b540aSrobert static inline int
__gthread_key_delete(__gthread_key_t key)550404b540aSrobert __gthread_key_delete (__gthread_key_t key)
551404b540aSrobert {
552404b540aSrobert return __gthrw_(pthread_key_delete) (key);
553404b540aSrobert }
554404b540aSrobert
555404b540aSrobert static inline void *
__gthread_getspecific(__gthread_key_t key)556404b540aSrobert __gthread_getspecific (__gthread_key_t key)
557404b540aSrobert {
558404b540aSrobert return __gthrw_(pthread_getspecific) (key);
559404b540aSrobert }
560404b540aSrobert
561404b540aSrobert static inline int
__gthread_setspecific(__gthread_key_t key,const void * ptr)562404b540aSrobert __gthread_setspecific (__gthread_key_t key, const void *ptr)
563404b540aSrobert {
564404b540aSrobert return __gthrw_(pthread_setspecific) (key, ptr);
565404b540aSrobert }
566404b540aSrobert
567404b540aSrobert static inline int
__gthread_mutex_lock(__gthread_mutex_t * mutex)568404b540aSrobert __gthread_mutex_lock (__gthread_mutex_t *mutex)
569404b540aSrobert {
570404b540aSrobert if (__gthread_active_p ())
571404b540aSrobert return __gthrw_(pthread_mutex_lock) (mutex);
572404b540aSrobert else
573404b540aSrobert return 0;
574404b540aSrobert }
575404b540aSrobert
576404b540aSrobert static inline int
__gthread_mutex_trylock(__gthread_mutex_t * mutex)577404b540aSrobert __gthread_mutex_trylock (__gthread_mutex_t *mutex)
578404b540aSrobert {
579404b540aSrobert if (__gthread_active_p ())
580404b540aSrobert return __gthrw_(pthread_mutex_trylock) (mutex);
581404b540aSrobert else
582404b540aSrobert return 0;
583404b540aSrobert }
584404b540aSrobert
585404b540aSrobert static inline int
__gthread_mutex_unlock(__gthread_mutex_t * mutex)586404b540aSrobert __gthread_mutex_unlock (__gthread_mutex_t *mutex)
587404b540aSrobert {
588404b540aSrobert if (__gthread_active_p ())
589404b540aSrobert return __gthrw_(pthread_mutex_unlock) (mutex);
590404b540aSrobert else
591404b540aSrobert return 0;
592404b540aSrobert }
593404b540aSrobert
594404b540aSrobert static inline int
__gthread_recursive_mutex_init_function(__gthread_recursive_mutex_t * mutex)595404b540aSrobert __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
596404b540aSrobert {
597404b540aSrobert mutex->depth = 0;
598404b540aSrobert mutex->owner = (pthread_t) 0;
599404b540aSrobert return __gthrw_(pthread_mutex_init) (&mutex->actual, NULL);
600404b540aSrobert }
601404b540aSrobert
602404b540aSrobert static inline int
__gthread_recursive_mutex_lock(__gthread_recursive_mutex_t * mutex)603404b540aSrobert __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
604404b540aSrobert {
605404b540aSrobert if (__gthread_active_p ())
606404b540aSrobert {
607404b540aSrobert pthread_t me = __gthrw_(pthread_self) ();
608404b540aSrobert
609404b540aSrobert if (mutex->owner != me)
610404b540aSrobert {
611404b540aSrobert __gthrw_(pthread_mutex_lock) (&mutex->actual);
612404b540aSrobert mutex->owner = me;
613404b540aSrobert }
614404b540aSrobert
615404b540aSrobert mutex->depth++;
616404b540aSrobert }
617404b540aSrobert return 0;
618404b540aSrobert }
619404b540aSrobert
620404b540aSrobert static inline int
__gthread_recursive_mutex_trylock(__gthread_recursive_mutex_t * mutex)621404b540aSrobert __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
622404b540aSrobert {
623404b540aSrobert if (__gthread_active_p ())
624404b540aSrobert {
625404b540aSrobert pthread_t me = __gthrw_(pthread_self) ();
626404b540aSrobert
627404b540aSrobert if (mutex->owner != me)
628404b540aSrobert {
629404b540aSrobert if (__gthrw_(pthread_mutex_trylock) (&mutex->actual))
630404b540aSrobert return 1;
631404b540aSrobert mutex->owner = me;
632404b540aSrobert }
633404b540aSrobert
634404b540aSrobert mutex->depth++;
635404b540aSrobert }
636404b540aSrobert return 0;
637404b540aSrobert }
638404b540aSrobert
639404b540aSrobert static inline int
__gthread_recursive_mutex_unlock(__gthread_recursive_mutex_t * mutex)640404b540aSrobert __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
641404b540aSrobert {
642404b540aSrobert if (__gthread_active_p ())
643404b540aSrobert {
644404b540aSrobert if (--mutex->depth == 0)
645404b540aSrobert {
646404b540aSrobert mutex->owner = (pthread_t) 0;
647404b540aSrobert __gthrw_(pthread_mutex_unlock) (&mutex->actual);
648404b540aSrobert }
649404b540aSrobert }
650404b540aSrobert return 0;
651404b540aSrobert }
652404b540aSrobert
653404b540aSrobert #endif /* _LIBOBJC */
654404b540aSrobert
655404b540aSrobert #endif /* ! GCC_GTHR_POSIX_H */
656