1169689Skan/* Threads compatibility routines for libgcc2 and libobjc.  */
2169689Skan/* Compile this one with gcc.  */
3169689Skan/* Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4169689Skan
5169689SkanThis file is part of GCC.
6169689Skan
7169689SkanGCC is free software; you can redistribute it and/or modify it under
8169689Skanthe terms of the GNU General Public License as published by the Free
9169689SkanSoftware Foundation; either version 2, or (at your option) any later
10169689Skanversion.
11169689Skan
12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
14169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15169689Skanfor more details.
16169689Skan
17169689SkanYou should have received a copy of the GNU General Public License
18169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20169689Skan02110-1301, USA.  */
21169689Skan
22169689Skan/* As a special exception, if you link this library with other files,
23169689Skan   some of which are compiled with GCC, to produce an executable,
24169689Skan   this library does not by itself cause the resulting executable
25169689Skan   to be covered by the GNU General Public License.
26169689Skan   This exception does not however invalidate any other reasons why
27169689Skan   the executable file might be covered by the GNU General Public License.  */
28169689Skan
29169689Skan#ifndef GCC_GTHR_POSIX_H
30169689Skan#define GCC_GTHR_POSIX_H
31169689Skan
32169689Skan/* POSIX threads specific definitions.
33169689Skan   Easy, since the interface is just one-to-one mapping.  */
34169689Skan
35169689Skan#define __GTHREADS 1
36169689Skan
37169689Skan/* Some implementations of <pthread.h> require this to be defined.  */
38169689Skan#ifndef _REENTRANT
39169689Skan#define _REENTRANT 1
40169689Skan#endif
41169689Skan
42169689Skan#include <pthread.h>
43169689Skan#include <unistd.h>
44169689Skan
45169689Skantypedef pthread_key_t __gthread_key_t;
46169689Skantypedef pthread_once_t __gthread_once_t;
47169689Skantypedef pthread_mutex_t __gthread_mutex_t;
48169689Skan
49169689Skantypedef struct {
50169689Skan  long depth;
51169689Skan  pthread_t owner;
52169689Skan  pthread_mutex_t actual;
53169689Skan} __gthread_recursive_mutex_t;
54169689Skan
55169689Skan#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
56169689Skan#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
57169689Skan#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
58169689Skan
59169689Skan#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
60169689Skan# define __gthrw(name) \
61169689Skan  static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
62169689Skan# define __gthrw_(name) __gthrw_ ## name
63169689Skan#else
64169689Skan# define __gthrw(name)
65169689Skan# define __gthrw_(name) name
66169689Skan#endif
67169689Skan
68169689Skan__gthrw(pthread_once)
69169689Skan__gthrw(pthread_key_create)
70169689Skan__gthrw(pthread_key_delete)
71169689Skan__gthrw(pthread_getspecific)
72169689Skan__gthrw(pthread_setspecific)
73169689Skan__gthrw(pthread_create)
74169689Skan__gthrw(pthread_cancel)
75169689Skan__gthrw(pthread_self)
76169689Skan
77169689Skan__gthrw(pthread_mutex_lock)
78169689Skan__gthrw(pthread_mutex_trylock)
79169689Skan__gthrw(pthread_mutex_unlock)
80169689Skan__gthrw(pthread_mutexattr_init)
81169689Skan__gthrw(pthread_mutexattr_destroy)
82169689Skan
83169689Skan__gthrw(pthread_mutex_init)
84169689Skan
85169689Skan#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
86169689Skan/* Objective-C.  */
87169689Skan__gthrw(pthread_cond_broadcast)
88169689Skan__gthrw(pthread_cond_destroy)
89169689Skan__gthrw(pthread_cond_init)
90169689Skan__gthrw(pthread_cond_signal)
91169689Skan__gthrw(pthread_cond_wait)
92169689Skan__gthrw(pthread_exit)
93169689Skan__gthrw(pthread_mutex_destroy)
94169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING
95169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
96169689Skan__gthrw(sched_get_priority_max)
97169689Skan__gthrw(sched_get_priority_min)
98169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
99169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */
100169689Skan__gthrw(sched_yield)
101169689Skan__gthrw(pthread_attr_destroy)
102169689Skan__gthrw(pthread_attr_init)
103169689Skan__gthrw(pthread_attr_setdetachstate)
104169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
105169689Skan__gthrw(pthread_getschedparam)
106169689Skan__gthrw(pthread_setschedparam)
107169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
108169689Skan#endif /* _LIBOBJC || _LIBOBJC_WEAK */
109169689Skan
110169689Skan#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
111169689Skan
112169689Skan/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
113169689Skan   -pthreads is not specified.  The functions are dummies and most return an
114169689Skan   error value.  However pthread_once returns 0 without invoking the routine
115169689Skan   it is passed so we cannot pretend that the interface is active if -pthreads
116169689Skan   is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
117169689Skan   we need to play the usual game with weak symbols.  On Solaris 10 and up, a
118252176Spfg   working interface is always exposed. On FreeBSD 6 and later, libc also
119252176Spfg   exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
120252176Spfg   to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
121252176Spfg   which means the alternate __gthread_active_p below cannot be used there.  */
122169689Skan
123169689Skan
124252176Spfg */
125252176Spfg
126252176Spfg#if defined(__FreeBSD__) || defined(__sun) && defined(__svr4__)
127252176Spfg
128169689Skanstatic volatile int __gthread_active = -1;
129169689Skan
130169689Skanstatic void
131169689Skan__gthread_trigger (void)
132169689Skan{
133169689Skan  __gthread_active = 1;
134169689Skan}
135169689Skan
136169689Skanstatic inline int
137169689Skan__gthread_active_p (void)
138169689Skan{
139169689Skan  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
140169689Skan  static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
141169689Skan
142169689Skan  /* Avoid reading __gthread_active twice on the main code path.  */
143169689Skan  int __gthread_active_latest_value = __gthread_active;
144169689Skan
145169689Skan  /* This test is not protected to avoid taking a lock on the main code
146169689Skan     path so every update of __gthread_active in a threaded program must
147169689Skan     be atomic with regard to the result of the test.  */
148169689Skan  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
149169689Skan    {
150169689Skan      if (__gthrw_(pthread_once))
151169689Skan	{
152169689Skan	  /* If this really is a threaded program, then we must ensure that
153169689Skan	     __gthread_active has been set to 1 before exiting this block.  */
154169689Skan	  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
155169689Skan	  __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
156169689Skan	  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
157169689Skan	}
158169689Skan
159169689Skan      /* Make sure we'll never enter this block again.  */
160169689Skan      if (__gthread_active < 0)
161169689Skan	__gthread_active = 0;
162169689Skan
163169689Skan      __gthread_active_latest_value = __gthread_active;
164169689Skan    }
165169689Skan
166169689Skan  return __gthread_active_latest_value != 0;
167169689Skan}
168169689Skan
169252176Spfg#else /* neither FreeBSD nor Solaris */
170169689Skan
171169689Skanstatic inline int
172169689Skan__gthread_active_p (void)
173169689Skan{
174169689Skan  static void *const __gthread_active_ptr
175169689Skan    = __extension__ (void *) &__gthrw_(pthread_cancel);
176169689Skan  return __gthread_active_ptr != 0;
177169689Skan}
178169689Skan
179252176Spfg#endif /* FreeBSD or Solaris */
180169689Skan
181169689Skan#else /* not SUPPORTS_WEAK */
182169689Skan
183169689Skanstatic inline int
184169689Skan__gthread_active_p (void)
185169689Skan{
186169689Skan  return 1;
187169689Skan}
188169689Skan
189169689Skan#endif /* SUPPORTS_WEAK */
190169689Skan
191169689Skan#ifdef _LIBOBJC
192169689Skan
193169689Skan/* This is the config.h file in libobjc/ */
194169689Skan#include <config.h>
195169689Skan
196169689Skan#ifdef HAVE_SCHED_H
197169689Skan# include <sched.h>
198169689Skan#endif
199169689Skan
200169689Skan/* Key structure for maintaining thread specific storage */
201169689Skanstatic pthread_key_t _objc_thread_storage;
202169689Skanstatic pthread_attr_t _objc_thread_attribs;
203169689Skan
204169689Skan/* Thread local storage for a single thread */
205169689Skanstatic void *thread_local_storage = NULL;
206169689Skan
207169689Skan/* Backend initialization functions */
208169689Skan
209169689Skan/* Initialize the threads subsystem.  */
210169689Skanstatic inline int
211169689Skan__gthread_objc_init_thread_system (void)
212169689Skan{
213169689Skan  if (__gthread_active_p ())
214169689Skan    {
215169689Skan      /* Initialize the thread storage key.  */
216169689Skan      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
217169689Skan	{
218169689Skan	  /* The normal default detach state for threads is
219169689Skan	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
220169689Skan	   * when you think they should.  */
221169689Skan	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
222169689Skan	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
223169689Skan					      PTHREAD_CREATE_DETACHED) == 0)
224169689Skan	    return 0;
225169689Skan	}
226169689Skan    }
227169689Skan
228169689Skan  return -1;
229169689Skan}
230169689Skan
231169689Skan/* Close the threads subsystem.  */
232169689Skanstatic inline int
233169689Skan__gthread_objc_close_thread_system (void)
234169689Skan{
235169689Skan  if (__gthread_active_p ()
236169689Skan      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
237169689Skan      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
238169689Skan    return 0;
239169689Skan
240169689Skan  return -1;
241169689Skan}
242169689Skan
243169689Skan/* Backend thread functions */
244169689Skan
245169689Skan/* Create a new thread of execution.  */
246169689Skanstatic inline objc_thread_t
247169689Skan__gthread_objc_thread_detach (void (*func)(void *), void *arg)
248169689Skan{
249169689Skan  objc_thread_t thread_id;
250169689Skan  pthread_t new_thread_handle;
251169689Skan
252169689Skan  if (!__gthread_active_p ())
253169689Skan    return NULL;
254169689Skan
255169689Skan  if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
256169689Skan    thread_id = (objc_thread_t) new_thread_handle;
257169689Skan  else
258169689Skan    thread_id = NULL;
259169689Skan
260169689Skan  return thread_id;
261169689Skan}
262169689Skan
263169689Skan/* Set the current thread's priority.  */
264169689Skanstatic inline int
265169689Skan__gthread_objc_thread_set_priority (int priority)
266169689Skan{
267169689Skan  if (!__gthread_active_p ())
268169689Skan    return -1;
269169689Skan  else
270169689Skan    {
271169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING
272169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
273169689Skan      pthread_t thread_id = __gthrw_(pthread_self) ();
274169689Skan      int policy;
275169689Skan      struct sched_param params;
276169689Skan      int priority_min, priority_max;
277169689Skan
278169689Skan      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
279169689Skan	{
280169689Skan	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
281169689Skan	    return -1;
282169689Skan
283169689Skan	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
284169689Skan	    return -1;
285169689Skan
286169689Skan	  if (priority > priority_max)
287169689Skan	    priority = priority_max;
288169689Skan	  else if (priority < priority_min)
289169689Skan	    priority = priority_min;
290169689Skan	  params.sched_priority = priority;
291169689Skan
292169689Skan	  /*
293169689Skan	   * The solaris 7 and several other man pages incorrectly state that
294169689Skan	   * this should be a pointer to policy but pthread.h is universally
295169689Skan	   * at odds with this.
296169689Skan	   */
297169689Skan	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
298169689Skan	    return 0;
299169689Skan	}
300169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
301169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */
302169689Skan      return -1;
303169689Skan    }
304169689Skan}
305169689Skan
306169689Skan/* Return the current thread's priority.  */
307169689Skanstatic inline int
308169689Skan__gthread_objc_thread_get_priority (void)
309169689Skan{
310169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING
311169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
312169689Skan  if (__gthread_active_p ())
313169689Skan    {
314169689Skan      int policy;
315169689Skan      struct sched_param params;
316169689Skan
317169689Skan      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
318169689Skan	return params.sched_priority;
319169689Skan      else
320169689Skan	return -1;
321169689Skan    }
322169689Skan  else
323169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
324169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */
325169689Skan    return OBJC_THREAD_INTERACTIVE_PRIORITY;
326169689Skan}
327169689Skan
328169689Skan/* Yield our process time to another thread.  */
329169689Skanstatic inline void
330169689Skan__gthread_objc_thread_yield (void)
331169689Skan{
332169689Skan  if (__gthread_active_p ())
333169689Skan    __gthrw_(sched_yield) ();
334169689Skan}
335169689Skan
336169689Skan/* Terminate the current thread.  */
337169689Skanstatic inline int
338169689Skan__gthread_objc_thread_exit (void)
339169689Skan{
340169689Skan  if (__gthread_active_p ())
341169689Skan    /* exit the thread */
342169689Skan    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
343169689Skan
344169689Skan  /* Failed if we reached here */
345169689Skan  return -1;
346169689Skan}
347169689Skan
348169689Skan/* Returns an integer value which uniquely describes a thread.  */
349169689Skanstatic inline objc_thread_t
350169689Skan__gthread_objc_thread_id (void)
351169689Skan{
352169689Skan  if (__gthread_active_p ())
353169689Skan    return (objc_thread_t) __gthrw_(pthread_self) ();
354169689Skan  else
355169689Skan    return (objc_thread_t) 1;
356169689Skan}
357169689Skan
358169689Skan/* Sets the thread's local storage pointer.  */
359169689Skanstatic inline int
360169689Skan__gthread_objc_thread_set_data (void *value)
361169689Skan{
362169689Skan  if (__gthread_active_p ())
363169689Skan    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
364169689Skan  else
365169689Skan    {
366169689Skan      thread_local_storage = value;
367169689Skan      return 0;
368169689Skan    }
369169689Skan}
370169689Skan
371169689Skan/* Returns the thread's local storage pointer.  */
372169689Skanstatic inline void *
373169689Skan__gthread_objc_thread_get_data (void)
374169689Skan{
375169689Skan  if (__gthread_active_p ())
376169689Skan    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
377169689Skan  else
378169689Skan    return thread_local_storage;
379169689Skan}
380169689Skan
381169689Skan/* Backend mutex functions */
382169689Skan
383169689Skan/* Allocate a mutex.  */
384169689Skanstatic inline int
385169689Skan__gthread_objc_mutex_allocate (objc_mutex_t mutex)
386169689Skan{
387169689Skan  if (__gthread_active_p ())
388169689Skan    {
389169689Skan      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
390169689Skan
391169689Skan      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
392169689Skan	{
393169689Skan	  objc_free (mutex->backend);
394169689Skan	  mutex->backend = NULL;
395169689Skan	  return -1;
396169689Skan	}
397169689Skan    }
398169689Skan
399169689Skan  return 0;
400169689Skan}
401169689Skan
402169689Skan/* Deallocate a mutex.  */
403169689Skanstatic inline int
404169689Skan__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
405169689Skan{
406169689Skan  if (__gthread_active_p ())
407169689Skan    {
408169689Skan      int count;
409169689Skan
410169689Skan      /*
411169689Skan       * Posix Threads specifically require that the thread be unlocked
412169689Skan       * for __gthrw_(pthread_mutex_destroy) to work.
413169689Skan       */
414169689Skan
415169689Skan      do
416169689Skan	{
417169689Skan	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
418169689Skan	  if (count < 0)
419169689Skan	    return -1;
420169689Skan	}
421169689Skan      while (count);
422169689Skan
423169689Skan      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
424169689Skan	return -1;
425169689Skan
426169689Skan      objc_free (mutex->backend);
427169689Skan      mutex->backend = NULL;
428169689Skan    }
429169689Skan  return 0;
430169689Skan}
431169689Skan
432169689Skan/* Grab a lock on a mutex.  */
433169689Skanstatic inline int
434169689Skan__gthread_objc_mutex_lock (objc_mutex_t mutex)
435169689Skan{
436169689Skan  if (__gthread_active_p ()
437169689Skan      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
438169689Skan    {
439169689Skan      return -1;
440169689Skan    }
441169689Skan
442169689Skan  return 0;
443169689Skan}
444169689Skan
445169689Skan/* Try to grab a lock on a mutex.  */
446169689Skanstatic inline int
447169689Skan__gthread_objc_mutex_trylock (objc_mutex_t mutex)
448169689Skan{
449169689Skan  if (__gthread_active_p ()
450169689Skan      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
451169689Skan    {
452169689Skan      return -1;
453169689Skan    }
454169689Skan
455169689Skan  return 0;
456169689Skan}
457169689Skan
458169689Skan/* Unlock the mutex */
459169689Skanstatic inline int
460169689Skan__gthread_objc_mutex_unlock (objc_mutex_t mutex)
461169689Skan{
462169689Skan  if (__gthread_active_p ()
463169689Skan      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
464169689Skan    {
465169689Skan      return -1;
466169689Skan    }
467169689Skan
468169689Skan  return 0;
469169689Skan}
470169689Skan
471169689Skan/* Backend condition mutex functions */
472169689Skan
473169689Skan/* Allocate a condition.  */
474169689Skanstatic inline int
475169689Skan__gthread_objc_condition_allocate (objc_condition_t condition)
476169689Skan{
477169689Skan  if (__gthread_active_p ())
478169689Skan    {
479169689Skan      condition->backend = objc_malloc (sizeof (pthread_cond_t));
480169689Skan
481169689Skan      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
482169689Skan	{
483169689Skan	  objc_free (condition->backend);
484169689Skan	  condition->backend = NULL;
485169689Skan	  return -1;
486169689Skan	}
487169689Skan    }
488169689Skan
489169689Skan  return 0;
490169689Skan}
491169689Skan
492169689Skan/* Deallocate a condition.  */
493169689Skanstatic inline int
494169689Skan__gthread_objc_condition_deallocate (objc_condition_t condition)
495169689Skan{
496169689Skan  if (__gthread_active_p ())
497169689Skan    {
498169689Skan      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
499169689Skan	return -1;
500169689Skan
501169689Skan      objc_free (condition->backend);
502169689Skan      condition->backend = NULL;
503169689Skan    }
504169689Skan  return 0;
505169689Skan}
506169689Skan
507169689Skan/* Wait on the condition */
508169689Skanstatic inline int
509169689Skan__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
510169689Skan{
511169689Skan  if (__gthread_active_p ())
512169689Skan    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
513169689Skan			      (pthread_mutex_t *) mutex->backend);
514169689Skan  else
515169689Skan    return 0;
516169689Skan}
517169689Skan
518169689Skan/* Wake up all threads waiting on this condition.  */
519169689Skanstatic inline int
520169689Skan__gthread_objc_condition_broadcast (objc_condition_t condition)
521169689Skan{
522169689Skan  if (__gthread_active_p ())
523169689Skan    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
524169689Skan  else
525169689Skan    return 0;
526169689Skan}
527169689Skan
528169689Skan/* Wake up one thread waiting on this condition.  */
529169689Skanstatic inline int
530169689Skan__gthread_objc_condition_signal (objc_condition_t condition)
531169689Skan{
532169689Skan  if (__gthread_active_p ())
533169689Skan    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
534169689Skan  else
535169689Skan    return 0;
536169689Skan}
537169689Skan
538169689Skan#else /* _LIBOBJC */
539169689Skan
540169689Skanstatic inline int
541169689Skan__gthread_once (__gthread_once_t *once, void (*func) (void))
542169689Skan{
543169689Skan  if (__gthread_active_p ())
544169689Skan    return __gthrw_(pthread_once) (once, func);
545169689Skan  else
546169689Skan    return -1;
547169689Skan}
548169689Skan
549169689Skanstatic inline int
550169689Skan__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
551169689Skan{
552169689Skan  return __gthrw_(pthread_key_create) (key, dtor);
553169689Skan}
554169689Skan
555169689Skanstatic inline int
556169689Skan__gthread_key_delete (__gthread_key_t key)
557169689Skan{
558169689Skan  return __gthrw_(pthread_key_delete) (key);
559169689Skan}
560169689Skan
561169689Skanstatic inline void *
562169689Skan__gthread_getspecific (__gthread_key_t key)
563169689Skan{
564169689Skan  return __gthrw_(pthread_getspecific) (key);
565169689Skan}
566169689Skan
567169689Skanstatic inline int
568169689Skan__gthread_setspecific (__gthread_key_t key, const void *ptr)
569169689Skan{
570169689Skan  return __gthrw_(pthread_setspecific) (key, ptr);
571169689Skan}
572169689Skan
573169689Skanstatic inline int
574169689Skan__gthread_mutex_lock (__gthread_mutex_t *mutex)
575169689Skan{
576169689Skan  if (__gthread_active_p ())
577169689Skan    return __gthrw_(pthread_mutex_lock) (mutex);
578169689Skan  else
579169689Skan    return 0;
580169689Skan}
581169689Skan
582169689Skanstatic inline int
583169689Skan__gthread_mutex_trylock (__gthread_mutex_t *mutex)
584169689Skan{
585169689Skan  if (__gthread_active_p ())
586169689Skan    return __gthrw_(pthread_mutex_trylock) (mutex);
587169689Skan  else
588169689Skan    return 0;
589169689Skan}
590169689Skan
591169689Skanstatic inline int
592169689Skan__gthread_mutex_unlock (__gthread_mutex_t *mutex)
593169689Skan{
594169689Skan  if (__gthread_active_p ())
595169689Skan    return __gthrw_(pthread_mutex_unlock) (mutex);
596169689Skan  else
597169689Skan    return 0;
598169689Skan}
599169689Skan
600169689Skanstatic inline int
601169689Skan__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
602169689Skan{
603169689Skan  mutex->depth = 0;
604169689Skan  mutex->owner = (pthread_t) 0;
605169689Skan  return __gthrw_(pthread_mutex_init) (&mutex->actual, NULL);
606169689Skan}
607169689Skan
608169689Skanstatic inline int
609169689Skan__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
610169689Skan{
611169689Skan  if (__gthread_active_p ())
612169689Skan    {
613169689Skan      pthread_t me = __gthrw_(pthread_self) ();
614169689Skan
615169689Skan      if (mutex->owner != me)
616169689Skan	{
617169689Skan	  __gthrw_(pthread_mutex_lock) (&mutex->actual);
618169689Skan	  mutex->owner = me;
619169689Skan	}
620169689Skan
621169689Skan      mutex->depth++;
622169689Skan    }
623169689Skan  return 0;
624169689Skan}
625169689Skan
626169689Skanstatic inline int
627169689Skan__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
628169689Skan{
629169689Skan  if (__gthread_active_p ())
630169689Skan    {
631169689Skan      pthread_t me = __gthrw_(pthread_self) ();
632169689Skan
633169689Skan      if (mutex->owner != me)
634169689Skan	{
635169689Skan	  if (__gthrw_(pthread_mutex_trylock) (&mutex->actual))
636169689Skan	    return 1;
637169689Skan	  mutex->owner = me;
638169689Skan	}
639169689Skan
640169689Skan      mutex->depth++;
641169689Skan    }
642169689Skan  return 0;
643169689Skan}
644169689Skan
645169689Skanstatic inline int
646169689Skan__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
647169689Skan{
648169689Skan  if (__gthread_active_p ())
649169689Skan    {
650169689Skan      if (--mutex->depth == 0)
651169689Skan	{
652169689Skan	   mutex->owner = (pthread_t) 0;
653169689Skan	   __gthrw_(pthread_mutex_unlock) (&mutex->actual);
654169689Skan	}
655169689Skan    }
656169689Skan  return 0;
657169689Skan}
658169689Skan
659169689Skan#endif /* _LIBOBJC */
660169689Skan
661169689Skan#endif /* ! GCC_GTHR_POSIX_H */
662