gthr-posix.h 23.6 KB
Newer Older
1
/* Threads compatibility routines for libgcc2 and libobjc.  */
2
/* Compile this one with gcc.  */
3
/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
4

5
This file is part of GCC.
6

7 8
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
11

12 13 14 15
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.
16

17 18 19 20 21 22 23 24
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.

You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */
25

26 27
#ifndef GCC_GTHR_POSIX_H
#define GCC_GTHR_POSIX_H
28 29

/* POSIX threads specific definitions.
30
   Easy, since the interface is just one-to-one mapping.  */
31 32

#define __GTHREADS 1
33
#define __GTHREADS_CXX0X 1
34 35

#include <pthread.h>
36 37 38 39 40 41 42 43 44 45

#if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \
     || !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK))
# include <unistd.h>
# if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 0
#  define _GTHREAD_USE_MUTEX_TIMEDLOCK 1
# else
#  define _GTHREAD_USE_MUTEX_TIMEDLOCK 0
# endif
#endif
46

47
typedef pthread_t __gthread_t;
48 49 50
typedef pthread_key_t __gthread_key_t;
typedef pthread_once_t __gthread_once_t;
typedef pthread_mutex_t __gthread_mutex_t;
51
typedef pthread_mutex_t __gthread_recursive_mutex_t;
52
typedef pthread_cond_t __gthread_cond_t;
53
typedef struct timespec __gthread_time_t;
54 55 56

/* POSIX like conditional variables are supported.  Please look at comments
   in gthr.h for details. */
H.J. Lu committed
57
#define __GTHREAD_HAS_COND	1
58 59

#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
60
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
61
#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
62 63 64 65
#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
66
#else
67
#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
68
#endif
69
#define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
70
#define __GTHREAD_TIME_INIT {0,0}
71

72 73 74 75 76 77 78 79 80 81 82 83 84
#ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
# undef __GTHREAD_MUTEX_INIT
#endif
#ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC
# undef __GTHREAD_RECURSIVE_MUTEX_INIT
# undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
# define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
#endif
#ifdef _GTHREAD_USE_COND_INIT_FUNC
# undef __GTHREAD_COND_INIT
# define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
#endif

85
#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
86 87 88
# ifndef __gthrw_pragma
#  define __gthrw_pragma(pragma)
# endif
89
# define __gthrw2(name,name2,type) \
90 91
  static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
  __gthrw_pragma(weak type)
92
# define __gthrw_(name) __gthrw_ ## name
93
#else
94
# define __gthrw2(name,name2,type)
95
# define __gthrw_(name) name
96
#endif
97

98
/* Typically, __gthrw_foo is a weak reference to symbol foo.  */
99
#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
Roger Sayle committed
100

101 102 103
__gthrw(pthread_once)
__gthrw(pthread_getspecific)
__gthrw(pthread_setspecific)
104

105
__gthrw(pthread_create)
106 107 108 109
__gthrw(pthread_join)
__gthrw(pthread_equal)
__gthrw(pthread_self)
__gthrw(pthread_detach)
110
#ifndef __BIONIC__
111
__gthrw(pthread_cancel)
112
#endif
113 114
__gthrw(sched_yield)

115 116
__gthrw(pthread_mutex_lock)
__gthrw(pthread_mutex_trylock)
117
#if _GTHREAD_USE_MUTEX_TIMEDLOCK
118
__gthrw(pthread_mutex_timedlock)
119
#endif
120
__gthrw(pthread_mutex_unlock)
Roger Sayle committed
121
__gthrw(pthread_mutex_init)
122
__gthrw(pthread_mutex_destroy)
123

124
__gthrw(pthread_cond_init)
125
__gthrw(pthread_cond_broadcast)
126
__gthrw(pthread_cond_signal)
127
__gthrw(pthread_cond_wait)
128 129
__gthrw(pthread_cond_timedwait)
__gthrw(pthread_cond_destroy)
Roger Sayle committed
130 131 132

__gthrw(pthread_key_create)
__gthrw(pthread_key_delete)
133 134 135
__gthrw(pthread_mutexattr_init)
__gthrw(pthread_mutexattr_settype)
__gthrw(pthread_mutexattr_destroy)
136

