1281348Scy/* This file is automatically generated.  DO NOT EDIT! */
2281348Scy/* Generated from: 	NetBSD: mknative-gcc,v 1.45 2009/12/17 15:48:13 uebayasi Exp  */
3281348Scy/* Generated from: NetBSD: mknative.common,v 1.9 2007/02/05 18:26:01 apb Exp  */
4281348Scy
5281348Scy/* Threads compatibility routines for libgcc2 and libobjc.  */
6281348Scy/* Compile this one with gcc.  */
7281348Scy/* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
8281348Scy   Free Software Foundation, Inc.
9281348Scy
10281348ScyThis file is part of GCC.
11281348Scy
12281348ScyGCC is free software; you can redistribute it and/or modify it under
13281348Scythe terms of the GNU General Public License as published by the Free
14281348ScySoftware Foundation; either version 2, or (at your option) any later
15281348Scyversion.
16281348Scy
17281348ScyGCC is distributed in the hope that it will be useful, but WITHOUT ANY
18281348ScyWARRANTY; without even the implied warranty of MERCHANTABILITY or
19281348ScyFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20281348Scyfor more details.
21281348Scy
22281348ScyYou should have received a copy of the GNU General Public License
23281348Scyalong with GCC; see the file COPYING.  If not, write to the Free
24281348ScySoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
25281348Scy02110-1301, USA.  */
26281348Scy
27281348Scy/* As a special exception, if you link this library with other files,
28281348Scy   some of which are compiled with GCC, to produce an executable,
29281348Scy   this library does not by itself cause the resulting executable
30281348Scy   to be covered by the GNU General Public License.
31281348Scy   This exception does not however invalidate any other reasons why
32281348Scy   the executable file might be covered by the GNU General Public License.  */
33281348Scy
34281348Scy#ifndef _GLIBCXX_GCC_GTHR_POSIX_H
35290000Sglebius#define _GLIBCXX_GCC_GTHR_POSIX_H
36281348Scy
37281348Scy/* POSIX threads specific definitions.
38290000Sglebius   Easy, since the interface is just one-to-one mapping.  */
39281348Scy
40281348Scy#define __GTHREADS 1
41281348Scy
42281348Scy/* Some implementations of <pthread.h> require this to be defined.  */
43281348Scy#if !defined(_REENTRANT) && defined(__osf__)
44281348Scy#define _REENTRANT 1
45281348Scy#endif
46281348Scy
47281348Scy#include <pthread.h>
48281348Scy#include <unistd.h>
49281348Scy
50281348Scytypedef pthread_key_t __gthread_key_t;
51281348Scytypedef pthread_once_t __gthread_once_t;
52281348Scytypedef pthread_mutex_t __gthread_mutex_t;
53281348Scytypedef pthread_mutex_t __gthread_recursive_mutex_t;
54281348Scy
55281348Scy#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
56281348Scy#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
57281348Scy#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
58281348Scy#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
59281348Scy#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
60281348Scy#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
61281348Scy#else
62281348Scy#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
63281348Scy#endif
64281348Scy
65281348Scy#if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
66281348Scy# ifndef __gthrw_pragma
67281348Scy#  define __gthrw_pragma(pragma)
68281348Scy# endif
69281348Scy# ifdef __clang__
70281348Scy# define __gthrw2(name,name2,type) \
71281348Scy  static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
72281348Scy  __gthrw_pragma(weak type)
73281348Scy# else
74281348Scy# define __gthrw2(name,name2,type) \
75281348Scy  extern __typeof(type) name __attribute__ ((__weakref__(#name2))); \
76281348Scy  __gthrw_pragma(weak type)
77281348Scy# endif
78281348Scy# define __gthrw_(name) __gthrw_ ## name
79281348Scy#else
80281348Scy# define __gthrw2(name,name2,type)
81281348Scy# define __gthrw_(name) name
82281348Scy#endif
83281348Scy
84281348Scy/* Typically, __gthrw_foo is a weak reference to symbol foo.  */
85281348Scy#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
86281348Scy
87281348Scy/* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
88281348Scy   map a subset of the POSIX pthread API to mangled versions of their
89281348Scy   names.  */
90281348Scy#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
91281348Scy#define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
92281348Scy__gthrw3(pthread_once)
93281348Scy__gthrw3(pthread_getspecific)
94281348Scy__gthrw3(pthread_setspecific)
95281348Scy__gthrw3(pthread_create)
96281348Scy__gthrw3(pthread_cancel)
97281348Scy__gthrw3(pthread_mutex_lock)
98281348Scy__gthrw3(pthread_mutex_trylock)
99__gthrw3(pthread_mutex_unlock)
100__gthrw3(pthread_mutex_init)
101#else
102__gthrw(pthread_once)
103__gthrw(pthread_getspecific)
104__gthrw(pthread_setspecific)
105__gthrw(pthread_create)
106__gthrw(pthread_cancel)
107__gthrw(pthread_mutex_lock)
108__gthrw(pthread_mutex_trylock)
109__gthrw(pthread_mutex_unlock)
110__gthrw(pthread_mutex_init)
111#endif
112
113__gthrw(pthread_key_create)
114__gthrw(pthread_key_delete)
115__gthrw(pthread_mutexattr_init)
116__gthrw(pthread_mutexattr_settype)
117__gthrw(pthread_mutexattr_destroy)
118
119
120#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
121/* Objective-C.  */
122#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
123__gthrw3(pthread_cond_broadcast)
124__gthrw3(pthread_cond_destroy)
125__gthrw3(pthread_cond_init)
126__gthrw3(pthread_cond_signal)
127__gthrw3(pthread_cond_wait)
128__gthrw3(pthread_exit)
129__gthrw3(pthread_mutex_destroy)
130__gthrw3(pthread_self)
131#else
132__gthrw(pthread_cond_broadcast)
133__gthrw(pthread_cond_destroy)
134__gthrw(pthread_cond_init)
135__gthrw(pthread_cond_signal)
136__gthrw(pthread_cond_wait)
137__gthrw(pthread_exit)
138__gthrw(pthread_mutex_destroy)
139__gthrw(pthread_self)
140#endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
141#ifdef _POSIX_PRIORITY_SCHEDULING
142#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
143__gthrw(sched_get_priority_max)
144__gthrw(sched_get_priority_min)
145#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
146#endif /* _POSIX_PRIORITY_SCHEDULING */
147__gthrw(sched_yield)
148__gthrw(pthread_attr_destroy)
149__gthrw(pthread_attr_init)
150__gthrw(pthread_attr_setdetachstate)
151#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
152__gthrw(pthread_getschedparam)
153__gthrw(pthread_setschedparam)
154#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
155#endif /* _LIBOBJC || _LIBOBJC_WEAK */
156
157#if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
158
159static inline int
160__gthread_active_p (void)
161{
162  static void *const __gthread_active_ptr
163    = __extension__ (void *) &__gthrw_(pthread_cancel);
164  return __gthread_active_ptr != 0;
165}
166
167#else /* not __GXX_WEAK__ */
168
169static inline int
170__gthread_active_p (void)
171{
172  return 1;
173}
174
175#endif /* __GXX_WEAK__ */
176
177#ifdef _LIBOBJC
178
179/* This is the config.h file in libobjc/ */
180#include <config.h>
181
182#ifdef HAVE_SCHED_H
183# include <sched.h>
184#endif
185
186/* Key structure for maintaining thread specific storage */
187static pthread_key_t _objc_thread_storage;
188static pthread_attr_t _objc_thread_attribs;
189
190/* Thread local storage for a single thread */
191static void *thread_local_storage = NULL;
192
193/* Backend initialization functions */
194
195/* Initialize the threads subsystem.  */
196static inline int
197__gthread_objc_init_thread_system (void)
198{
199  if (__gthread_active_p ())
200    {
201      /* Initialize the thread storage key.  */
202      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
203	{
204	  /* The normal default detach state for threads is
205	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
206	   * when you think they should.  */
207	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
208	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
209					      PTHREAD_CREATE_DETACHED) == 0)
210	    return 0;
211	}
212    }
213
214  return -1;
215}
216
217/* Close the threads subsystem.  */
218static inline int
219__gthread_objc_close_thread_system (void)
220{
221  if (__gthread_active_p ()
222      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
223      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
224    return 0;
225
226  return -1;
227}
228
229/* Backend thread functions */
230
231/* Create a new thread of execution.  */
232static inline objc_thread_t
233__gthread_objc_thread_detach (void (*func)(void *), void *arg)
234{
235  objc_thread_t thread_id;
236  pthread_t new_thread_handle;
237
238  if (!__gthread_active_p ())
239    return NULL;
240
241  if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
242    thread_id = (objc_thread_t) new_thread_handle;
243  else
244    thread_id = NULL;
245
246  return thread_id;
247}
248
249/* Set the current thread's priority.  */
250static inline int
251__gthread_objc_thread_set_priority (int priority)
252{
253  if (!__gthread_active_p ())
254    return -1;
255  else
256    {
257#ifdef _POSIX_PRIORITY_SCHEDULING
258#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
259      pthread_t thread_id = __gthrw_(pthread_self) ();
260      int policy;
261      struct sched_param params;
262      int priority_min, priority_max;
263
264      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
265	{
266	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
267	    return -1;
268
269	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
270	    return -1;
271
272	  if (priority > priority_max)
273	    priority = priority_max;
274	  else if (priority < priority_min)
275	    priority = priority_min;
276	  params.sched_priority = priority;
277
278	  /*
279	   * The solaris 7 and several other man pages incorrectly state that
280	   * this should be a pointer to policy but pthread.h is universally
281	   * at odds with this.
282	   */
283	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
284	    return 0;
285	}
286#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
287#endif /* _POSIX_PRIORITY_SCHEDULING */
288      return -1;
289    }
290}
291
292/* Return the current thread's priority.  */
293static inline int
294__gthread_objc_thread_get_priority (void)
295{
296#ifdef _POSIX_PRIORITY_SCHEDULING
297#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
298  if (__gthread_active_p ())
299    {
300      int policy;
301      struct sched_param params;
302
303      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
304	return params.sched_priority;
305      else
306	return -1;
307    }
308  else
309#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
310#endif /* _POSIX_PRIORITY_SCHEDULING */
311    return OBJC_THREAD_INTERACTIVE_PRIORITY;
312}
313
314/* Yield our process time to another thread.  */
315static inline void
316__gthread_objc_thread_yield (void)
317{
318  if (__gthread_active_p ())
319    __gthrw_(sched_yield) ();
320}
321
322/* Terminate the current thread.  */
323static inline int
324__gthread_objc_thread_exit (void)
325{
326  if (__gthread_active_p ())
327    /* exit the thread */
328    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
329
330  /* Failed if we reached here */
331  return -1;
332}
333
334/* Returns an integer value which uniquely describes a thread.  */
335static inline objc_thread_t
336__gthread_objc_thread_id (void)
337{
338  if (__gthread_active_p ())
339    return (objc_thread_t) __gthrw_(pthread_self) ();
340  else
341    return (objc_thread_t) 1;
342}
343
344/* Sets the thread's local storage pointer.  */
345static inline int
346__gthread_objc_thread_set_data (void *value)
347{
348  if (__gthread_active_p ())
349    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
350  else
351    {
352      thread_local_storage = value;
353      return 0;
354    }
355}
356
357/* Returns the thread's local storage pointer.  */
358static inline void *
359__gthread_objc_thread_get_data (void)
360{
361  if (__gthread_active_p ())
362    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
363  else
364    return thread_local_storage;
365}
366
367/* Backend mutex functions */
368
369/* Allocate a mutex.  */
370static inline int
371__gthread_objc_mutex_allocate (objc_mutex_t mutex)
372{
373  if (__gthread_active_p ())
374    {
375      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
376
377      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
378	{
379	  objc_free (mutex->backend);
380	  mutex->backend = NULL;
381	  return -1;
382	}
383    }
384
385  return 0;
386}
387
388/* Deallocate a mutex.  */
389static inline int
390__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
391{
392  if (__gthread_active_p ())
393    {
394      int count;
395
396      /*
397       * Posix Threads specifically require that the thread be unlocked
398       * for __gthrw_(pthread_mutex_destroy) to work.
399       */
400
401      do
402	{
403	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
404	  if (count < 0)
405	    return -1;
406	}
407      while (count);
408
409      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
410	return -1;
411
412      objc_free (mutex->backend);
413      mutex->backend = NULL;
414    }
415  return 0;
416}
417
418/* Grab a lock on a mutex.  */
419static inline int
420__gthread_objc_mutex_lock (objc_mutex_t mutex)
421{
422  if (__gthread_active_p ()
423      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
424    {
425      return -1;
426    }
427
428  return 0;
429}
430
431/* Try to grab a lock on a mutex.  */
432static inline int
433__gthread_objc_mutex_trylock (objc_mutex_t mutex)
434{
435  if (__gthread_active_p ()
436      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
437    {
438      return -1;
439    }
440
441  return 0;
442}
443
444/* Unlock the mutex */
445static inline int
446__gthread_objc_mutex_unlock (objc_mutex_t mutex)
447{
448  if (__gthread_active_p ()
449      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
450    {
451      return -1;
452    }
453
454  return 0;
455}
456
457/* Backend condition mutex functions */
458
459/* Allocate a condition.  */
460static inline int
461__gthread_objc_condition_allocate (objc_condition_t condition)
462{
463  if (__gthread_active_p ())
464    {
465      condition->backend = objc_malloc (sizeof (pthread_cond_t));
466
467      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
468	{
469	  objc_free (condition->backend);
470	  condition->backend = NULL;
471	  return -1;
472	}
473    }
474
475  return 0;
476}
477
478/* Deallocate a condition.  */
479static inline int
480__gthread_objc_condition_deallocate (objc_condition_t condition)
481{
482  if (__gthread_active_p ())
483    {
484      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
485	return -1;
486
487      objc_free (condition->backend);
488      condition->backend = NULL;
489    }
490  return 0;
491}
492
493/* Wait on the condition */
494static inline int
495__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
496{
497  if (__gthread_active_p ())
498    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
499			      (pthread_mutex_t *) mutex->backend);
500  else
501    return 0;
502}
503
504/* Wake up all threads waiting on this condition.  */
505static inline int
506__gthread_objc_condition_broadcast (objc_condition_t condition)
507{
508  if (__gthread_active_p ())
509    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
510  else
511    return 0;
512}
513
514/* Wake up one thread waiting on this condition.  */
515static inline int
516__gthread_objc_condition_signal (objc_condition_t condition)
517{
518  if (__gthread_active_p ())
519    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
520  else
521    return 0;
522}
523
524#else /* _LIBOBJC */
525
526static inline int
527__gthread_once (__gthread_once_t *once, void (*func) (void))
528{
529  if (__gthread_active_p ())
530    return __gthrw_(pthread_once) (once, func);
531  else
532    return -1;
533}
534
535static inline int
536__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
537{
538  return __gthrw_(pthread_key_create) (key, dtor);
539}
540
541static inline int
542__gthread_key_delete (__gthread_key_t key)
543{
544  return __gthrw_(pthread_key_delete) (key);
545}
546
547static inline void *
548__gthread_getspecific (__gthread_key_t key)
549{
550  return __gthrw_(pthread_getspecific) (key);
551}
552
553static inline int
554__gthread_setspecific (__gthread_key_t key, const void *ptr)
555{
556  return __gthrw_(pthread_setspecific) (key, ptr);
557}
558
559static inline int
560__gthread_mutex_lock (__gthread_mutex_t *mutex)
561{
562  if (__gthread_active_p ())
563    return __gthrw_(pthread_mutex_lock) (mutex);
564  else
565    return 0;
566}
567
568static inline int
569__gthread_mutex_trylock (__gthread_mutex_t *mutex)
570{
571  if (__gthread_active_p ())
572    return __gthrw_(pthread_mutex_trylock) (mutex);
573  else
574    return 0;
575}
576
577static inline int
578__gthread_mutex_unlock (__gthread_mutex_t *mutex)
579{
580  if (__gthread_active_p ())
581    return __gthrw_(pthread_mutex_unlock) (mutex);
582  else
583    return 0;
584}
585
586#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
587static inline int
588__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
589{
590  if (__gthread_active_p ())
591    {
592      pthread_mutexattr_t attr;
593      int r;
594
595      r = __gthrw_(pthread_mutexattr_init) (&attr);
596      if (!r)
597	r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
598      if (!r)
599	r = __gthrw_(pthread_mutex_init) (mutex, &attr);
600      if (!r)
601	r = __gthrw_(pthread_mutexattr_destroy) (&attr);
602      return r;
603    }
604  return 0;
605}
606#endif
607
608static inline int
609__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
610{
611  return __gthread_mutex_lock (mutex);
612}
613
614static inline int
615__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
616{
617  return __gthread_mutex_trylock (mutex);
618}
619
620static inline int
621__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
622{
623  return __gthread_mutex_unlock (mutex);
624}
625
626#endif /* _LIBOBJC */
627
628#endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */
629