re PR middle-end/33617 (ICE for nonconstant callee-copied constructor arguments)
[official-gcc.git] / gcc / gthr-posix95.h
blobf0d1553193e8f4f5aed6adcde975c0307af4b43f
1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA. */
22 /* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License. */
29 #ifndef GCC_GTHR_POSIX_H
30 #define GCC_GTHR_POSIX_H
32 /* POSIX threads specific definitions.
33 Easy, since the interface is just one-to-one mapping. */
35 #define __GTHREADS 1
37 /* Some implementations of <pthread.h> require this to be defined. */
38 #ifndef _REENTRANT
39 #define _REENTRANT 1
40 #endif
42 #include <pthread.h>
43 #include <unistd.h>
45 typedef pthread_key_t __gthread_key_t;
46 typedef pthread_once_t __gthread_once_t;
47 typedef pthread_mutex_t __gthread_mutex_t;
49 typedef struct {
50 long depth;
51 pthread_t owner;
52 pthread_mutex_t actual;
53 } __gthread_recursive_mutex_t;
55 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
56 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
57 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
59 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
60 # define __gthrw(name) \
61 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
62 # define __gthrw_(name) __gthrw_ ## name
63 #else
64 # define __gthrw(name)
65 # define __gthrw_(name) name
66 #endif
68 __gthrw(pthread_once)
69 __gthrw(pthread_key_create)
70 __gthrw(pthread_key_delete)
71 __gthrw(pthread_getspecific)
72 __gthrw(pthread_setspecific)
73 __gthrw(pthread_create)
74 __gthrw(pthread_cancel)
75 __gthrw(pthread_self)
77 __gthrw(pthread_mutex_lock)
78 __gthrw(pthread_mutex_trylock)
79 __gthrw(pthread_mutex_unlock)
80 __gthrw(pthread_mutexattr_init)
81 __gthrw(pthread_mutexattr_destroy)
83 __gthrw(pthread_mutex_init)
85 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
86 /* Objective-C. */
87 __gthrw(pthread_cond_broadcast)
88 __gthrw(pthread_cond_destroy)
89 __gthrw(pthread_cond_init)
90 __gthrw(pthread_cond_signal)
91 __gthrw(pthread_cond_wait)
92 __gthrw(pthread_exit)
93 __gthrw(pthread_mutex_destroy)
94 #ifdef _POSIX_PRIORITY_SCHEDULING
95 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
96 __gthrw(sched_get_priority_max)
97 __gthrw(sched_get_priority_min)
98 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
99 #endif /* _POSIX_PRIORITY_SCHEDULING */
100 __gthrw(sched_yield)
101 __gthrw(pthread_attr_destroy)
102 __gthrw(pthread_attr_init)
103 __gthrw(pthread_attr_setdetachstate)
104 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
105 __gthrw(pthread_getschedparam)
106 __gthrw(pthread_setschedparam)
107 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
108 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
110 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
112 /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
113 -pthreads is not specified. The functions are dummies and most return an
114 error value. However pthread_once returns 0 without invoking the routine
115 it is passed so we cannot pretend that the interface is active if -pthreads
116 is not specified. On Solaris 2.5.1, the interface is not exposed at all so
117 we need to play the usual game with weak symbols. On Solaris 10 and up, a
118 working interface is always exposed. */
120 #if defined(__sun) && defined(__svr4__)
122 static volatile int __gthread_active = -1;
124 static void
125 __gthread_trigger (void)
127 __gthread_active = 1;
130 static inline int
131 __gthread_active_p (void)
133 static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
134 static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
136 /* Avoid reading __gthread_active twice on the main code path. */
137 int __gthread_active_latest_value = __gthread_active;
139 /* This test is not protected to avoid taking a lock on the main code
140 path so every update of __gthread_active in a threaded program must
141 be atomic with regard to the result of the test. */
142 if (__builtin_expect (__gthread_active_latest_value < 0, 0))
144 if (__gthrw_(pthread_once))
146 /* If this really is a threaded program, then we must ensure that
147 __gthread_active has been set to 1 before exiting this block. */
148 __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
149 __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
150 __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
153 /* Make sure we'll never enter this block again. */
154 if (__gthread_active < 0)
155 __gthread_active = 0;
157 __gthread_active_latest_value = __gthread_active;
160 return __gthread_active_latest_value != 0;
163 #else /* not Solaris */
165 static inline int
166 __gthread_active_p (void)
168 static void *const __gthread_active_ptr
169 = __extension__ (void *) &__gthrw_(pthread_cancel);
170 return __gthread_active_ptr != 0;
173 #endif /* Solaris */
175 #else /* not SUPPORTS_WEAK */
177 /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
178 calls in shared flavors of the HP-UX C library. Most of the stubs
179 have no functionality. The details are described in the "libc cumulative
180 patch" for each subversion of HP-UX 11. There are two special interfaces
181 provided for checking whether an application is linked to a pthread
182 library or not. However, these interfaces aren't available in early
183 libc versions. We also can't use pthread_once as some libc versions
184 call the init function. So, we use pthread_create to check whether it
185 is possible to create a thread or not. The stub implementation returns
186 the error number ENOSYS. */
188 #if defined(__hppa__) && defined(__hpux__)
190 #include <errno.h>
192 static volatile int __gthread_active = -1;
194 static void *
195 __gthread_start (void *arg __attribute__((unused)))
197 return NULL;
200 static void __gthread_active_init (void) __attribute__((noinline));
201 static void
202 __gthread_active_init (void)
204 static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
205 pthread_t t;
206 int result;
208 __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
209 if (__gthread_active < 0)
211 result = __gthrw_(pthread_create) (&t, NULL, __gthread_start, NULL);
212 if (result != ENOSYS)
214 __gthread_active = 1;
215 if (!result)
216 __gthrw_(pthread_join) (t, NULL);
218 else
219 __gthread_active = 0;
221 __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
224 static inline int
225 __gthread_active_p (void)
227 /* Avoid reading __gthread_active twice on the main code path. */
228 int __gthread_active_latest_value = __gthread_active;
230 /* This test is not protected to avoid taking a lock on the main code
231 path so every update of __gthread_active in a threaded program must
232 be atomic with regard to the result of the test. */
233 if (__builtin_expect (__gthread_active_latest_value < 0, 0))
235 __gthread_active_init ();
236 __gthread_active_latest_value = __gthread_active;
239 return __gthread_active_latest_value != 0;
242 #else /* not hppa-hpux */
244 static inline int
245 __gthread_active_p (void)
247 return 1;
250 #endif /* hppa-hpux */
252 #endif /* SUPPORTS_WEAK */
254 #ifdef _LIBOBJC
256 /* This is the config.h file in libobjc/ */
257 #include <config.h>
259 #ifdef HAVE_SCHED_H
260 # include <sched.h>
261 #endif
263 /* Key structure for maintaining thread specific storage */
264 static pthread_key_t _objc_thread_storage;
265 static pthread_attr_t _objc_thread_attribs;
267 /* Thread local storage for a single thread */
268 static void *thread_local_storage = NULL;
270 /* Backend initialization functions */
272 /* Initialize the threads subsystem. */
273 static inline int
274 __gthread_objc_init_thread_system (void)
276 if (__gthread_active_p ())
278 /* Initialize the thread storage key. */
279 if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
281 /* The normal default detach state for threads is
282 * PTHREAD_CREATE_JOINABLE which causes threads to not die
283 * when you think they should. */
284 if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
285 && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
286 PTHREAD_CREATE_DETACHED) == 0)
287 return 0;
291 return -1;
294 /* Close the threads subsystem. */
295 static inline int
296 __gthread_objc_close_thread_system (void)
298 if (__gthread_active_p ()
299 && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
300 && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
301 return 0;
303 return -1;
306 /* Backend thread functions */
308 /* Create a new thread of execution. */
309 static inline objc_thread_t
310 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
312 objc_thread_t thread_id;
313 pthread_t new_thread_handle;
315 if (!__gthread_active_p ())
316 return NULL;
318 if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
319 thread_id = (objc_thread_t) new_thread_handle;
320 else
321 thread_id = NULL;
323 return thread_id;
326 /* Set the current thread's priority. */
327 static inline int
328 __gthread_objc_thread_set_priority (int priority)
330 if (!__gthread_active_p ())
331 return -1;
332 else
334 #ifdef _POSIX_PRIORITY_SCHEDULING
335 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
336 pthread_t thread_id = __gthrw_(pthread_self) ();
337 int policy;
338 struct sched_param params;
339 int priority_min, priority_max;
341 if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
343 if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
344 return -1;
346 if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
347 return -1;
349 if (priority > priority_max)
350 priority = priority_max;
351 else if (priority < priority_min)
352 priority = priority_min;
353 params.sched_priority = priority;
356 * The solaris 7 and several other man pages incorrectly state that
357 * this should be a pointer to policy but pthread.h is universally
358 * at odds with this.
360 if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
361 return 0;
363 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
364 #endif /* _POSIX_PRIORITY_SCHEDULING */
365 return -1;
369 /* Return the current thread's priority. */
370 static inline int
371 __gthread_objc_thread_get_priority (void)
373 #ifdef _POSIX_PRIORITY_SCHEDULING
374 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
375 if (__gthread_active_p ())
377 int policy;
378 struct sched_param params;
380 if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
381 return params.sched_priority;
382 else
383 return -1;
385 else
386 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
387 #endif /* _POSIX_PRIORITY_SCHEDULING */
388 return OBJC_THREAD_INTERACTIVE_PRIORITY;
391 /* Yield our process time to another thread. */
392 static inline void
393 __gthread_objc_thread_yield (void)
395 if (__gthread_active_p ())
396 __gthrw_(sched_yield) ();
399 /* Terminate the current thread. */
400 static inline int
401 __gthread_objc_thread_exit (void)
403 if (__gthread_active_p ())
404 /* exit the thread */
405 __gthrw_(pthread_exit) (&__objc_thread_exit_status);
407 /* Failed if we reached here */
408 return -1;
411 /* Returns an integer value which uniquely describes a thread. */
412 static inline objc_thread_t
413 __gthread_objc_thread_id (void)
415 if (__gthread_active_p ())
416 return (objc_thread_t) __gthrw_(pthread_self) ();
417 else
418 return (objc_thread_t) 1;
421 /* Sets the thread's local storage pointer. */
422 static inline int
423 __gthread_objc_thread_set_data (void *value)
425 if (__gthread_active_p ())
426 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
427 else
429 thread_local_storage = value;
430 return 0;
434 /* Returns the thread's local storage pointer. */
435 static inline void *
436 __gthread_objc_thread_get_data (void)
438 if (__gthread_active_p ())
439 return __gthrw_(pthread_getspecific) (_objc_thread_storage);
440 else
441 return thread_local_storage;
444 /* Backend mutex functions */
446 /* Allocate a mutex. */
447 static inline int
448 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
450 if (__gthread_active_p ())
452 mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
454 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
456 objc_free (mutex->backend);
457 mutex->backend = NULL;
458 return -1;
462 return 0;
465 /* Deallocate a mutex. */
466 static inline int
467 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
469 if (__gthread_active_p ())
471 int count;
474 * Posix Threads specifically require that the thread be unlocked
475 * for __gthrw_(pthread_mutex_destroy) to work.
480 count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
481 if (count < 0)
482 return -1;
484 while (count);
486 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
487 return -1;
489 objc_free (mutex->backend);
490 mutex->backend = NULL;
492 return 0;
495 /* Grab a lock on a mutex. */
496 static inline int
497 __gthread_objc_mutex_lock (objc_mutex_t mutex)
499 if (__gthread_active_p ()
500 && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
502 return -1;
505 return 0;
508 /* Try to grab a lock on a mutex. */
509 static inline int
510 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
512 if (__gthread_active_p ()
513 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
515 return -1;
518 return 0;
521 /* Unlock the mutex */
522 static inline int
523 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
525 if (__gthread_active_p ()
526 && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
528 return -1;
531 return 0;
534 /* Backend condition mutex functions */
536 /* Allocate a condition. */
537 static inline int
538 __gthread_objc_condition_allocate (objc_condition_t condition)
540 if (__gthread_active_p ())
542 condition->backend = objc_malloc (sizeof (pthread_cond_t));
544 if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
546 objc_free (condition->backend);
547 condition->backend = NULL;
548 return -1;
552 return 0;
555 /* Deallocate a condition. */
556 static inline int
557 __gthread_objc_condition_deallocate (objc_condition_t condition)
559 if (__gthread_active_p ())
561 if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
562 return -1;
564 objc_free (condition->backend);
565 condition->backend = NULL;
567 return 0;
570 /* Wait on the condition */
571 static inline int
572 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
574 if (__gthread_active_p ())
575 return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
576 (pthread_mutex_t *) mutex->backend);
577 else
578 return 0;
581 /* Wake up all threads waiting on this condition. */
582 static inline int
583 __gthread_objc_condition_broadcast (objc_condition_t condition)
585 if (__gthread_active_p ())
586 return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
587 else
588 return 0;
591 /* Wake up one thread waiting on this condition. */
592 static inline int
593 __gthread_objc_condition_signal (objc_condition_t condition)
595 if (__gthread_active_p ())
596 return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
597 else
598 return 0;
601 #else /* _LIBOBJC */
603 static inline int
604 __gthread_once (__gthread_once_t *once, void (*func) (void))
606 if (__gthread_active_p ())
607 return __gthrw_(pthread_once) (once, func);
608 else
609 return -1;
612 static inline int
613 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
615 return __gthrw_(pthread_key_create) (key, dtor);
618 static inline int
619 __gthread_key_delete (__gthread_key_t key)
621 return __gthrw_(pthread_key_delete) (key);
624 static inline void *
625 __gthread_getspecific (__gthread_key_t key)
627 return __gthrw_(pthread_getspecific) (key);
630 static inline int
631 __gthread_setspecific (__gthread_key_t key, const void *ptr)
633 return __gthrw_(pthread_setspecific) (key, ptr);
636 static inline int
637 __gthread_mutex_lock (__gthread_mutex_t *mutex)
639 if (__gthread_active_p ())
640 return __gthrw_(pthread_mutex_lock) (mutex);
641 else
642 return 0;
645 static inline int
646 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
648 if (__gthread_active_p ())
649 return __gthrw_(pthread_mutex_trylock) (mutex);
650 else
651 return 0;
654 static inline int
655 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
657 if (__gthread_active_p ())
658 return __gthrw_(pthread_mutex_unlock) (mutex);
659 else
660 return 0;
663 static inline int
664 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
666 mutex->depth = 0;
667 mutex->owner = (pthread_t) 0;
668 return __gthrw_(pthread_mutex_init) (&mutex->actual, NULL);
671 static inline int
672 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
674 if (__gthread_active_p ())
676 pthread_t me = __gthrw_(pthread_self) ();
678 if (mutex->owner != me)
680 __gthrw_(pthread_mutex_lock) (&mutex->actual);
681 mutex->owner = me;
684 mutex->depth++;
686 return 0;
689 static inline int
690 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
692 if (__gthread_active_p ())
694 pthread_t me = __gthrw_(pthread_self) ();
696 if (mutex->owner != me)
698 if (__gthrw_(pthread_mutex_trylock) (&mutex->actual))
699 return 1;
700 mutex->owner = me;
703 mutex->depth++;
705 return 0;
708 static inline int
709 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
711 if (__gthread_active_p ())
713 if (--mutex->depth == 0)
715 mutex->owner = (pthread_t) 0;
716 __gthrw_(pthread_mutex_unlock) (&mutex->actual);
719 return 0;
722 #endif /* _LIBOBJC */
724 #endif /* ! GCC_GTHR_POSIX_H */