137

138
#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
139
/* Objective-C.  */
140
__gthrw(pthread_exit)
141
#ifdef _POSIX_PRIORITY_SCHEDULING
142
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
143 144
__gthrw(sched_get_priority_max)
__gthrw(sched_get_priority_min)
145
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
146
#endif /* _POSIX_PRIORITY_SCHEDULING */
147 148 149
__gthrw(pthread_attr_destroy)
__gthrw(pthread_attr_init)
__gthrw(pthread_attr_setdetachstate)
150
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
151 152
__gthrw(pthread_getschedparam)
__gthrw(pthread_setschedparam)
153
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
154
#endif /* _LIBOBJC || _LIBOBJC_WEAK */
155

156 157
#if SUPPORTS_WEAK && GTHREAD_USE_WEAK

158 159 160 161 162 163
/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
   -pthreads is not specified.  The functions are dummies and most return an
   error value.  However pthread_once returns 0 without invoking the routine
   it is passed so we cannot pretend that the interface is active if -pthreads
   is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
   we need to play the usual game with weak symbols.  On Solaris 10 and up, a
164 165 166 167
   working interface is always exposed.  On FreeBSD 6 and later, libc also
   exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
   to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
   which means the alternate __gthread_active_p below cannot be used there.  */
168

169
#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211

static volatile int __gthread_active = -1;

static void
__gthread_trigger (void)
{
  __gthread_active = 1;
}

static inline int
__gthread_active_p (void)
{
  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
  static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;

  /* Avoid reading __gthread_active twice on the main code path.  */
  int __gthread_active_latest_value = __gthread_active;

  /* This test is not protected to avoid taking a lock on the main code
     path so every update of __gthread_active in a threaded program must
     be atomic with regard to the result of the test.  */
  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
    {
      if (__gthrw_(pthread_once))
	{
	  /* If this really is a threaded program, then we must ensure that
	     __gthread_active has been set to 1 before exiting this block.  */
	  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
	  __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
	  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
	}

      /* Make sure we'll never enter this block again.  */
      if (__gthread_active < 0)
	__gthread_active = 0;

      __gthread_active_latest_value = __gthread_active;
    }

  return __gthread_active_latest_value != 0;
}

212
#else /* neither FreeBSD nor Solaris */
213

214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
/* For a program to be multi-threaded the only thing that it certainly must
   be using is pthread_create.  However, there may be other libraries that
   intercept pthread_create with their own definitions to wrap pthreads
   functionality for some purpose.  In those cases, pthread_create being
   defined might not necessarily mean that libpthread is actually linked
   in.

   For the GNU C library, we can use a known internal name.  This is always
   available in the ABI, but no other library would define it.  That is
   ideal, since any public pthread function might be intercepted just as
   pthread_create might be.  __pthread_key_create is an "internal"
   implementation symbol, but it is part of the public exported ABI.  Also,
   it's among the symbols that the static libpthread.a always links in
   whenever pthread_create is used, so there is no danger of a false
   negative result in any statically-linked, multi-threaded program.

   For others, we choose pthread_cancel as a function that seems unlikely
   to be redefined by an interceptor library.  The bionic (Android) C
   library does not provide pthread_cancel, so we do use pthread_create
   there (and interceptor libraries lose).  */

#ifdef __GLIBC__
__gthrw2(__gthrw_(__pthread_key_create),
	 __pthread_key_create,
	 pthread_key_create)
# define GTHR_ACTIVE_PROXY	__gthrw_(__pthread_key_create)
#elif defined (__BIONIC__)
# define GTHR_ACTIVE_PROXY	__gthrw_(pthread_create)
#else
# define GTHR_ACTIVE_PROXY	__gthrw_(pthread_cancel)
#endif

246
static inline int
247
__gthread_active_p (void)
248
{
249
  static void *const __gthread_active_ptr
250
    = __extension__ (void *) &GTHR_ACTIVE_PROXY;
251 252 253
  return __gthread_active_ptr != 0;
}

254
#endif /* FreeBSD or Solaris */
255

