1/* Threads compatibility routines for libgcc2 and libobjc.  */
2/* Compile this one with gcc.  */
3/* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011
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 3, 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
18Under Section 7 of GPL version 3, you are granted additional
19permissions described in the GCC Runtime Library Exception, version
203.1, as published by the Free Software Foundation.
21
22You should have received a copy of the GNU General Public License and
23a copy of the GCC Runtime Library Exception along with this program;
24see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25<http://www.gnu.org/licenses/>.  */
26
27#ifndef GCC_GTHR_POSIX_H
28#define GCC_GTHR_POSIX_H
29
30/* POSIX threads specific definitions.
31   Easy, since the interface is just one-to-one mapping.  */
32
33#define __GTHREADS 1
34
35/* Some implementations of <pthread.h> require this to be defined.  */
36#ifndef _REENTRANT
37#define _REENTRANT 1
38#endif
39
40#include <pthread.h>
41#include <unistd.h>
42
43typedef pthread_key_t __gthread_key_t;
44typedef pthread_once_t __gthread_once_t;
45typedef pthread_mutex_t __gthread_mutex_t;
46typedef pthread_cond_t __gthread_cond_t;
47
48/* POSIX like conditional variables are supported.  Please look at comments
49   in gthr.h for details. */
50#define __GTHREAD_HAS_COND	1
51
52typedef struct {
53  long depth;
54  pthread_t owner;
55  pthread_mutex_t actual;
56} __gthread_recursive_mutex_t;
57
58#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
59#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
60#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
61#define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
62
63#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
64# define __gthrw(name) \
65  static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
66# define __gthrw_(name) __gthrw_ ## name
67#else
68# define __gthrw(name)
69# define __gthrw_(name) name
70#endif
71
72__gthrw(pthread_once)
73__gthrw(pthread_key_create)
74__gthrw(pthread_key_delete)
75__gthrw(pthread_getspecific)
76__gthrw(pthread_setspecific)
77__gthrw(pthread_create)
78__gthrw(pthread_cancel)
79__gthrw(pthread_self)
80
81__gthrw(pthread_mutex_init)
82__gthrw(pthread_mutex_destroy)
83__gthrw(pthread_mutex_lock)
84__gthrw(pthread_mutex_trylock)
85__gthrw(pthread_mutex_unlock)
86__gthrw(pthread_mutexattr_init)
87__gthrw(pthread_mutexattr_destroy)
88
89__gthrw(pthread_cond_broadcast)
90__gthrw(pthread_cond_wait)
91
92#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
93/* Objective-C.  */
94__gthrw(pthread_cond_destroy)
95__gthrw(pthread_cond_init)
96__gthrw(pthread_cond_signal)
97__gthrw(pthread_exit)
98#ifdef _POSIX_PRIORITY_SCHEDULING
99#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
100__gthrw(sched_get_priority_max)
101__gthrw(sched_get_priority_min)
102#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
103#endif /* _POSIX_PRIORITY_SCHEDULING */
104__gthrw(sched_yield)
105__gthrw(pthread_attr_destroy)
106__gthrw(pthread_attr_init)
107__gthrw(pthread_attr_setdetachstate)
108#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
109__gthrw(pthread_getschedparam)
110__gthrw(pthread_setschedparam)
111#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
112#endif /* _LIBOBJC || _LIBOBJC_WEAK */
113
114#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
115
116/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
117   -pthreads is not specified.  The functions are dummies and most return an
118   error value.  However pthread_once returns 0 without invoking the routine
119   it is passed so we cannot pretend that the interface is active if -pthreads
120   is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
121   we need to play the usual game with weak symbols.  On Solaris 10 and up, a
122   working interface is always exposed.  On FreeBSD 6 and later, libc also
123   exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
124   to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
125   which means the alternate __gthread_active_p below cannot be used there.  */
126
127#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
128
129static volatile int __gthread_active = -1;
130
131static void
132__gthread_trigger (void)
133{
134  __gthread_active = 1;
135}
136
137static inline int
138__gthread_active_p (void)
139{
140  static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
141  static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
142
143  /* Avoid reading __gthread_active twice on the main code path.  */
144  int __gthread_active_latest_value = __gthread_active;
145
146  /* This test is not protected to avoid taking a lock on the main code
147     path so every update of __gthread_active in a threaded program must
148     be atomic with regard to the result of the test.  */
149  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
150    {
151      if (__gthrw_(pthread_once))
152	{
153	  /* If this really is a threaded program, then we must ensure that
154	     __gthread_active has been set to 1 before exiting this block.  */
155	  __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
156	  __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
157	  __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
158	}
159
160      /* Make sure we'll never enter this block again.  */
161      if (__gthread_active < 0)
162	__gthread_active = 0;
163
164      __gthread_active_latest_value = __gthread_active;
165    }
166
167  return __gthread_active_latest_value != 0;
168}
169
170#else /* neither FreeBSD nor Solaris */
171
172static inline int
173__gthread_active_p (void)
174{
175  static void *const __gthread_active_ptr
176    = __extension__ (void *) &__gthrw_(pthread_cancel);
177  return __gthread_active_ptr != 0;
178}
179
180#endif /* FreeBSD or Solaris */
181
182#else /* not SUPPORTS_WEAK */
183
184/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
185   calls in shared flavors of the HP-UX C library.  Most of the stubs
186   have no functionality.  The details are described in the "libc cumulative
187   patch" for each subversion of HP-UX 11.  There are two special interfaces
188   provided for checking whether an application is linked to a shared pthread
189   library or not.  However, these interfaces aren't available in early
190   pthread libraries.  We also need a test that works for archive
191   libraries.  We can't use pthread_once as some libc versions call the
192   init function.  We also can't use pthread_create or pthread_attr_init
193   as these create a thread and thereby prevent changing the default stack
194   size.  The function pthread_default_stacksize_np is available in both
195   the archive and shared versions of libpthread.   It can be used to
196   determine the default pthread stack size.  There is a stub in some
197   shared libc versions which returns a zero size if pthreads are not
198   active.  We provide an equivalent stub to handle cases where libc
199   doesn't provide one.  */
200
201#if defined(__hppa__) && defined(__hpux__)
202
203static volatile int __gthread_active = -1;
204
205static inline int
206__gthread_active_p (void)
207{
208  /* Avoid reading __gthread_active twice on the main code path.  */
209  int __gthread_active_latest_value = __gthread_active;
210  size_t __s;
211
212  if (__builtin_expect (__gthread_active_latest_value < 0, 0))
213    {
214      pthread_default_stacksize_np (0, &__s);
215      __gthread_active = __s ? 1 : 0;
216      __gthread_active_latest_value = __gthread_active;
217    }
218
219  return __gthread_active_latest_value != 0;
220}
221
222#else /* not hppa-hpux */
223
224static inline int
225__gthread_active_p (void)
226{
227  return 1;
228}
229
230#endif /* hppa-hpux */
231
232#endif /* SUPPORTS_WEAK */
233
234#ifdef _LIBOBJC
235
236/* This is the config.h file in libobjc/ */
237#include <config.h>
238
239#ifdef HAVE_SCHED_H
240# include <sched.h>
241#endif
242
243/* Key structure for maintaining thread specific storage */
244static pthread_key_t _objc_thread_storage;
245static pthread_attr_t _objc_thread_attribs;
246
247/* Thread local storage for a single thread */
248static void *thread_local_storage = NULL;
249
250/* Backend initialization functions */
251
252/* Initialize the threads subsystem.  */
253static inline int
254__gthread_objc_init_thread_system (void)
255{
256  if (__gthread_active_p ())
257    {
258      /* Initialize the thread storage key.  */
259      if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
260	{
261	  /* The normal default detach state for threads is
262	   * PTHREAD_CREATE_JOINABLE which causes threads to not die
263	   * when you think they should.  */
264	  if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
265	      && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
266					      PTHREAD_CREATE_DETACHED) == 0)
267	    return 0;
268	}
269    }
270
271  return -1;
272}
273
274/* Close the threads subsystem.  */
275static inline int
276__gthread_objc_close_thread_system (void)
277{
278  if (__gthread_active_p ()
279      && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
280      && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
281    return 0;
282
283  return -1;
284}
285
286/* Backend thread functions */
287
288/* Create a new thread of execution.  */
289static inline objc_thread_t
290__gthread_objc_thread_detach (void (*func)(void *), void *arg)
291{
292  objc_thread_t thread_id;
293  pthread_t new_thread_handle;
294
295  if (!__gthread_active_p ())
296    return NULL;
297
298  if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
299    thread_id = (objc_thread_t) new_thread_handle;
300  else
301    thread_id = NULL;
302
303  return thread_id;
304}
305
306/* Set the current thread's priority.  */
307static inline int
308__gthread_objc_thread_set_priority (int priority)
309{
310  if (!__gthread_active_p ())
311    return -1;
312  else
313    {
314#ifdef _POSIX_PRIORITY_SCHEDULING
315#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
316      pthread_t thread_id = __gthrw_(pthread_self) ();
317      int policy;
318      struct sched_param params;
319      int priority_min, priority_max;
320
321      if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
322	{
323	  if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
324	    return -1;
325
326	  if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
327	    return -1;
328
329	  if (priority > priority_max)
330	    priority = priority_max;
331	  else if (priority < priority_min)
332	    priority = priority_min;
333	  params.sched_priority = priority;
334
335	  /*
336	   * The solaris 7 and several other man pages incorrectly state that
337	   * this should be a pointer to policy but pthread.h is universally
338	   * at odds with this.
339	   */
340	  if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
341	    return 0;
342	}
343#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
344#endif /* _POSIX_PRIORITY_SCHEDULING */
345      return -1;
346    }
347}
348
349/* Return the current thread's priority.  */
350static inline int
351__gthread_objc_thread_get_priority (void)
352{
353#ifdef _POSIX_PRIORITY_SCHEDULING
354#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
355  if (__gthread_active_p ())
356    {
357      int policy;
358      struct sched_param params;
359
360      if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
361	return params.sched_priority;
362      else
363	return -1;
364    }
365  else
366#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
367#endif /* _POSIX_PRIORITY_SCHEDULING */
368    return OBJC_THREAD_INTERACTIVE_PRIORITY;
369}
370
371/* Yield our process time to another thread.  */
372static inline void
373__gthread_objc_thread_yield (void)
374{
375  if (__gthread_active_p ())
376    __gthrw_(sched_yield) ();
377}
378
379/* Terminate the current thread.  */
380static inline int
381__gthread_objc_thread_exit (void)
382{
383  if (__gthread_active_p ())
384    /* exit the thread */
385    __gthrw_(pthread_exit) (&__objc_thread_exit_status);
386
387  /* Failed if we reached here */
388  return -1;
389}
390
391/* Returns an integer value which uniquely describes a thread.  */
392static inline objc_thread_t
393__gthread_objc_thread_id (void)
394{
395  if (__gthread_active_p ())
396    return (objc_thread_t) __gthrw_(pthread_self) ();
397  else
398    return (objc_thread_t) 1;
399}
400
401/* Sets the thread's local storage pointer.  */
402static inline int
403__gthread_objc_thread_set_data (void *value)
404{
405  if (__gthread_active_p ())
406    return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
407  else
408    {
409      thread_local_storage = value;
410      return 0;
411    }
412}
413
414/* Returns the thread's local storage pointer.  */
415static inline void *
416__gthread_objc_thread_get_data (void)
417{
418  if (__gthread_active_p ())
419    return __gthrw_(pthread_getspecific) (_objc_thread_storage);
420  else
421    return thread_local_storage;
422}
423
424/* Backend mutex functions */
425
426/* Allocate a mutex.  */
427static inline int
428__gthread_objc_mutex_allocate (objc_mutex_t mutex)
429{
430  if (__gthread_active_p ())
431    {
432      mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
433
434      if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
435	{
436	  objc_free (mutex->backend);
437	  mutex->backend = NULL;
438	  return -1;
439	}
440    }
441
442  return 0;
443}
444
445/* Deallocate a mutex.  */
446static inline int
447__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
448{
449  if (__gthread_active_p ())
450    {
451      int count;
452
453      /*
454       * Posix Threads specifically require that the thread be unlocked
455       * for __gthrw_(pthread_mutex_destroy) to work.
456       */
457
458      do
459	{
460	  count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
461	  if (count < 0)
462	    return -1;
463	}
464      while (count);
465
466      if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
467	return -1;
468
469      objc_free (mutex->backend);
470      mutex->backend = NULL;
471    }
472  return 0;
473}
474
475/* Grab a lock on a mutex.  */
476static inline int
477__gthread_objc_mutex_lock (objc_mutex_t mutex)
478{
479  if (__gthread_active_p ()
480      && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
481    {
482      return -1;
483    }
484
485  return 0;
486}
487
488/* Try to grab a lock on a mutex.  */
489static inline int
490__gthread_objc_mutex_trylock (objc_mutex_t mutex)
491{
492  if (__gthread_active_p ()
493      && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
494    {
495      return -1;
496    }
497
498  return 0;
499}
500
501/* Unlock the mutex */
502static inline int
503__gthread_objc_mutex_unlock (objc_mutex_t mutex)
504{
505  if (__gthread_active_p ()
506      && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
507    {
508      return -1;
509    }
510
511  return 0;
512}
513
514/* Backend condition mutex functions */
515
516/* Allocate a condition.  */
517static inline int
518__gthread_objc_condition_allocate (objc_condition_t condition)
519{
520  if (__gthread_active_p ())
521    {
522      condition->backend = objc_malloc (sizeof (pthread_cond_t));
523
524      if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
525	{
526	  objc_free (condition->backend);
527	  condition->backend = NULL;
528	  return -1;
529	}
530    }
531
532  return 0;
533}
534
535/* Deallocate a condition.  */
536static inline int
537__gthread_objc_condition_deallocate (objc_condition_t condition)
538{
539  if (__gthread_active_p ())
540    {
541      if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
542	return -1;
543
544      objc_free (condition->backend);
545      condition->backend = NULL;
546    }
547  return 0;
548}
549
550/* Wait on the condition */
551static inline int
552__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
553{
554  if (__gthread_active_p ())
555    return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
556			      (pthread_mutex_t *) mutex->backend);
557  else
558    return 0;
559}
560
561/* Wake up all threads waiting on this condition.  */
562static inline int
563__gthread_objc_condition_broadcast (objc_condition_t condition)
564{
565  if (__gthread_active_p ())
566    return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
567  else
568    return 0;
569}
570
571/* Wake up one thread waiting on this condition.  */
572static inline int
573__gthread_objc_condition_signal (objc_condition_t condition)
574{
575  if (__gthread_active_p ())
576    return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
577  else
578    return 0;
579}
580
581#else /* _LIBOBJC */
582
583static inline int
584__gthread_once (__gthread_once_t *__once, void (*__func) (void))
585{
586  if (__gthread_active_p ())
587    return __gthrw_(pthread_once) (__once, __func);
588  else
589    return -1;
590}
591
592static inline int
593__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
594{
595  return __gthrw_(pthread_key_create) (__key, __dtor);
596}
597
598static inline int
599__gthread_key_delete (__gthread_key_t __key)
600{
601  return __gthrw_(pthread_key_delete) (__key);
602}
603
604static inline void *
605__gthread_getspecific (__gthread_key_t __key)
606{
607  return __gthrw_(pthread_getspecific) (__key);
608}
609
610static inline int
611__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
612{
613  return __gthrw_(pthread_setspecific) (__key, __ptr);
614}
615
616static inline int
617__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
618{
619  if (__gthread_active_p ())
620    return __gthrw_(pthread_mutex_destroy) (__mutex);
621  else
622    return 0;
623}
624
625static inline int
626__gthread_mutex_lock (__gthread_mutex_t *__mutex)
627{
628  if (__gthread_active_p ())
629    return __gthrw_(pthread_mutex_lock) (__mutex);
630  else
631    return 0;
632}
633
634static inline int
635__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
636{
637  if (__gthread_active_p ())
638    return __gthrw_(pthread_mutex_trylock) (__mutex);
639  else
640    return 0;
641}
642
643static inline int
644__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
645{
646  if (__gthread_active_p ())
647    return __gthrw_(pthread_mutex_unlock) (__mutex);
648  else
649    return 0;
650}
651
652static inline int
653__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
654{
655  __mutex->depth = 0;
656  __mutex->owner = (pthread_t) 0;
657  return __gthrw_(pthread_mutex_init) (&__mutex->actual, NULL);
658}
659
660static inline int
661__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
662{
663  if (__gthread_active_p ())
664    {
665      pthread_t __me = __gthrw_(pthread_self) ();
666
667      if (__mutex->owner != __me)
668	{
669	  __gthrw_(pthread_mutex_lock) (&__mutex->actual);
670	  __mutex->owner = __me;
671	}
672
673      __mutex->depth++;
674    }
675  return 0;
676}
677
678static inline int
679__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
680{
681  if (__gthread_active_p ())
682    {
683      pthread_t __me = __gthrw_(pthread_self) ();
684
685      if (__mutex->owner != __me)
686	{
687	  if (__gthrw_(pthread_mutex_trylock) (&__mutex->actual))
688	    return 1;
689	  __mutex->owner = __me;
690	}
691
692      __mutex->depth++;
693    }
694  return 0;
695}
696
697static inline int
698__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
699{
700  if (__gthread_active_p ())
701    {
702      if (--__mutex->depth == 0)
703	{
704	   __mutex->owner = (pthread_t) 0;
705	   __gthrw_(pthread_mutex_unlock) (&__mutex->actual);
706	}
707    }
708  return 0;
709}
710
711static inline int
712__gthread_cond_broadcast (__gthread_cond_t *__cond)
713{
714  return __gthrw_(pthread_cond_broadcast) (__cond);
715}
716
717static inline int
718__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
719{
720  return __gthrw_(pthread_cond_wait) (__cond, __mutex);
721}
722
723static inline int
724__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
725			       __gthread_recursive_mutex_t *__mutex)
726{
727  return __gthrw_(pthread_cond_wait) (__cond, &__mutex->actual);
728}
729
730#endif /* _LIBOBJC */
731
732#endif /* ! GCC_GTHR_POSIX_H */
733