gthr-posix95.h revision 169689
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
118169689Skan   working interface is always exposed.  */
119169689Skan
120169689Skan#if defined(__sun) && defined(__svr4__)
121169689Skan
122169689Skanstatic volatile int __gthread_active = -1;
123169689Skan
124169689Skanstatic void
125169689Skan__gthread_trigger (void)
126169689Skan{
127169689Skan  __gthread_active = 1;
128169689Skan}
129169689Skan
130169689Skanstatic inline int
131169689Skan__gthread_active_p (void)
132169689Skan{
133169689Skan  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
134169689Skan  static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
135169689Skan
136169689Skan  /* Avoid reading __gthread_active twice on the main code path.  */
137169689Skan  int __gthread_active_latest_value = __gthread_active;
138169689Skan
139169689Skan  /* This test is not protected to avoid taking a lock on the main code
140169689Skan     path so every update of __gthread_active in a threaded program must
141169689Skan     be atomic with regard to the result of the test.  */
142169689Skan  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
143169689Skan    {
144169689Skan      if (__gthrw_(pthread_once))
145169689Skan	{
146169689Skan	  /* If this really is a threaded program, then we must ensure that
147169689Skan	     __gthread_active has been set to 1 before exiting this block.  */
148169689Skan	  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
149169689Skan	  __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
150169689Skan	  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
151169689Skan	}
152169689Skan
153169689Skan      /* Make sure we'll never enter this block again.  */
154169689Skan      if (__gthread_active < 0)
155169689Skan	__gthread_active = 0;
156169689Skan
157169689Skan      __gthread_active_latest_value = __gthread_active;
158169689Skan    }
159169689Skan
160169689Skan  return __gthread_active_latest_value != 0;
161169689Skan}
162169689Skan
163169689Skan#else /* not Solaris */
164169689Skan
165169689Skanstatic inline int
166169689Skan__gthread_active_p (void)
167169689Skan{
168169689Skan  static void *const __gthread_active_ptr
169169689Skan    = __extension__ (void *) &__gthrw_(pthread_cancel);
170169689Skan  return __gthread_active_ptr != 0;
171169689Skan}
172169689Skan
173169689Skan#endif /* Solaris */
174169689Skan
175169689Skan#else /* not SUPPORTS_WEAK */
176169689Skan
177169689Skanstatic inline int
178169689Skan__gthread_active_p (void)
179169689Skan{
180169689Skan  return 1;
181169689Skan}
182169689Skan
183169689Skan#endif /* SUPPORTS_WEAK */
184169689Skan
185169689Skan#ifdef _LIBOBJC
186169689Skan
187169689Skan/* This is the config.h file in libobjc/ */
188169689Skan#include <config.h>
189169689Skan
190169689Skan#ifdef HAVE_SCHED_H
191169689Skan# include <sched.h>
192169689Skan#endif
193169689Skan
194169689Skan/* Key structure for maintaining thread specific storage */
195169689Skanstatic pthread_key_t _objc_thread_storage;
196169689Skanstatic pthread_attr_t _objc_thread_attribs;
197169689Skan
198169689Skan/* Thread local storage for a single thread */
199169689Skanstatic void *thread_local_storage = NULL;
200169689Skan
201169689Skan/* Backend initialization functions */
202169689Skan
203169689Skan/* Initialize the threads subsystem.  */
204169689Skanstatic inline int
205169689Skan__gthread_objc_init_thread_system (void)
206169689Skan{
207169689Skan  if (__gthread_active_p ())
208169689Skan    {
209169689Skan      /* Initialize the thread storage key.  */
210169689Skan      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
211169689Skan	{
212169689Skan	  /* The normal default detach state for threads is
213169689Skan	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
214169689Skan	   * when you think they should.  */
215169689Skan	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
216169689Skan	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
217169689Skan					      PTHREAD_CREATE_DETACHED) == 0)
218169689Skan	    return 0;
219169689Skan	}
220169689Skan    }
221169689Skan
222169689Skan  return -1;
223169689Skan}
224169689Skan
225169689Skan/* Close the threads subsystem.  */
226169689Skanstatic inline int
227169689Skan__gthread_objc_close_thread_system (void)
228169689Skan{
229169689Skan  if (__gthread_active_p ()
230169689Skan      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
231169689Skan      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
232169689Skan    return 0;
233169689Skan
234169689Skan  return -1;
235169689Skan}
236169689Skan
237169689Skan/* Backend thread functions */
238169689Skan
239169689Skan/* Create a new thread of execution.  */
240169689Skanstatic inline objc_thread_t
241169689Skan__gthread_objc_thread_detach (void (*func)(void *), void *arg)
242169689Skan{
243169689Skan  objc_thread_t thread_id;
244169689Skan  pthread_t new_thread_handle;
245169689Skan
246169689Skan  if (!__gthread_active_p ())
247169689Skan    return NULL;
248169689Skan
249169689Skan  if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
250169689Skan    thread_id = (objc_thread_t) new_thread_handle;
251169689Skan  else
252169689Skan    thread_id = NULL;
253169689Skan
254169689Skan  return thread_id;
255169689Skan}
256169689Skan
257169689Skan/* Set the current thread's priority.  */
258169689Skanstatic inline int
259169689Skan__gthread_objc_thread_set_priority (int priority)
260169689Skan{
261169689Skan  if (!__gthread_active_p ())
262169689Skan    return -1;
263169689Skan  else
264169689Skan    {
265169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING
266169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
267169689Skan      pthread_t thread_id = __gthrw_(pthread_self) ();
268169689Skan      int policy;
269169689Skan      struct sched_param params;
270169689Skan      int priority_min, priority_max;
271169689Skan
272169689Skan      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
273169689Skan	{
274169689Skan	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
275169689Skan	    return -1;
276169689Skan
277169689Skan	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
278169689Skan	    return -1;
279169689Skan
280169689Skan	  if (priority > priority_max)
281169689Skan	    priority = priority_max;
282169689Skan	  else if (priority < priority_min)
283169689Skan	    priority = priority_min;
284169689Skan	  params.sched_priority = priority;
285169689Skan
286169689Skan	  /*
287169689Skan	   * The solaris 7 and several other man pages incorrectly state that
288169689Skan	   * this should be a pointer to policy but pthread.h is universally
289169689Skan	   * at odds with this.
290169689Skan	   */
291169689Skan	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
292169689Skan	    return 0;
293169689Skan	}
294169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
295169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */
296169689Skan      return -1;
297169689Skan    }
298169689Skan}
299169689Skan
300169689Skan/* Return the current thread's priority.  */
301169689Skanstatic inline int
302169689Skan__gthread_objc_thread_get_priority (void)
303169689Skan{
304169689Skan#ifdef _POSIX_PRIORITY_SCHEDULING
305169689Skan#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
306169689Skan  if (__gthread_active_p ())
307169689Skan    {
308169689Skan      int policy;
309169689Skan      struct sched_param params;
310169689Skan
311169689Skan      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
312169689Skan	return params.sched_priority;
313169689Skan      else
314169689Skan	return -1;
315169689Skan    }
316169689Skan  else
317169689Skan#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
318169689Skan#endif /* _POSIX_PRIORITY_SCHEDULING */
319169689Skan    return OBJC_THREAD_INTERACTIVE_PRIORITY;
320169689Skan}
321169689Skan
322169689Skan/* Yield our process time to another thread.  */
323169689Skanstatic inline void
324169689Skan__gthread_objc_thread_yield (void)
325169689Skan{
326169689Skan  if (__gthread_active_p ())
327169689Skan    __gthrw_(sched_yield) ();
328169689Skan}
329169689Skan
330169689Skan/* Terminate the current thread.  */
331169689Skanstatic inline int
332169689Skan__gthread_objc_thread_exit (void)
333169689Skan{
334169689Skan  if (__gthread_active_p ())
335169689Skan    /* exit the thread */
336169689Skan    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
337169689Skan
338169689Skan  /* Failed if we reached here */
339169689Skan  return -1;
340169689Skan}
341169689Skan
342169689Skan/* Returns an integer value which uniquely describes a thread.  */
343169689Skanstatic inline objc_thread_t
344169689Skan__gthread_objc_thread_id (void)
345169689Skan{
346169689Skan  if (__gthread_active_p ())
347169689Skan    return (objc_thread_t) __gthrw_(pthread_self) ();
348169689Skan  else
349169689Skan    return (objc_thread_t) 1;
350169689Skan}
351169689Skan
352169689Skan/* Sets the thread's local storage pointer.  */
353169689Skanstatic inline int
354169689Skan__gthread_objc_thread_set_data (void *value)
355169689Skan{
356169689Skan  if (__gthread_active_p ())
357169689Skan    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
358169689Skan  else
359169689Skan    {
360169689Skan      thread_local_storage = value;
361169689Skan      return 0;
362169689Skan    }
363169689Skan}
364169689Skan
365169689Skan/* Returns the thread's local storage pointer.  */
366169689Skanstatic inline void *
367169689Skan__gthread_objc_thread_get_data (void)
368169689Skan{
369169689Skan  if (__gthread_active_p ())
370169689Skan    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
371169689Skan  else
372169689Skan    return thread_local_storage;
373169689Skan}
374169689Skan
375169689Skan/* Backend mutex functions */
376169689Skan
377169689Skan/* Allocate a mutex.  */
378169689Skanstatic inline int
379169689Skan__gthread_objc_mutex_allocate (objc_mutex_t mutex)
380169689Skan{
381169689Skan  if (__gthread_active_p ())
382169689Skan    {
383169689Skan      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
384169689Skan
385169689Skan      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
386169689Skan	{
387169689Skan	  objc_free (mutex->backend);
388169689Skan	  mutex->backend = NULL;
389169689Skan	  return -1;
390169689Skan	}
391169689Skan    }
392169689Skan
393169689Skan  return 0;
394169689Skan}
395169689Skan
396169689Skan/* Deallocate a mutex.  */
397169689Skanstatic inline int
398169689Skan__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
399169689Skan{
400169689Skan  if (__gthread_active_p ())
401169689Skan    {
402169689Skan      int count;
403169689Skan
404169689Skan      /*
405169689Skan       * Posix Threads specifically require that the thread be unlocked
406169689Skan       * for __gthrw_(pthread_mutex_destroy) to work.
407169689Skan       */
408169689Skan
409169689Skan      do
410169689Skan	{
411169689Skan	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
412169689Skan	  if (count < 0)
413169689Skan	    return -1;
414169689Skan	}
415169689Skan      while (count);
416169689Skan
417169689Skan      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
418169689Skan	return -1;
419169689Skan
420169689Skan      objc_free (mutex->backend);
421169689Skan      mutex->backend = NULL;
422169689Skan    }
423169689Skan  return 0;
424169689Skan}
425169689Skan
426169689Skan/* Grab a lock on a mutex.  */
427169689Skanstatic inline int
428169689Skan__gthread_objc_mutex_lock (objc_mutex_t mutex)
429169689Skan{
430169689Skan  if (__gthread_active_p ()
431169689Skan      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
432169689Skan    {
433169689Skan      return -1;
434169689Skan    }
435169689Skan
436169689Skan  return 0;
437169689Skan}
438169689Skan
439169689Skan/* Try to grab a lock on a mutex.  */
440169689Skanstatic inline int
441169689Skan__gthread_objc_mutex_trylock (objc_mutex_t mutex)
442169689Skan{
443169689Skan  if (__gthread_active_p ()
444169689Skan      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
445169689Skan    {
446169689Skan      return -1;
447169689Skan    }
448169689Skan
449169689Skan  return 0;
450169689Skan}
451169689Skan
452169689Skan/* Unlock the mutex */
453169689Skanstatic inline int
454169689Skan__gthread_objc_mutex_unlock (objc_mutex_t mutex)
455169689Skan{
456169689Skan  if (__gthread_active_p ()
457169689Skan      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
458169689Skan    {
459169689Skan      return -1;
460169689Skan    }
461169689Skan
462169689Skan  return 0;
463169689Skan}
464169689Skan
465169689Skan/* Backend condition mutex functions */
466169689Skan
467169689Skan/* Allocate a condition.  */
468169689Skanstatic inline int
469169689Skan__gthread_objc_condition_allocate (objc_condition_t condition)
470169689Skan{
471169689Skan  if (__gthread_active_p ())
472169689Skan    {
473169689Skan      condition->backend = objc_malloc (sizeof (pthread_cond_t));
474169689Skan
475169689Skan      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
476169689Skan	{
477169689Skan	  objc_free (condition->backend);
478169689Skan	  condition->backend = NULL;
479169689Skan	  return -1;
480169689Skan	}
481169689Skan    }
482169689Skan
483169689Skan  return 0;
484169689Skan}
485169689Skan
486169689Skan/* Deallocate a condition.  */
487169689Skanstatic inline int
488169689Skan__gthread_objc_condition_deallocate (objc_condition_t condition)
489169689Skan{
490169689Skan  if (__gthread_active_p ())
491169689Skan    {
492169689Skan      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
493169689Skan	return -1;
494169689Skan
495169689Skan      objc_free (condition->backend);
496169689Skan      condition->backend = NULL;
497169689Skan    }
498169689Skan  return 0;
499169689Skan}
500169689Skan
501169689Skan/* Wait on the condition */
502169689Skanstatic inline int
503169689Skan__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
504169689Skan{
505169689Skan  if (__gthread_active_p ())
506169689Skan    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
507169689Skan			      (pthread_mutex_t *) mutex->backend);
508169689Skan  else
509169689Skan    return 0;
510169689Skan}
511169689Skan
512169689Skan/* Wake up all threads waiting on this condition.  */
513169689Skanstatic inline int
514169689Skan__gthread_objc_condition_broadcast (objc_condition_t condition)
515169689Skan{
516169689Skan  if (__gthread_active_p ())
517169689Skan    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
518169689Skan  else
519169689Skan    return 0;
520169689Skan}
521169689Skan
522169689Skan/* Wake up one thread waiting on this condition.  */
523169689Skanstatic inline int
524169689Skan__gthread_objc_condition_signal (objc_condition_t condition)
525169689Skan{
526169689Skan  if (__gthread_active_p ())
527169689Skan    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
528169689Skan  else
529169689Skan    return 0;
530169689Skan}
531169689Skan
532169689Skan#else /* _LIBOBJC */
533169689Skan
534169689Skanstatic inline int
535169689Skan__gthread_once (__gthread_once_t *once, void (*func) (void))
536169689Skan{
537169689Skan  if (__gthread_active_p ())
538169689Skan    return __gthrw_(pthread_once) (once, func);
539169689Skan  else
540169689Skan    return -1;
541169689Skan}
542169689Skan
543169689Skanstatic inline int
544169689Skan__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
545169689Skan{
546169689Skan  return __gthrw_(pthread_key_create) (key, dtor);
547169689Skan}
548169689Skan
549169689Skanstatic inline int
550169689Skan__gthread_key_delete (__gthread_key_t key)
551169689Skan{
552169689Skan  return __gthrw_(pthread_key_delete) (key);
553169689Skan}
554169689Skan
555169689Skanstatic inline void *
556169689Skan__gthread_getspecific (__gthread_key_t key)
557169689Skan{
558169689Skan  return __gthrw_(pthread_getspecific) (key);
559169689Skan}
560169689Skan
561169689Skanstatic inline int
562169689Skan__gthread_setspecific (__gthread_key_t key, const void *ptr)
563169689Skan{
564169689Skan  return __gthrw_(pthread_setspecific) (key, ptr);
565169689Skan}
566169689Skan
567169689Skanstatic inline int
568169689Skan__gthread_mutex_lock (__gthread_mutex_t *mutex)
569169689Skan{
570169689Skan  if (__gthread_active_p ())
571169689Skan    return __gthrw_(pthread_mutex_lock) (mutex);
572169689Skan  else
573169689Skan    return 0;
574169689Skan}
575169689Skan
576169689Skanstatic inline int
577169689Skan__gthread_mutex_trylock (__gthread_mutex_t *mutex)
578169689Skan{
579169689Skan  if (__gthread_active_p ())
580169689Skan    return __gthrw_(pthread_mutex_trylock) (mutex);
581169689Skan  else
582169689Skan    return 0;
583169689Skan}
584169689Skan
585169689Skanstatic inline int
586169689Skan__gthread_mutex_unlock (__gthread_mutex_t *mutex)
587169689Skan{
588169689Skan  if (__gthread_active_p ())
589169689Skan    return __gthrw_(pthread_mutex_unlock) (mutex);
590169689Skan  else
591169689Skan    return 0;
592169689Skan}
593169689Skan
594169689Skanstatic inline int
595169689Skan__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
596169689Skan{
597169689Skan  mutex->depth = 0;
598169689Skan  mutex->owner = (pthread_t) 0;
599169689Skan  return __gthrw_(pthread_mutex_init) (&mutex->actual, NULL);
600169689Skan}
601169689Skan
602169689Skanstatic inline int
603169689Skan__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
604169689Skan{
605169689Skan  if (__gthread_active_p ())
606169689Skan    {
607169689Skan      pthread_t me = __gthrw_(pthread_self) ();
608169689Skan
609169689Skan      if (mutex->owner != me)
610169689Skan	{
611169689Skan	  __gthrw_(pthread_mutex_lock) (&mutex->actual);
612169689Skan	  mutex->owner = me;
613169689Skan	}
614169689Skan
615169689Skan      mutex->depth++;
616169689Skan    }
617169689Skan  return 0;
618169689Skan}
619169689Skan
620169689Skanstatic inline int
621169689Skan__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
622169689Skan{
623169689Skan  if (__gthread_active_p ())
624169689Skan    {
625169689Skan      pthread_t me = __gthrw_(pthread_self) ();
626169689Skan
627169689Skan      if (mutex->owner != me)
628169689Skan	{
629169689Skan	  if (__gthrw_(pthread_mutex_trylock) (&mutex->actual))
630169689Skan	    return 1;
631169689Skan	  mutex->owner = me;
632169689Skan	}
633169689Skan
634169689Skan      mutex->depth++;
635169689Skan    }
636169689Skan  return 0;
637169689Skan}
638169689Skan
639169689Skanstatic inline int
640169689Skan__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
641169689Skan{
642169689Skan  if (__gthread_active_p ())
643169689Skan    {
644169689Skan      if (--mutex->depth == 0)
645169689Skan	{
646169689Skan	   mutex->owner = (pthread_t) 0;
647169689Skan	   __gthrw_(pthread_mutex_unlock) (&mutex->actual);
648169689Skan	}
649169689Skan    }
650169689Skan  return 0;
651169689Skan}
652169689Skan
653169689Skan#endif /* _LIBOBJC */
654169689Skan
655169689Skan#endif /* ! GCC_GTHR_POSIX_H */
656