256 257
#else /* not SUPPORTS_WEAK */

258 259 260 261
/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
   calls in shared flavors of the HP-UX C library.  Most of the stubs
   have no functionality.  The details are described in the "libc cumulative
   patch" for each subversion of HP-UX 11.  There are two special interfaces
262
   provided for checking whether an application is linked to a shared pthread
263
   library or not.  However, these interfaces aren't available in early
264 265 266 267 268 269 270 271 272 273
   libpthread libraries.  We also need a test that works for archive
   libraries.  We can't use pthread_once as some libc versions call the
   init function.  We also can't use pthread_create or pthread_attr_init
   as these create a thread and thereby prevent changing the default stack
   size.  The function pthread_default_stacksize_np is available in both
   the archive and shared versions of libpthread.   It can be used to
   determine the default pthread stack size.  There is a stub in some
   shared libc versions which returns a zero size if pthreads are not
   active.  We provide an equivalent stub to handle cases where libc
   doesn't provide one.  */
274 275 276 277 278 279 280 281 282 283

#if defined(__hppa__) && defined(__hpux__)

static volatile int __gthread_active = -1;

static inline int
__gthread_active_p (void)
{
  /* Avoid reading __gthread_active twice on the main code path.  */
  int __gthread_active_latest_value = __gthread_active;
284
  size_t __s;
285 286 287

  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
    {
288 289
      pthread_default_stacksize_np (0, &__s);
      __gthread_active = __s ? 1 : 0;
290 291 292 293 294 295 296 297
      __gthread_active_latest_value = __gthread_active;
    }

  return __gthread_active_latest_value != 0;
}

#else /* not hppa-hpux */

298
static inline int
299
__gthread_active_p (void)
300 301 302 303
{
  return 1;
}

304 305
#endif /* hppa-hpux */

306 307
#endif /* SUPPORTS_WEAK */

308 309
#ifdef _LIBOBJC

310 311 312 313 314 315 316
/* This is the config.h file in libobjc/ */
#include <config.h>

#ifdef HAVE_SCHED_H
# include <sched.h>
#endif

317 318
/* Key structure for maintaining thread specific storage */
static pthread_key_t _objc_thread_storage;
319
static pthread_attr_t _objc_thread_attribs;
320 321 322 323 324 325

/* Thread local storage for a single thread */
static void *thread_local_storage = NULL;

/* Backend initialization functions */

326
/* Initialize the threads subsystem.  */
327
static inline int
328
__gthread_objc_init_thread_system (void)
329 330
{
  if (__gthread_active_p ())
331
    {
332
      /* Initialize the thread storage key.  */
333
      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
334 335 336 337
	{
	  /* The normal default detach state for threads is
	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
	   * when you think they should.  */
338 339
	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
340
					      PTHREAD_CREATE_DETACHED) == 0)
341 342
	    return 0;
	}
343
    }
344 345

  return -1;
346 347
}

348
/* Close the threads subsystem.  */
349
static inline int
350
__gthread_objc_close_thread_system (void)
351
{
352
  if (__gthread_active_p ()
353 354
      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
355
    return 0;
356 357

  return -1;
358 359 360 361
}

/* Backend thread functions */

362
/* Create a new thread of execution.  */
363
static inline objc_thread_t
364
__gthread_objc_thread_detach (void (*func)(void *), void *arg)
365 366 367 368 369 370
{
  objc_thread_t thread_id;
  pthread_t new_thread_handle;

  if (!__gthread_active_p ())
    return NULL;
371

372 373
  if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs,
				  (void *) func, arg)))
374
    thread_id = (objc_thread_t) new_thread_handle;
375 376
  else
    thread_id = NULL;
377

378 379 380
  return thread_id;
}

