190075Sobrien/* Threads compatibility routines for libgcc2 and libobjc.  */
250397Sobrien/* Compile this one with gcc.  */
3171825Skan/* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4132718Skan   Free Software Foundation, Inc.
550397Sobrien
690075SobrienThis file is part of GCC.
750397Sobrien
890075SobrienGCC is free software; you can redistribute it and/or modify it under
990075Sobrienthe terms of the GNU General Public License as published by the Free
1090075SobrienSoftware Foundation; either version 2, or (at your option) any later
1190075Sobrienversion.
1250397Sobrien
1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1590075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1690075Sobrienfor more details.
1750397Sobrien
1850397SobrienYou should have received a copy of the GNU General Public License
1990075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
2250397Sobrien
2350397Sobrien/* As a special exception, if you link this library with other files,
2450397Sobrien   some of which are compiled with GCC, to produce an executable,
2550397Sobrien   this library does not by itself cause the resulting executable
2650397Sobrien   to be covered by the GNU General Public License.
2750397Sobrien   This exception does not however invalidate any other reasons why
2850397Sobrien   the executable file might be covered by the GNU General Public License.  */
2950397Sobrien
3090075Sobrien#ifndef GCC_GTHR_POSIX_H
3190075Sobrien#define GCC_GTHR_POSIX_H
3250397Sobrien
3350397Sobrien/* POSIX threads specific definitions.
3490075Sobrien   Easy, since the interface is just one-to-one mapping.  */
3550397Sobrien
3650397Sobrien#define __GTHREADS 1
3750397Sobrien
38132718Skan/* Some implementations of <pthread.h> require this to be defined.  */
39169689Skan#if !defined(_REENTRANT) && defined(__osf__)
40132718Skan#define _REENTRANT 1
41132718Skan#endif
42132718Skan
4350397Sobrien#include <pthread.h>
44117395Skan#include <unistd.h>
4550397Sobrien
4650397Sobrientypedef pthread_key_t __gthread_key_t;
4750397Sobrientypedef pthread_once_t __gthread_once_t;
4850397Sobrientypedef pthread_mutex_t __gthread_mutex_t;
49169689Skantypedef pthread_mutex_t __gthread_recursive_mutex_t;
5050397Sobrien
5150397Sobrien#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
5250397Sobrien#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
53169689Skan#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
54169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
55169689Skan#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
56169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
57169689Skan#else
58169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
59169689Skan#endif
6050397Sobrien
6150397Sobrien#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
62171825Skan# ifndef __gthrw_pragma
63171825Skan#  define __gthrw_pragma(pragma)
64171825Skan# endif
65169689Skan# define __gthrw2(name,name2,type) \
66171825Skan  static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
67171825Skan  __gthrw_pragma(weak type)
68169689Skan# define __gthrw_(name) __gthrw_ ## name
69169689Skan#else
70169689Skan# define __gthrw2(name,name2,type)
71169689Skan# define __gthrw_(name) name
72169689Skan#endif
7350397Sobrien
74169689Skan/* Typically, __gthrw_foo is a weak reference to symbol foo.  */
75169689Skan#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
7650397Sobrien
77169689Skan/* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
78169689Skan   map a subset of the POSIX pthread API to mangled versions of their
79169689Skan   names.  */
80169689Skan#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
81169689Skan#define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
82169689Skan__gthrw3(pthread_once)
83169689Skan__gthrw3(pthread_getspecific)
84169689Skan__gthrw3(pthread_setspecific)
85169689Skan__gthrw3(pthread_create)
86169689Skan__gthrw3(pthread_cancel)
87169689Skan__gthrw3(pthread_mutex_lock)
88169689Skan__gthrw3(pthread_mutex_trylock)
89169689Skan__gthrw3(pthread_mutex_unlock)
90169689Skan__gthrw3(pthread_mutex_init)
91169689Skan#else
92169689Skan__gthrw(pthread_once)
93169689Skan__gthrw(pthread_getspecific)
94169689Skan__gthrw(pthread_setspecific)
95169689Skan__gthrw(pthread_create)
96169689Skan__gthrw(pthread_cancel)
97169689Skan__gthrw(pthread_mutex_lock)
98169689Skan__gthrw(pthread_mutex_trylock)
99169689Skan__gthrw(pthread_mutex_unlock)
100169689Skan__gthrw(pthread_mutex_init)
101169689Skan#endif
10250397Sobrien
103169689Skan__gthrw(pthread_key_create)
104169689Skan__gthrw(pthread_key_delete)
105169689Skan__gthrw(pthread_mutexattr_init)
106169689Skan__gthrw(pthread_mutexattr_settype)
107169689Skan__gthrw(pthread_mutexattr_destroy)
108169689Skan
109169689Skan
110132718Skan#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
111117395Skan/* Objective-C.  */
112169689Skan#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
113169689Skan__gthrw3(pthread_cond_broadcast)
114169689Skan__gthrw3(pthread_cond_destroy)
115169689Skan__gthrw3(pthread_cond_init)
116169689Skan__gthrw3(pthread_cond_signal)
117169689Skan__gthrw3(pthread_cond_wait)
118169689Skan__gthrw3(pthread_exit)
119169689Skan__gthrw3(pthread_mutex_destroy)
120169689Skan__gthrw3(pthread_self)
121169689Skan#else
122169689Skan__gthrw(pthread_cond_broadcast)
123169689Skan__gthrw(pthread_cond_destroy)
124169689Skan__gthrw(pthread_cond_init)
125169689Skan__gthrw(pthread_cond_signal)
126169689Skan__gthrw(pthread_cond_wait)
127169689Skan__gthrw(pthread_exit)
128169689Skan__gthrw(pthread_mutex_destroy)
129169689Skan__gthrw(pthread_self)
130169689Skan#endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
131169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING
132117395Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
133169689Skan__gthrw(sched_get_priority_max)
134169689Skan__gthrw(sched_get_priority_min)
135117395Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
136169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */
137169689Skan__gthrw(sched_yield)
138169689Skan__gthrw(pthread_attr_destroy)
139169689Skan__gthrw(pthread_attr_init)
140169689Skan__gthrw(pthread_attr_setdetachstate)
141117395Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
142169689Skan__gthrw(pthread_getschedparam)
143169689Skan__gthrw(pthread_setschedparam)
144117395Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
145132718Skan#endif /* _LIBOBJC || _LIBOBJC_WEAK */
14650397Sobrien
147169689Skan#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
148169689Skan
149169689Skan/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
150169689Skan   -pthreads is not specified.  The functions are dummies and most return an
151169689Skan   error value.  However pthread_once returns 0 without invoking the routine
152169689Skan   it is passed so we cannot pretend that the interface is active if -pthreads
153169689Skan   is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
154169689Skan   we need to play the usual game with weak symbols.  On Solaris 10 and up, a
155178388Smarius   working interface is always exposed.  On FreeBSD 6 and later, libc also
156178388Smarius   exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
157178388Smarius   to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
158178388Smarius   which means the alternate __gthread_active_p below cannot be used there.  */
159169689Skan
160178388Smarius#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
161169689Skan
162169689Skanstatic volatile int __gthread_active = -1;
163169689Skan
164169689Skanstatic void
165169689Skan__gthread_trigger (void)
166169689Skan{
167169689Skan  __gthread_active = 1;
168169689Skan}
169169689Skan
17050397Sobrienstatic inline int
17190075Sobrien__gthread_active_p (void)
17250397Sobrien{
173169689Skan  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
174169689Skan  static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
175169689Skan
176169689Skan  /* Avoid reading __gthread_active twice on the main code path.  */
177169689Skan  int __gthread_active_latest_value = __gthread_active;
178169689Skan
179169689Skan  /* This test is not protected to avoid taking a lock on the main code
180169689Skan     path so every update of __gthread_active in a threaded program must
181169689Skan     be atomic with regard to the result of the test.  */
182169689Skan  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
183169689Skan    {
184169689Skan      if (__gthrw_(pthread_once))
185169689Skan	{
186169689Skan	  /* If this really is a threaded program, then we must ensure that
187169689Skan	     __gthread_active has been set to 1 before exiting this block.  */
188169689Skan	  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
189169689Skan	  __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
190169689Skan	  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
191169689Skan	}
192169689Skan
193169689Skan      /* Make sure we'll never enter this block again.  */
194169689Skan      if (__gthread_active < 0)
195169689Skan	__gthread_active = 0;
196169689Skan
197169689Skan      __gthread_active_latest_value = __gthread_active;
198169689Skan    }
199169689Skan
200169689Skan  return __gthread_active_latest_value != 0;
201169689Skan}
202169689Skan
203178388Smarius#else /* neither FreeBSD nor Solaris */
204169689Skan
205169689Skanstatic inline int
206169689Skan__gthread_active_p (void)
207169689Skan{
208169689Skan  static void *const __gthread_active_ptr
209169689Skan    = __extension__ (void *) &__gthrw_(pthread_cancel);
21050397Sobrien  return __gthread_active_ptr != 0;
21150397Sobrien}
21250397Sobrien
213178388Smarius#endif /* FreeBSD or Solaris */
214169689Skan
21550397Sobrien#else /* not SUPPORTS_WEAK */
21650397Sobrien
21750397Sobrienstatic inline int
21890075Sobrien__gthread_active_p (void)
21950397Sobrien{
22050397Sobrien  return 1;
22150397Sobrien}
22250397Sobrien
22350397Sobrien#endif /* SUPPORTS_WEAK */
22450397Sobrien
22590075Sobrien#ifdef _LIBOBJC
22690075Sobrien
22790075Sobrien/* This is the config.h file in libobjc/ */
22890075Sobrien#include <config.h>
22990075Sobrien
23090075Sobrien#ifdef HAVE_SCHED_H
23190075Sobrien# include <sched.h>
23290075Sobrien#endif
23390075Sobrien
23490075Sobrien/* Key structure for maintaining thread specific storage */
23590075Sobrienstatic pthread_key_t _objc_thread_storage;
23690075Sobrienstatic pthread_attr_t _objc_thread_attribs;
23790075Sobrien
23890075Sobrien/* Thread local storage for a single thread */
23990075Sobrienstatic void *thread_local_storage = NULL;
24090075Sobrien
24190075Sobrien/* Backend initialization functions */
24290075Sobrien
24390075Sobrien/* Initialize the threads subsystem.  */
24450397Sobrienstatic inline int
245117395Skan__gthread_objc_init_thread_system (void)
24650397Sobrien{
24750397Sobrien  if (__gthread_active_p ())
24890075Sobrien    {
249169689Skan      /* Initialize the thread storage key.  */
250169689Skan      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
251117395Skan	{
252117395Skan	  /* The normal default detach state for threads is
253117395Skan	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
254117395Skan	   * when you think they should.  */
255169689Skan	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
256169689Skan	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
257117395Skan					      PTHREAD_CREATE_DETACHED) == 0)
258117395Skan	    return 0;
259117395Skan	}
26090075Sobrien    }
26190075Sobrien
26290075Sobrien  return -1;
26390075Sobrien}
26490075Sobrien
26590075Sobrien/* Close the threads subsystem.  */
26690075Sobrienstatic inline int
267117395Skan__gthread_objc_close_thread_system (void)
26890075Sobrien{
26990075Sobrien  if (__gthread_active_p ()
270169689Skan      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
271169689Skan      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
27290075Sobrien    return 0;
27390075Sobrien
27490075Sobrien  return -1;
27590075Sobrien}
27690075Sobrien
27790075Sobrien/* Backend thread functions */
27890075Sobrien
27990075Sobrien/* Create a new thread of execution.  */
28090075Sobrienstatic inline objc_thread_t
281117395Skan__gthread_objc_thread_detach (void (*func)(void *), void *arg)
28290075Sobrien{
28390075Sobrien  objc_thread_t thread_id;
28490075Sobrien  pthread_t new_thread_handle;
28590075Sobrien
28690075Sobrien  if (!__gthread_active_p ())
28790075Sobrien    return NULL;
288117395Skan
289169689Skan  if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
29090075Sobrien    thread_id = (objc_thread_t) new_thread_handle;
29190075Sobrien  else
29290075Sobrien    thread_id = NULL;
293117395Skan
29490075Sobrien  return thread_id;
29590075Sobrien}
29690075Sobrien
29790075Sobrien/* Set the current thread's priority.  */
29890075Sobrienstatic inline int
299117395Skan__gthread_objc_thread_set_priority (int priority)
30090075Sobrien{
301117395Skan  if (!__gthread_active_p ())
30290075Sobrien    return -1;
303117395Skan  else
304117395Skan    {
305169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING
306117395Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
307169689Skan      pthread_t thread_id = __gthrw_(pthread_self) ();
308117395Skan      int policy;
309117395Skan      struct sched_param params;
310117395Skan      int priority_min, priority_max;
31190075Sobrien
312169689Skan      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
313117395Skan	{
314169689Skan	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
315117395Skan	    return -1;
31690075Sobrien
317169689Skan	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
318117395Skan	    return -1;
31990075Sobrien
320117395Skan	  if (priority > priority_max)
321117395Skan	    priority = priority_max;
322117395Skan	  else if (priority < priority_min)
323117395Skan	    priority = priority_min;
324117395Skan	  params.sched_priority = priority;
32590075Sobrien
326117395Skan	  /*
327117395Skan	   * The solaris 7 and several other man pages incorrectly state that
328117395Skan	   * this should be a pointer to policy but pthread.h is universally
329117395Skan	   * at odds with this.
330117395Skan	   */
331169689Skan	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
332117395Skan	    return 0;
333117395Skan	}
334117395Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
335169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */
336117395Skan      return -1;
337117395Skan    }
33890075Sobrien}
33990075Sobrien
34090075Sobrien/* Return the current thread's priority.  */
34190075Sobrienstatic inline int
342117395Skan__gthread_objc_thread_get_priority (void)
34390075Sobrien{
344169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING
345117395Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
34690075Sobrien  if (__gthread_active_p ())
34790075Sobrien    {
34890075Sobrien      int policy;
34990075Sobrien      struct sched_param params;
35090075Sobrien
351169689Skan      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
352117395Skan	return params.sched_priority;
35390075Sobrien      else
354117395Skan	return -1;
35590075Sobrien    }
35690075Sobrien  else
357117395Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
358169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */
35990075Sobrien    return OBJC_THREAD_INTERACTIVE_PRIORITY;
36090075Sobrien}
36190075Sobrien
36290075Sobrien/* Yield our process time to another thread.  */
36390075Sobrienstatic inline void
364117395Skan__gthread_objc_thread_yield (void)
36590075Sobrien{
36690075Sobrien  if (__gthread_active_p ())
367169689Skan    __gthrw_(sched_yield) ();
36890075Sobrien}
36990075Sobrien
37090075Sobrien/* Terminate the current thread.  */
37190075Sobrienstatic inline int
372117395Skan__gthread_objc_thread_exit (void)
37390075Sobrien{
37490075Sobrien  if (__gthread_active_p ())
37590075Sobrien    /* exit the thread */
376169689Skan    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
37790075Sobrien
37890075Sobrien  /* Failed if we reached here */
37990075Sobrien  return -1;
38090075Sobrien}
38190075Sobrien
38290075Sobrien/* Returns an integer value which uniquely describes a thread.  */
38390075Sobrienstatic inline objc_thread_t
384117395Skan__gthread_objc_thread_id (void)
38590075Sobrien{
38690075Sobrien  if (__gthread_active_p ())
387169689Skan    return (objc_thread_t) __gthrw_(pthread_self) ();
38890075Sobrien  else
38990075Sobrien    return (objc_thread_t) 1;
39090075Sobrien}
39190075Sobrien
39290075Sobrien/* Sets the thread's local storage pointer.  */
39390075Sobrienstatic inline int
394117395Skan__gthread_objc_thread_set_data (void *value)
39590075Sobrien{
39690075Sobrien  if (__gthread_active_p ())
397169689Skan    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
39890075Sobrien  else
39990075Sobrien    {
40090075Sobrien      thread_local_storage = value;
40190075Sobrien      return 0;
40290075Sobrien    }
40390075Sobrien}
40490075Sobrien
40590075Sobrien/* Returns the thread's local storage pointer.  */
40690075Sobrienstatic inline void *
407117395Skan__gthread_objc_thread_get_data (void)
40890075Sobrien{
40990075Sobrien  if (__gthread_active_p ())
410169689Skan    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
41190075Sobrien  else
41290075Sobrien    return thread_local_storage;
41390075Sobrien}
41490075Sobrien
41590075Sobrien/* Backend mutex functions */
41690075Sobrien
41790075Sobrien/* Allocate a mutex.  */
41890075Sobrienstatic inline int
419117395Skan__gthread_objc_mutex_allocate (objc_mutex_t mutex)
42090075Sobrien{
42190075Sobrien  if (__gthread_active_p ())
42290075Sobrien    {
423117395Skan      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
42490075Sobrien
425169689Skan      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
42690075Sobrien	{
427117395Skan	  objc_free (mutex->backend);
42890075Sobrien	  mutex->backend = NULL;
42990075Sobrien	  return -1;
43090075Sobrien	}
43190075Sobrien    }
43290075Sobrien
43390075Sobrien  return 0;
43490075Sobrien}
43590075Sobrien
43690075Sobrien/* Deallocate a mutex.  */
43790075Sobrienstatic inline int
438117395Skan__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
43990075Sobrien{
44090075Sobrien  if (__gthread_active_p ())
44190075Sobrien    {
44290075Sobrien      int count;
44390075Sobrien
44490075Sobrien      /*
44590075Sobrien       * Posix Threads specifically require that the thread be unlocked
446169689Skan       * for __gthrw_(pthread_mutex_destroy) to work.
44790075Sobrien       */
44890075Sobrien
44990075Sobrien      do
45090075Sobrien	{
451169689Skan	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
45290075Sobrien	  if (count < 0)
45390075Sobrien	    return -1;
45490075Sobrien	}
45590075Sobrien      while (count);
45690075Sobrien
457169689Skan      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
45890075Sobrien	return -1;
45990075Sobrien
460117395Skan      objc_free (mutex->backend);
46190075Sobrien      mutex->backend = NULL;
46290075Sobrien    }
46390075Sobrien  return 0;
46490075Sobrien}
46590075Sobrien
46690075Sobrien/* Grab a lock on a mutex.  */
46790075Sobrienstatic inline int
468117395Skan__gthread_objc_mutex_lock (objc_mutex_t mutex)
46990075Sobrien{
470117395Skan  if (__gthread_active_p ()
471169689Skan      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
47290075Sobrien    {
47390075Sobrien      return -1;
47490075Sobrien    }
47590075Sobrien
47690075Sobrien  return 0;
47790075Sobrien}
47890075Sobrien
47990075Sobrien/* Try to grab a lock on a mutex.  */
48090075Sobrienstatic inline int
481117395Skan__gthread_objc_mutex_trylock (objc_mutex_t mutex)
48290075Sobrien{
483117395Skan  if (__gthread_active_p ()
484169689Skan      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
48590075Sobrien    {
48690075Sobrien      return -1;
48790075Sobrien    }
48890075Sobrien
48990075Sobrien  return 0;
49090075Sobrien}
49190075Sobrien
49290075Sobrien/* Unlock the mutex */
49390075Sobrienstatic inline int
494117395Skan__gthread_objc_mutex_unlock (objc_mutex_t mutex)
49590075Sobrien{
496117395Skan  if (__gthread_active_p ()
497169689Skan      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
49890075Sobrien    {
49990075Sobrien      return -1;
50090075Sobrien    }
50190075Sobrien
50290075Sobrien  return 0;
50390075Sobrien}
50490075Sobrien
50590075Sobrien/* Backend condition mutex functions */
50690075Sobrien
50790075Sobrien/* Allocate a condition.  */
50890075Sobrienstatic inline int
509117395Skan__gthread_objc_condition_allocate (objc_condition_t condition)
51090075Sobrien{
51190075Sobrien  if (__gthread_active_p ())
51290075Sobrien    {
513117395Skan      condition->backend = objc_malloc (sizeof (pthread_cond_t));
51490075Sobrien
515169689Skan      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
51690075Sobrien	{
517117395Skan	  objc_free (condition->backend);
51890075Sobrien	  condition->backend = NULL;
51990075Sobrien	  return -1;
52090075Sobrien	}
52190075Sobrien    }
52290075Sobrien
52390075Sobrien  return 0;
52490075Sobrien}
52590075Sobrien
52690075Sobrien/* Deallocate a condition.  */
52790075Sobrienstatic inline int
528117395Skan__gthread_objc_condition_deallocate (objc_condition_t condition)
52990075Sobrien{
53090075Sobrien  if (__gthread_active_p ())
53190075Sobrien    {
532169689Skan      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
53390075Sobrien	return -1;
53490075Sobrien
535117395Skan      objc_free (condition->backend);
53690075Sobrien      condition->backend = NULL;
53790075Sobrien    }
53890075Sobrien  return 0;
53990075Sobrien}
54090075Sobrien
54190075Sobrien/* Wait on the condition */
54290075Sobrienstatic inline int
543117395Skan__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
54490075Sobrien{
54590075Sobrien  if (__gthread_active_p ())
546169689Skan    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
547117395Skan			      (pthread_mutex_t *) mutex->backend);
54890075Sobrien  else
54990075Sobrien    return 0;
55090075Sobrien}
55190075Sobrien
55290075Sobrien/* Wake up all threads waiting on this condition.  */
55390075Sobrienstatic inline int
554117395Skan__gthread_objc_condition_broadcast (objc_condition_t condition)
55590075Sobrien{
55690075Sobrien  if (__gthread_active_p ())
557169689Skan    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
55890075Sobrien  else
55990075Sobrien    return 0;
56090075Sobrien}
56190075Sobrien
56290075Sobrien/* Wake up one thread waiting on this condition.  */
56390075Sobrienstatic inline int
564117395Skan__gthread_objc_condition_signal (objc_condition_t condition)
56590075Sobrien{
56690075Sobrien  if (__gthread_active_p ())
567169689Skan    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
56890075Sobrien  else
56990075Sobrien    return 0;
57090075Sobrien}
57190075Sobrien
57290075Sobrien#else /* _LIBOBJC */
57390075Sobrien
57490075Sobrienstatic inline int
57590075Sobrien__gthread_once (__gthread_once_t *once, void (*func) (void))
57690075Sobrien{
57790075Sobrien  if (__gthread_active_p ())
578169689Skan    return __gthrw_(pthread_once) (once, func);
57950397Sobrien  else
58050397Sobrien    return -1;
58150397Sobrien}
58250397Sobrien
58350397Sobrienstatic inline int
58450397Sobrien__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
58550397Sobrien{
586169689Skan  return __gthrw_(pthread_key_create) (key, dtor);
58750397Sobrien}
58850397Sobrien
58950397Sobrienstatic inline int
59050397Sobrien__gthread_key_delete (__gthread_key_t key)
59150397Sobrien{
592169689Skan  return __gthrw_(pthread_key_delete) (key);
59350397Sobrien}
59450397Sobrien
59550397Sobrienstatic inline void *
59650397Sobrien__gthread_getspecific (__gthread_key_t key)
59750397Sobrien{
598169689Skan  return __gthrw_(pthread_getspecific) (key);
59950397Sobrien}
60050397Sobrien
60150397Sobrienstatic inline int
60250397Sobrien__gthread_setspecific (__gthread_key_t key, const void *ptr)
60350397Sobrien{
604169689Skan  return __gthrw_(pthread_setspecific) (key, ptr);
60550397Sobrien}
60650397Sobrien
60750397Sobrienstatic inline int
60850397Sobrien__gthread_mutex_lock (__gthread_mutex_t *mutex)
60950397Sobrien{
61050397Sobrien  if (__gthread_active_p ())
611169689Skan    return __gthrw_(pthread_mutex_lock) (mutex);
61250397Sobrien  else
61350397Sobrien    return 0;
61450397Sobrien}
61550397Sobrien
61650397Sobrienstatic inline int
61750397Sobrien__gthread_mutex_trylock (__gthread_mutex_t *mutex)
61850397Sobrien{
61950397Sobrien  if (__gthread_active_p ())
620169689Skan    return __gthrw_(pthread_mutex_trylock) (mutex);
62150397Sobrien  else
62250397Sobrien    return 0;
62350397Sobrien}
62450397Sobrien
62550397Sobrienstatic inline int
62650397Sobrien__gthread_mutex_unlock (__gthread_mutex_t *mutex)
62750397Sobrien{
62850397Sobrien  if (__gthread_active_p ())
629169689Skan    return __gthrw_(pthread_mutex_unlock) (mutex);
63050397Sobrien  else
63150397Sobrien    return 0;
63250397Sobrien}
63350397Sobrien
634169689Skan#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
635169689Skanstatic inline int
636169689Skan__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
637169689Skan{
638169689Skan  if (__gthread_active_p ())
639169689Skan    {
640169689Skan      pthread_mutexattr_t attr;
641169689Skan      int r;
642169689Skan
643169689Skan      r = __gthrw_(pthread_mutexattr_init) (&attr);
644169689Skan      if (!r)
645169689Skan	r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
646169689Skan      if (!r)
647169689Skan	r = __gthrw_(pthread_mutex_init) (mutex, &attr);
648169689Skan      if (!r)
649169689Skan	r = __gthrw_(pthread_mutexattr_destroy) (&attr);
650169689Skan      return r;
651169689Skan    }
652169689Skan  return 0;
653169689Skan}
654169689Skan#endif
655169689Skan
656169689Skanstatic inline int
657169689Skan__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
658169689Skan{
659169689Skan  return __gthread_mutex_lock (mutex);
660169689Skan}
661169689Skan
662169689Skanstatic inline int
663169689Skan__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
664169689Skan{
665169689Skan  return __gthread_mutex_trylock (mutex);
666169689Skan}
667169689Skan
668169689Skanstatic inline int
669169689Skan__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
670169689Skan{
671169689Skan  return __gthread_mutex_unlock (mutex);
672169689Skan}
673169689Skan
67490075Sobrien#endif /* _LIBOBJC */
67590075Sobrien
67690075Sobrien#endif /* ! GCC_GTHR_POSIX_H */
677