xref: /openbsd/gnu/gcc/gcc/gthr-posix95.h (revision f4362409)
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, &params) == 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, &params) == 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, &params) == 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