381
/* Set the current thread's priority.  */
382
static inline int
383
__gthread_objc_thread_set_priority (int priority)
384
{
385
  if (!__gthread_active_p ())
386
    return -1;
387 388
  else
    {
389
#ifdef _POSIX_PRIORITY_SCHEDULING
390
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
391
      pthread_t thread_id = __gthrw_(pthread_self) ();
392 393 394
      int policy;
      struct sched_param params;
      int priority_min, priority_max;
395

396
      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
397
	{
398
	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
399 400
	    return -1;

401
	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
402
	    return -1;
403

404 405 406 407 408 409 410 411 412 413 414
	  if (priority > priority_max)
	    priority = priority_max;
	  else if (priority < priority_min)
	    priority = priority_min;
	  params.sched_priority = priority;

	  /*
	   * The solaris 7 and several other man pages incorrectly state that
	   * this should be a pointer to policy but pthread.h is universally
	   * at odds with this.
	   */
415
	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
416 417
	    return 0;
	}
418
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
419
#endif /* _POSIX_PRIORITY_SCHEDULING */
420 421
      return -1;
    }
422 423
}

424
/* Return the current thread's priority.  */
425
static inline int
426
__gthread_objc_thread_get_priority (void)
427
{
428
#ifdef _POSIX_PRIORITY_SCHEDULING
429
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
430
  if (__gthread_active_p ())
431 432 433 434
    {
      int policy;
      struct sched_param params;

435
      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
436
	return params.sched_priority;
437
      else
438
	return -1;
439
    }
440
  else
441
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
442
#endif /* _POSIX_PRIORITY_SCHEDULING */
443 444 445
    return OBJC_THREAD_INTERACTIVE_PRIORITY;
}

446
/* Yield our process time to another thread.  */
447
static inline void
448
__gthread_objc_thread_yield (void)
449 450
{
  if (__gthread_active_p ())
451
    __gthrw_(sched_yield) ();
452 453
}

454
/* Terminate the current thread.  */
455
static inline int
456
__gthread_objc_thread_exit (void)
457 458 459
{
  if (__gthread_active_p ())
    /* exit the thread */
460
    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
461 462 463 464 465

  /* Failed if we reached here */
  return -1;
}

466
/* Returns an integer value which uniquely describes a thread.  */
467
static inline objc_thread_t
468
__gthread_objc_thread_id (void)
469 470
{
  if (__gthread_active_p ())
471
    return (objc_thread_t) __gthrw_(pthread_self) ();
472
  else
473
    return (objc_thread_t) 1;
474 475
}

476
/* Sets the thread's local storage pointer.  */
477
static inline int
478
__gthread_objc_thread_set_data (void *value)
479 480
{
  if (__gthread_active_p ())
481
    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
482 483 484 485 486 487 488
  else
    {
      thread_local_storage = value;
      return 0;
    }
}

489
/* Returns the thread's local storage pointer.  */
490
static inline void *
491
__gthread_objc_thread_get_data (void)
492 493
{
  if (__gthread_active_p ())
494
    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
495 496 497 498 499 500
  else
    return thread_local_storage;
}

/* Backend mutex functions */

501
/* Allocate a mutex.  */
502
static inline int
503
__gthread_objc_mutex_allocate (objc_mutex_t mutex)
504 505 506
{
  if (__gthread_active_p ())
    {
507
      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
508

509
      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
510
	{
511
	  objc_free (mutex->backend);
512 513 514 515 516 517 518 519
	  mutex->backend = NULL;
	  return -1;
	}
    }

  return 0;
}

520
/* Deallocate a mutex.  */
521
static inline int
522
__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
523 524 525 526 527 528 529
{
  if (__gthread_active_p ())
    {
      int count;

      /*
       * Posix Threads specifically require that the thread be unlocked
530
       * for __gthrw_(pthread_mutex_destroy) to work.
531 532 533 534
       */

      do
	{
535
	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
536 537 538 539 540
	  if (count < 0)
	    return -1;
	}
      while (count);

541
      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
542 543
	return -1;

544
      objc_free (mutex->backend);
545 546 547 548 549
      mutex->backend = NULL;
    }
  return 0;
}

