gthr-posix.h revision 178388
1/* Threads compatibility routines for libgcc2 and libobjc.  */
2/* Compile this one with gcc.  */
3/* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4   Free Software Foundation, Inc.
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING.  If not, write to the Free
20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2102110-1301, USA.  */
22
23/* As a special exception, if you link this library with other files,
24   some of which are compiled with GCC, to produce an executable,
25   this library does not by itself cause the resulting executable
26   to be covered by the GNU General Public License.
27   This exception does not however invalidate any other reasons why
28   the executable file might be covered by the GNU General Public License.  */
29
30#ifndef GCC_GTHR_POSIX_H
31#define GCC_GTHR_POSIX_H
32
33/* POSIX threads specific definitions.
34   Easy, since the interface is just one-to-one mapping.  */
35
36#define __GTHREADS 1
37
38/* Some implementations of <pthread.h> require this to be defined.  */
39#if !defined(_REENTRANT) && defined(__osf__)
40#define _REENTRANT 1
41#endif
42
43#include <pthread.h>
44#include <unistd.h>
45
46typedef pthread_key_t __gthread_key_t;
47typedef pthread_once_t __gthread_once_t;
48typedef pthread_mutex_t __gthread_mutex_t;
49typedef pthread_mutex_t __gthread_recursive_mutex_t;
50
51#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
52#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
53#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
54#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
55#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
56#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
57#else
58#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
59#endif
60
61#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
62# ifndef __gthrw_pragma
63#  define __gthrw_pragma(pragma)
64# endif
65# define __gthrw2(name,name2,type) \
66  static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
67  __gthrw_pragma(weak type)
68# define __gthrw_(name) __gthrw_ ## name
69#else
70# define __gthrw2(name,name2,type)
71# define __gthrw_(name) name
72#endif
73
74/* Typically, __gthrw_foo is a weak reference to symbol foo.  */
75#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
76
77/* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
78   map a subset of the POSIX pthread API to mangled versions of their
79   names.  */
80#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
81#define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
82__gthrw3(pthread_once)
83__gthrw3(pthread_getspecific)
84__gthrw3(pthread_setspecific)
85__gthrw3(pthread_create)
86__gthrw3(pthread_cancel)
87__gthrw3(pthread_mutex_lock)
88__gthrw3(pthread_mutex_trylock)
89__gthrw3(pthread_mutex_unlock)
90__gthrw3(pthread_mutex_init)
91#else
92__gthrw(pthread_once)
93__gthrw(pthread_getspecific)
94__gthrw(pthread_setspecific)
95__gthrw(pthread_create)
96__gthrw(pthread_cancel)
97__gthrw(pthread_mutex_lock)
98__gthrw(pthread_mutex_trylock)
99__gthrw(pthread_mutex_unlock)
100__gthrw(pthread_mutex_init)
101#endif
102
103__gthrw(pthread_key_create)
104__gthrw(pthread_key_delete)
105__gthrw(pthread_mutexattr_init)
106__gthrw(pthread_mutexattr_settype)
107__gthrw(pthread_mutexattr_destroy)
108
109
110#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
111/* Objective-C.  */
112#if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
113__gthrw3(pthread_cond_broadcast)
114__gthrw3(pthread_cond_destroy)
115__gthrw3(pthread_cond_init)
116__gthrw3(pthread_cond_signal)
117__gthrw3(pthread_cond_wait)
118__gthrw3(pthread_exit)
119__gthrw3(pthread_mutex_destroy)
120__gthrw3(pthread_self)
121#else
122__gthrw(pthread_cond_broadcast)
123__gthrw(pthread_cond_destroy)
124__gthrw(pthread_cond_init)
125__gthrw(pthread_cond_signal)
126__gthrw(pthread_cond_wait)
127__gthrw(pthread_exit)
128__gthrw(pthread_mutex_destroy)
129__gthrw(pthread_self)
130#endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
131#ifdef _POSIX_PRIORITY_SCHEDULING
132#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
133__gthrw(sched_get_priority_max)
134__gthrw(sched_get_priority_min)
135#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
136#endif /* _POSIX_PRIORITY_SCHEDULING */
137__gthrw(sched_yield)
138__gthrw(pthread_attr_destroy)
139__gthrw(pthread_attr_init)
140__gthrw(pthread_attr_setdetachstate)
141#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
142__gthrw(pthread_getschedparam)
143__gthrw(pthread_setschedparam)
144#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
145#endif /* _LIBOBJC || _LIBOBJC_WEAK */
146
147#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
148
149/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
150   -pthreads is not specified.  The functions are dummies and most return an
151   error value.  However pthread_once returns 0 without invoking the routine
152   it is passed so we cannot pretend that the interface is active if -pthreads
153   is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
154   we need to play the usual game with weak symbols.  On Solaris 10 and up, a
155   working interface is always exposed.  On FreeBSD 6 and later, libc also
156   exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
157   to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
158   which means the alternate __gthread_active_p below cannot be used there.  */
159
160#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
161
162static volatile int __gthread_active = -1;
163
164static void
165__gthread_trigger (void)
166{
167  __gthread_active = 1;
168}
169
170static inline int
171__gthread_active_p (void)
172{
173  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
174  static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
175
176  /* Avoid reading __gthread_active twice on the main code path.  */
177  int __gthread_active_latest_value = __gthread_active;
178
179  /* This test is not protected to avoid taking a lock on the main code
180     path so every update of __gthread_active in a threaded program must
181     be atomic with regard to the result of the test.  */
182  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
183    {
184      if (__gthrw_(pthread_once))
185	{
186	  /* If this really is a threaded program, then we must ensure that
187	     __gthread_active has been set to 1 before exiting this block.  */
188	  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
189	  __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
190	  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
191	}
192
193      /* Make sure we'll never enter this block again.  */
194      if (__gthread_active < 0)
195	__gthread_active = 0;
196
197      __gthread_active_latest_value = __gthread_active;
198    }
199
200  return __gthread_active_latest_value != 0;
201}
202
203#else /* neither FreeBSD nor Solaris */
204
205static inline int
206__gthread_active_p (void)
207{
208  static void *const __gthread_active_ptr
209    = __extension__ (void *) &__gthrw_(pthread_cancel);
210  return __gthread_active_ptr != 0;
211}
212
213#endif /* FreeBSD or Solaris */
214
215#else /* not SUPPORTS_WEAK */
216
217static inline int
218__gthread_active_p (void)
219{
220  return 1;
221}
222
223#endif /* SUPPORTS_WEAK */
224
225#ifdef _LIBOBJC
226
227/* This is the config.h file in libobjc/ */
228#include <config.h>
229
230#ifdef HAVE_SCHED_H
231# include <sched.h>
232#endif
233
234/* Key structure for maintaining thread specific storage */
235static pthread_key_t _objc_thread_storage;
236static pthread_attr_t _objc_thread_attribs;
237
238/* Thread local storage for a single thread */
239static void *thread_local_storage = NULL;
240
241/* Backend initialization functions */
242
243/* Initialize the threads subsystem.  */
244static inline int
245__gthread_objc_init_thread_system (void)
246{
247  if (__gthread_active_p ())
248    {
249      /* Initialize the thread storage key.  */
250      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
251	{
252	  /* The normal default detach state for threads is
253	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
254	   * when you think they should.  */
255	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
256	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
257					      PTHREAD_CREATE_DETACHED) == 0)
258	    return 0;
259	}
260    }
261
262  return -1;
263}
264
265/* Close the threads subsystem.  */
266static inline int
267__gthread_objc_close_thread_system (void)
268{
269  if (__gthread_active_p ()
270      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
271      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
272    return 0;
273
274  return -1;
275}
276
277/* Backend thread functions */
278
279/* Create a new thread of execution.  */
280static inline objc_thread_t
281__gthread_objc_thread_detach (void (*func)(void *), void *arg)
282{
283  objc_thread_t thread_id;
284  pthread_t new_thread_handle;
285
286  if (!__gthread_active_p ())
287    return NULL;
288
289  if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
290    thread_id = (objc_thread_t) new_thread_handle;
291  else
292    thread_id = NULL;
293
294  return thread_id;
295}
296
297/* Set the current thread's priority.  */
298static inline int
299__gthread_objc_thread_set_priority (int priority)
300{
301  if (!__gthread_active_p ())
302    return -1;
303  else
304    {
305#ifdef _POSIX_PRIORITY_SCHEDULING
306#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
307      pthread_t thread_id = __gthrw_(pthread_self) ();
308      int policy;
309      struct sched_param params;
310      int priority_min, priority_max;
311
312      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
313	{
314	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
315	    return -1;
316
317	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
318	    return -1;
319
320	  if (priority > priority_max)
321	    priority = priority_max;
322	  else if (priority < priority_min)
323	    priority = priority_min;
324	  params.sched_priority = priority;
325
326	  /*
327	   * The solaris 7 and several other man pages incorrectly state that
328	   * this should be a pointer to policy but pthread.h is universally
329	   * at odds with this.
330	   */
331	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
332	    return 0;
333	}
334#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
335#endif /* _POSIX_PRIORITY_SCHEDULING */
336      return -1;
337    }
338}
339
340/* Return the current thread's priority.  */
341static inline int
342__gthread_objc_thread_get_priority (void)
343{
344#ifdef _POSIX_PRIORITY_SCHEDULING
345#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
346  if (__gthread_active_p ())
347    {
348      int policy;
349      struct sched_param params;
350
351      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
352	return params.sched_priority;
353      else
354	return -1;
355    }
356  else
357#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
358#endif /* _POSIX_PRIORITY_SCHEDULING */
359    return OBJC_THREAD_INTERACTIVE_PRIORITY;
360}
361
362/* Yield our process time to another thread.  */
363static inline void
364__gthread_objc_thread_yield (void)
365{
366  if (__gthread_active_p ())
367    __gthrw_(sched_yield) ();
368}
369
370/* Terminate the current thread.  */
371static inline int
372__gthread_objc_thread_exit (void)
373{
374  if (__gthread_active_p ())
375    /* exit the thread */
376    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
377
378  /* Failed if we reached here */
379  return -1;
380}
381
382/* Returns an integer value which uniquely describes a thread.  */
383static inline objc_thread_t
384__gthread_objc_thread_id (void)
385{
386  if (__gthread_active_p ())
387    return (objc_thread_t) __gthrw_(pthread_self) ();
388  else
389    return (objc_thread_t) 1;
390}
391
392/* Sets the thread's local storage pointer.  */
393static inline int
394__gthread_objc_thread_set_data (void *value)
395{
396  if (__gthread_active_p ())
397    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
398  else
399    {
400      thread_local_storage = value;
401      return 0;
402    }
403}
404
405/* Returns the thread's local storage pointer.  */
406static inline void *
407__gthread_objc_thread_get_data (void)
408{
409  if (__gthread_active_p ())
410    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
411  else
412    return thread_local_storage;
413}
414
415/* Backend mutex functions */
416
417/* Allocate a mutex.  */
418static inline int
419__gthread_objc_mutex_allocate (objc_mutex_t mutex)
420{
421  if (__gthread_active_p ())
422    {
423      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
424
425      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
426	{
427	  objc_free (mutex->backend);
428	  mutex->backend = NULL;
429	  return -1;
430	}
431    }
432
433  return 0;
434}
435
436/* Deallocate a mutex.  */
437static inline int
438__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
439{
440  if (__gthread_active_p ())
441    {
442      int count;
443
444      /*
445       * Posix Threads specifically require that the thread be unlocked
446       * for __gthrw_(pthread_mutex_destroy) to work.
447       */
448
449      do
450	{
451	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
452	  if (count < 0)
453	    return -1;
454	}
455      while (count);
456
457      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
458	return -1;
459
460      objc_free (mutex->backend);
461      mutex->backend = NULL;
462    }
463  return 0;
464}
465
466/* Grab a lock on a mutex.  */
467static inline int
468__gthread_objc_mutex_lock (objc_mutex_t mutex)
469{
470  if (__gthread_active_p ()
471      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
472    {
473      return -1;
474    }
475
476  return 0;
477}
478
479/* Try to grab a lock on a mutex.  */
480static inline int
481__gthread_objc_mutex_trylock (objc_mutex_t mutex)
482{
483  if (__gthread_active_p ()
484      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
485    {
486      return -1;
487    }
488
489  return 0;
490}
491
492/* Unlock the mutex */
493static inline int
494__gthread_objc_mutex_unlock (objc_mutex_t mutex)
495{
496  if (__gthread_active_p ()
497      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
498    {
499      return -1;
500    }
501
502  return 0;
503}
504
505/* Backend condition mutex functions */
506
507/* Allocate a condition.  */
508static inline int
509__gthread_objc_condition_allocate (objc_condition_t condition)
510{
511  if (__gthread_active_p ())
512    {
513      condition->backend = objc_malloc (sizeof (pthread_cond_t));
514
515      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
516	{
517	  objc_free (condition->backend);
518	  condition->backend = NULL;
519	  return -1;
520	}
521    }
522
523  return 0;
524}
525
526/* Deallocate a condition.  */
527static inline int
528__gthread_objc_condition_deallocate (objc_condition_t condition)
529{
530  if (__gthread_active_p ())
531    {
532      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
533	return -1;
534
535      objc_free (condition->backend);
536      condition->backend = NULL;
537    }
538  return 0;
539}
540
541/* Wait on the condition */
542static inline int
543__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
544{
545  if (__gthread_active_p ())
546    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
547			      (pthread_mutex_t *) mutex->backend);
548  else
549    return 0;
550}
551
552/* Wake up all threads waiting on this condition.  */
553static inline int
554__gthread_objc_condition_broadcast (objc_condition_t condition)
555{
556  if (__gthread_active_p ())
557    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
558  else
559    return 0;
560}
561
562/* Wake up one thread waiting on this condition.  */
563static inline int
564__gthread_objc_condition_signal (objc_condition_t condition)
565{
566  if (__gthread_active_p ())
567    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
568  else
569    return 0;
570}
571
572#else /* _LIBOBJC */
573
574static inline int
575__gthread_once (__gthread_once_t *once, void (*func) (void))
576{
577  if (__gthread_active_p ())
578    return __gthrw_(pthread_once) (once, func);
579  else
580    return -1;
581}
582
583static inline int
584__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
585{
586  return __gthrw_(pthread_key_create) (key, dtor);
587}
588
589static inline int
590__gthread_key_delete (__gthread_key_t key)
591{
592  return __gthrw_(pthread_key_delete) (key);
593}
594
595static inline void *
596__gthread_getspecific (__gthread_key_t key)
597{
598  return __gthrw_(pthread_getspecific) (key);
599}
600
601static inline int
602__gthread_setspecific (__gthread_key_t key, const void *ptr)
603{
604  return __gthrw_(pthread_setspecific) (key, ptr);
605}
606
607static inline int
608__gthread_mutex_lock (__gthread_mutex_t *mutex)
609{
610  if (__gthread_active_p ())
611    return __gthrw_(pthread_mutex_lock) (mutex);
612  else
613    return 0;
614}
615
616static inline int
617__gthread_mutex_trylock (__gthread_mutex_t *mutex)
618{
619  if (__gthread_active_p ())
620    return __gthrw_(pthread_mutex_trylock) (mutex);
621  else
622    return 0;
623}
624
625static inline int
626__gthread_mutex_unlock (__gthread_mutex_t *mutex)
627{
628  if (__gthread_active_p ())
629    return __gthrw_(pthread_mutex_unlock) (mutex);
630  else
631    return 0;
632}
633
634#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
635static inline int
636__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
637{
638  if (__gthread_active_p ())
639    {
640      pthread_mutexattr_t attr;
641      int r;
642
643      r = __gthrw_(pthread_mutexattr_init) (&attr);
644      if (!r)
645	r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
646      if (!r)
647	r = __gthrw_(pthread_mutex_init) (mutex, &attr);
648      if (!r)
649	r = __gthrw_(pthread_mutexattr_destroy) (&attr);
650      return r;
651    }
652  return 0;
653}
654#endif
655
656static inline int
657__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
658{
659  return __gthread_mutex_lock (mutex);
660}
661
662static inline int
663__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
664{
665  return __gthread_mutex_trylock (mutex);
666}
667
668static inline int
669__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
670{
671  return __gthread_mutex_unlock (mutex);
672}
673
674#endif /* _LIBOBJC */
675
676#endif /* ! GCC_GTHR_POSIX_H */
677