2006-08-06 Paolo Carlini <pcarlini@suse.de>
[official-gcc.git] / gcc / gthr-posix.h
blob62f83b3ffbcbe05ef40b45a7f7de71577a0ca48a
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
4 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to the Free
20 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, USA. */
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. */
30 #ifndef GCC_GTHR_POSIX_H
31 #define GCC_GTHR_POSIX_H
33 /* POSIX threads specific definitions.
34 Easy, since the interface is just one-to-one mapping. */
36 #define __GTHREADS 1
38 /* Some implementations of <pthread.h> require this to be defined. */
39 #ifndef _REENTRANT
40 #define _REENTRANT 1
41 #endif
43 #include <pthread.h>
44 #include <unistd.h>
46 typedef pthread_key_t __gthread_key_t;
47 typedef pthread_once_t __gthread_once_t;
48 typedef pthread_mutex_t __gthread_mutex_t;
49 typedef pthread_mutex_t __gthread_recursive_mutex_t;
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
61 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
62 # define __gthrw2(name,name2,type) \
63 static __typeof(type) name __attribute__ ((__weakref__(#name2)));
64 # define __gthrw_(name) __gthrw_ ## name
65 #else
66 # define __gthrw2(name,name2,type)
67 # define __gthrw_(name) name
68 #endif
70 /* Typically, __gthrw_foo is a weak reference to symbol foo. */
71 #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
73 /* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
74 map a subset of the POSIX pthread API to mangled versions of their
75 names. */
76 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
77 #define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
78 __gthrw3(pthread_once)
79 __gthrw3(pthread_getspecific)
80 __gthrw3(pthread_setspecific)
81 __gthrw3(pthread_create)
82 __gthrw3(pthread_cancel)
83 __gthrw3(pthread_mutex_lock)
84 __gthrw3(pthread_mutex_trylock)
85 __gthrw3(pthread_mutex_unlock)
86 __gthrw3(pthread_mutex_init)
87 #else
88 __gthrw(pthread_once)
89 __gthrw(pthread_getspecific)
90 __gthrw(pthread_setspecific)
91 __gthrw(pthread_create)
92 __gthrw(pthread_cancel)
93 __gthrw(pthread_mutex_lock)
94 __gthrw(pthread_mutex_trylock)
95 __gthrw(pthread_mutex_unlock)
96 __gthrw(pthread_mutex_init)
97 #endif
99 __gthrw(pthread_key_create)
100 __gthrw(pthread_key_delete)
101 __gthrw(pthread_mutexattr_init)
102 __gthrw(pthread_mutexattr_settype)
103 __gthrw(pthread_mutexattr_destroy)
106 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
107 /* Objective-C. */
108 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
109 __gthrw3(pthread_cond_broadcast)
110 __gthrw3(pthread_cond_destroy)
111 __gthrw3(pthread_cond_init)
112 __gthrw3(pthread_cond_signal)
113 __gthrw3(pthread_cond_wait)
114 __gthrw3(pthread_exit)
115 __gthrw3(pthread_mutex_destroy)
116 __gthrw3(pthread_self)
117 #else
118 __gthrw(pthread_cond_broadcast)
119 __gthrw(pthread_cond_destroy)
120 __gthrw(pthread_cond_init)
121 __gthrw(pthread_cond_signal)
122 __gthrw(pthread_cond_wait)
123 __gthrw(pthread_exit)
124 __gthrw(pthread_mutex_destroy)
125 __gthrw(pthread_self)
126 #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
127 #ifdef _POSIX_PRIORITY_SCHEDULING
128 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
129 __gthrw(sched_get_priority_max)
130 __gthrw(sched_get_priority_min)
131 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
132 #endif /* _POSIX_PRIORITY_SCHEDULING */
133 __gthrw(sched_yield)
134 __gthrw(pthread_attr_destroy)
135 __gthrw(pthread_attr_init)
136 __gthrw(pthread_attr_setdetachstate)
137 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
138 __gthrw(pthread_getschedparam)
139 __gthrw(pthread_setschedparam)
140 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
141 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
143 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
145 static inline int
146 __gthread_active_p (void)
148 static void *const __gthread_active_ptr
149 = __extension__ (void *) &__gthrw_(pthread_cancel);
150 return __gthread_active_ptr != 0;
153 #else /* not SUPPORTS_WEAK */
155 static inline int
156 __gthread_active_p (void)
158 return 1;
161 #endif /* SUPPORTS_WEAK */
163 #ifdef _LIBOBJC
165 /* This is the config.h file in libobjc/ */
166 #include <config.h>
168 #ifdef HAVE_SCHED_H
169 # include <sched.h>
170 #endif
172 /* Key structure for maintaining thread specific storage */
173 static pthread_key_t _objc_thread_storage;
174 static pthread_attr_t _objc_thread_attribs;
176 /* Thread local storage for a single thread */
177 static void *thread_local_storage = NULL;
179 /* Backend initialization functions */
181 /* Initialize the threads subsystem. */
182 static inline int
183 __gthread_objc_init_thread_system (void)
185 if (__gthread_active_p ())
187 /* Initialize the thread storage key. */
188 if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
190 /* The normal default detach state for threads is
191 * PTHREAD_CREATE_JOINABLE which causes threads to not die
192 * when you think they should. */
193 if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
194 && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
195 PTHREAD_CREATE_DETACHED) == 0)
196 return 0;
200 return -1;
203 /* Close the threads subsystem. */
204 static inline int
205 __gthread_objc_close_thread_system (void)
207 if (__gthread_active_p ()
208 && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
209 && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
210 return 0;
212 return -1;
215 /* Backend thread functions */
217 /* Create a new thread of execution. */
218 static inline objc_thread_t
219 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
221 objc_thread_t thread_id;
222 pthread_t new_thread_handle;
224 if (!__gthread_active_p ())
225 return NULL;
227 if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
228 thread_id = (objc_thread_t) new_thread_handle;
229 else
230 thread_id = NULL;
232 return thread_id;
235 /* Set the current thread's priority. */
236 static inline int
237 __gthread_objc_thread_set_priority (int priority)
239 if (!__gthread_active_p ())
240 return -1;
241 else
243 #ifdef _POSIX_PRIORITY_SCHEDULING
244 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
245 pthread_t thread_id = __gthrw_(pthread_self) ();
246 int policy;
247 struct sched_param params;
248 int priority_min, priority_max;
250 if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
252 if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
253 return -1;
255 if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
256 return -1;
258 if (priority > priority_max)
259 priority = priority_max;
260 else if (priority < priority_min)
261 priority = priority_min;
262 params.sched_priority = priority;
265 * The solaris 7 and several other man pages incorrectly state that
266 * this should be a pointer to policy but pthread.h is universally
267 * at odds with this.
269 if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
270 return 0;
272 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
273 #endif /* _POSIX_PRIORITY_SCHEDULING */
274 return -1;
278 /* Return the current thread's priority. */
279 static inline int
280 __gthread_objc_thread_get_priority (void)
282 #ifdef _POSIX_PRIORITY_SCHEDULING
283 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
284 if (__gthread_active_p ())
286 int policy;
287 struct sched_param params;
289 if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
290 return params.sched_priority;
291 else
292 return -1;
294 else
295 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
296 #endif /* _POSIX_PRIORITY_SCHEDULING */
297 return OBJC_THREAD_INTERACTIVE_PRIORITY;
300 /* Yield our process time to another thread. */
301 static inline void
302 __gthread_objc_thread_yield (void)
304 if (__gthread_active_p ())
305 __gthrw_(sched_yield) ();
308 /* Terminate the current thread. */
309 static inline int
310 __gthread_objc_thread_exit (void)
312 if (__gthread_active_p ())
313 /* exit the thread */
314 __gthrw_(pthread_exit) (&__objc_thread_exit_status);
316 /* Failed if we reached here */
317 return -1;
320 /* Returns an integer value which uniquely describes a thread. */
321 static inline objc_thread_t
322 __gthread_objc_thread_id (void)
324 if (__gthread_active_p ())
325 return (objc_thread_t) __gthrw_(pthread_self) ();
326 else
327 return (objc_thread_t) 1;
330 /* Sets the thread's local storage pointer. */
331 static inline int
332 __gthread_objc_thread_set_data (void *value)
334 if (__gthread_active_p ())
335 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
336 else
338 thread_local_storage = value;
339 return 0;
343 /* Returns the thread's local storage pointer. */
344 static inline void *
345 __gthread_objc_thread_get_data (void)
347 if (__gthread_active_p ())
348 return __gthrw_(pthread_getspecific) (_objc_thread_storage);
349 else
350 return thread_local_storage;
353 /* Backend mutex functions */
355 /* Allocate a mutex. */
356 static inline int
357 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
359 if (__gthread_active_p ())
361 mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
363 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
365 objc_free (mutex->backend);
366 mutex->backend = NULL;
367 return -1;
371 return 0;
374 /* Deallocate a mutex. */
375 static inline int
376 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
378 if (__gthread_active_p ())
380 int count;
383 * Posix Threads specifically require that the thread be unlocked
384 * for __gthrw_(pthread_mutex_destroy) to work.
389 count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
390 if (count < 0)
391 return -1;
393 while (count);
395 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
396 return -1;
398 objc_free (mutex->backend);
399 mutex->backend = NULL;
401 return 0;
404 /* Grab a lock on a mutex. */
405 static inline int
406 __gthread_objc_mutex_lock (objc_mutex_t mutex)
408 if (__gthread_active_p ()
409 && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
411 return -1;
414 return 0;
417 /* Try to grab a lock on a mutex. */
418 static inline int
419 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
421 if (__gthread_active_p ()
422 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
424 return -1;
427 return 0;
430 /* Unlock the mutex */
431 static inline int
432 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
434 if (__gthread_active_p ()
435 && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
437 return -1;
440 return 0;
443 /* Backend condition mutex functions */
445 /* Allocate a condition. */
446 static inline int
447 __gthread_objc_condition_allocate (objc_condition_t condition)
449 if (__gthread_active_p ())
451 condition->backend = objc_malloc (sizeof (pthread_cond_t));
453 if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
455 objc_free (condition->backend);
456 condition->backend = NULL;
457 return -1;
461 return 0;
464 /* Deallocate a condition. */
465 static inline int
466 __gthread_objc_condition_deallocate (objc_condition_t condition)
468 if (__gthread_active_p ())
470 if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
471 return -1;
473 objc_free (condition->backend);
474 condition->backend = NULL;
476 return 0;
479 /* Wait on the condition */
480 static inline int
481 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
483 if (__gthread_active_p ())
484 return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
485 (pthread_mutex_t *) mutex->backend);
486 else
487 return 0;
490 /* Wake up all threads waiting on this condition. */
491 static inline int
492 __gthread_objc_condition_broadcast (objc_condition_t condition)
494 if (__gthread_active_p ())
495 return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
496 else
497 return 0;
500 /* Wake up one thread waiting on this condition. */
501 static inline int
502 __gthread_objc_condition_signal (objc_condition_t condition)
504 if (__gthread_active_p ())
505 return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
506 else
507 return 0;
510 #else /* _LIBOBJC */
512 static inline int
513 __gthread_once (__gthread_once_t *once, void (*func) (void))
515 if (__gthread_active_p ())
516 return __gthrw_(pthread_once) (once, func);
517 else
518 return -1;
521 static inline int
522 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
524 return __gthrw_(pthread_key_create) (key, dtor);
527 static inline int
528 __gthread_key_delete (__gthread_key_t key)
530 return __gthrw_(pthread_key_delete) (key);
533 static inline void *
534 __gthread_getspecific (__gthread_key_t key)
536 return __gthrw_(pthread_getspecific) (key);
539 static inline int
540 __gthread_setspecific (__gthread_key_t key, const void *ptr)
542 return __gthrw_(pthread_setspecific) (key, ptr);
545 static inline int
546 __gthread_mutex_lock (__gthread_mutex_t *mutex)
548 if (__gthread_active_p ())
549 return __gthrw_(pthread_mutex_lock) (mutex);
550 else
551 return 0;
554 static inline int
555 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
557 if (__gthread_active_p ())
558 return __gthrw_(pthread_mutex_trylock) (mutex);
559 else
560 return 0;
563 static inline int
564 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
566 if (__gthread_active_p ())
567 return __gthrw_(pthread_mutex_unlock) (mutex);
568 else
569 return 0;
572 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
573 static inline int
574 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
576 if (__gthread_active_p ())
578 pthread_mutexattr_t attr;
579 int r;
581 r = __gthrw_(pthread_mutexattr_init) (&attr);
582 if (!r)
583 r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
584 if (!r)
585 r = __gthrw_(pthread_mutex_init) (mutex, &attr);
586 if (!r)
587 r = __gthrw_(pthread_mutexattr_destroy) (&attr);
588 return r;
590 return 0;
592 #endif
594 static inline int
595 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
597 return __gthread_mutex_lock (mutex);
600 static inline int
601 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
603 return __gthread_mutex_trylock (mutex);
606 static inline int
607 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
609 return __gthread_mutex_unlock (mutex);
612 #endif /* _LIBOBJC */
614 #endif /* ! GCC_GTHR_POSIX_H */