550
/* Grab a lock on a mutex.  */
551
static inline int
552
__gthread_objc_mutex_lock (objc_mutex_t mutex)
553
{
554
  if (__gthread_active_p ()
555
      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
556 557 558 559 560
    {
      return -1;
    }

  return 0;
561 562
}

563
/* Try to grab a lock on a mutex.  */
564
static inline int
565
__gthread_objc_mutex_trylock (objc_mutex_t mutex)
566
{
567
  if (__gthread_active_p ()
568
      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
569 570 571 572 573
    {
      return -1;
    }

  return 0;
574 575 576 577
}

/* Unlock the mutex */
static inline int
578
__gthread_objc_mutex_unlock (objc_mutex_t mutex)
579
{
580
  if (__gthread_active_p ()
581
      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
582 583 584 585 586
    {
      return -1;
    }

  return 0;
587 588 589 590
}

/* Backend condition mutex functions */

591
/* Allocate a condition.  */
592
static inline int
593
__gthread_objc_condition_allocate (objc_condition_t condition)
594 595 596
{
  if (__gthread_active_p ())
    {
597
      condition->backend = objc_malloc (sizeof (pthread_cond_t));
598

599
      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
600
	{
601
	  objc_free (condition->backend);
602 603 604 605 606 607 608 609
	  condition->backend = NULL;
	  return -1;
	}
    }

  return 0;
}

610
/* Deallocate a condition.  */
611
static inline int
612
__gthread_objc_condition_deallocate (objc_condition_t condition)
613 614 615
{
  if (__gthread_active_p ())
    {
616
      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
617 618
	return -1;

619
      objc_free (condition->backend);
620 621 622 623 624 625 626
      condition->backend = NULL;
    }
  return 0;
}

/* Wait on the condition */
static inline int
627
__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
628 629
{
  if (__gthread_active_p ())
630
    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
631
			      (pthread_mutex_t *) mutex->backend);
632 633 634 635
  else
    return 0;
}

636
/* Wake up all threads waiting on this condition.  */
637
static inline int
638
__gthread_objc_condition_broadcast (objc_condition_t condition)
639 640
{
  if (__gthread_active_p ())
641
    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
642 643 644 645
  else
    return 0;
}

646
/* Wake up one thread waiting on this condition.  */
647
static inline int
648
__gthread_objc_condition_signal (objc_condition_t condition)
649 650
{
  if (__gthread_active_p ())
651
    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
652 653 654 655 656 657
  else
    return 0;
}

#else /* _LIBOBJC */

658
static inline int
659 660
__gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
		  void *__args)
661
{
662
  return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
663 664 665
}

static inline int
666
__gthread_join (__gthread_t __threadid, void **__value_ptr)
667
{
668
  return __gthrw_(pthread_join) (__threadid, __value_ptr);
669 670 671
}

static inline int
672
__gthread_detach (__gthread_t __threadid)
673
{
674
  return __gthrw_(pthread_detach) (__threadid);
675 676 677
}

static inline int
678
__gthread_equal (__gthread_t __t1, __gthread_t __t2)
679
{
680
  return __gthrw_(pthread_equal) (__t1, __t2);
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
}

static inline __gthread_t
__gthread_self (void)
{
  return __gthrw_(pthread_self) ();
}

static inline int
__gthread_yield (void)
{
  return __gthrw_(sched_yield) ();
}

static inline int
696
__gthread_once (__gthread_once_t *__once, void (*__func) (void))
697 698
{
  if (__gthread_active_p ())
699
    return __gthrw_(pthread_once) (__once, __func);
700 701 702 703 704
  else
    return -1;
}

static inline int
705
__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
706
{
707
  return __gthrw_(pthread_key_create) (__key, __dtor);
708 709 710
}

static inline int
711
__gthread_key_delete (__gthread_key_t __key)
712
{
713
  return __gthrw_(pthread_key_delete) (__key);
714 715 716
}

static inline void *
717
__gthread_getspecific (__gthread_key_t __key)
718
{
719
  return __gthrw_(pthread_getspecific) (__key);
720 721 722
}

static inline int
723
__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
724
{
725
  return __gthrw_(pthread_setspecific) (__key, __ptr);
726 727
}

728 729 730 731 732 733
static inline void
__gthread_mutex_init_function (__gthread_mutex_t *__mutex)
{
  if (__gthread_active_p ())
    __gthrw_(pthread_mutex_init) (__mutex, NULL);
}
734 735

static inline int
736
__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
737 738
{
  if (__gthread_active_p ())
739
    return __gthrw_(pthread_mutex_destroy) (__mutex);
740 741 742 743 744
  else
    return 0;
}

static inline int
745
__gthread_mutex_lock (__gthread_mutex_t *__mutex)
746 747
{
  if (__gthread_active_p ())
748
    return __gthrw_(pthread_mutex_lock) (__mutex);
749 750 751 752 753
  else
    return 0;
}

static inline int
754
__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
755 756
{
  if (__gthread_active_p ())
757
    return __gthrw_(pthread_mutex_trylock) (__mutex);
758 759 760 761
  else
    return 0;
}

762
#if _GTHREAD_USE_MUTEX_TIMEDLOCK
763
static inline int
764 765
__gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
			   const __gthread_time_t *__abs_timeout)
766 767
{
  if (__gthread_active_p ())
768
    return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout);
769 770 771 772 773
  else
    return 0;
}
#endif

774
static inline int
775
__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
776 777
{
  if (__gthread_active_p ())
778
    return __gthrw_(pthread_mutex_unlock) (__mutex);
779 780 781 782
  else
    return 0;
}

783 784
#if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \
  || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
785
static inline int
786
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
787 788 789
{
  if (__gthread_active_p ())
    {
790 791 792 793 794 795 796 797 798 799 800 801
      pthread_mutexattr_t __attr;
      int __r;

      __r = __gthrw_(pthread_mutexattr_init) (&__attr);
      if (!__r)
	__r = __gthrw_(pthread_mutexattr_settype) (&__attr,
						   PTHREAD_MUTEX_RECURSIVE);
      if (!__r)
	__r = __gthrw_(pthread_mutex_init) (__mutex, &__attr);
      if (!__r)
	__r = __gthrw_(pthread_mutexattr_destroy) (&__attr);
      return __r;
802
    }
803
  return 0;
804 805 806 807
}
#endif

static inline int
808
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
809
{
810
  return __gthread_mutex_lock (__mutex);
811 812 813
}

static inline int
814
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
815
{
816
  return __gthread_mutex_trylock (__mutex);
817 818
}

819
#if _GTHREAD_USE_MUTEX_TIMEDLOCK
820
static inline int
821 822
__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
				     const __gthread_time_t *__abs_timeout)
823
{
824
  return __gthread_mutex_timedlock (__mutex, __abs_timeout);
825 826 827
}
#endif

828
static inline int
829
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
830
{
831
  return __gthread_mutex_unlock (__mutex);
832 833
}

834 835 836 837 838 839
static inline int
__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
{
  return __gthread_mutex_destroy (__mutex);
}

840 841 842 843 844 845 846 847 848
#ifdef _GTHREAD_USE_COND_INIT_FUNC
static inline void
__gthread_cond_init_function (__gthread_cond_t *__cond)
{
  if (__gthread_active_p ())
    __gthrw_(pthread_cond_init) (__cond, NULL);
}
#endif

849
static inline int
850
__gthread_cond_broadcast (__gthread_cond_t *__cond)
851
{
852
  return __gthrw_(pthread_cond_broadcast) (__cond);
853 854 855
}

static inline int
856
__gthread_cond_signal (__gthread_cond_t *__cond)
857
{
858
  return __gthrw_(pthread_cond_signal) (__cond);
859 860 861
}

static inline int
862
__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
863
{
864
  return __gthrw_(pthread_cond_wait) (__cond, __mutex);
865 866 867
}

static inline int
868 869
__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
			  const __gthread_time_t *__abs_timeout)
870
{
871
  return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
872 873 874
}

static inline int
875 876
__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
			       __gthread_recursive_mutex_t *__mutex)
877
{
878
  return __gthread_cond_wait (__cond, __mutex);
879 880
}

881
static inline int
882
__gthread_cond_destroy (__gthread_cond_t* __cond)
883
{
884
  return __gthrw_(pthread_cond_destroy) (__cond);
885 886
}

887 888
#endif /* _LIBOBJC */

889
#endif /* ! GCC_GTHR_POSIX_H */