2006-02-25 Thomas Koenig <Thomas.Koenig@online.de>
[official-gcc.git] / gcc / gthr-posix.h
blobdf03947e606db87d0fa8430e7a17b096a1660d23
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) \
63 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name2)));
64 # define __gthrw_(name) __gthrw_ ## name
65 #else
66 # define __gthrw2(name,name2)
67 # define __gthrw_(name) name
68 #endif
70 /* Typically, __gthrw_foo is a weak reference to symbol foo. */
71 #define __gthrw(name) __gthrw2(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 __gthrw2(pthread_once,__pthread_once)
78 __gthrw2(pthread_getspecific,__pthread_getspecific)
79 __gthrw2(pthread_setspecific,__pthread_setspecific)
80 __gthrw2(pthread_create,__pthread_create)
81 __gthrw2(pthread_cancel,__pthread_cancel)
82 __gthrw2(pthread_mutex_lock,__pthread_mutex_lock)
83 __gthrw2(pthread_mutex_trylock,__pthread_mutex_trylock)
84 __gthrw2(pthread_mutex_unlock,__pthread_mutex_unlock)
85 __gthrw2(pthread_mutex_init,__pthread_mutex_init)
86 #else
87 __gthrw(pthread_once)
88 __gthrw(pthread_getspecific)
89 __gthrw(pthread_setspecific)
90 __gthrw(pthread_create)
91 __gthrw(pthread_cancel)
92 __gthrw(pthread_mutex_lock)
93 __gthrw(pthread_mutex_trylock)
94 __gthrw(pthread_mutex_unlock)
95 __gthrw(pthread_mutex_init)
96 #endif
98 __gthrw(pthread_key_create)
99 __gthrw(pthread_key_delete)
100 __gthrw(pthread_mutexattr_init)
101 __gthrw(pthread_mutexattr_settype)
102 __gthrw(pthread_mutexattr_destroy)
105 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
106 /* Objective-C. */
107 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
108 __gthrw2(pthread_cond_broadcast,__pthread_cond_broadcast)
109 __gthrw2(pthread_cond_destroy,__pthread_cond_destroy)
110 __gthrw2(pthread_cond_init,__pthread_cond_init)
111 __gthrw2(pthread_cond_signal,__pthread_cond_signal)
112 __gthrw2(pthread_cond_wait,__pthread_cond_wait)
113 __gthrw2(pthread_exit,__pthread_exit)
114 __gthrw2(pthread_mutex_destroy,__pthread_mutex_destroy)
115 __gthrw2(pthread_self,__pthread_self)
116 #else
117 __gthrw(pthread_cond_broadcast)
118 __gthrw(pthread_cond_destroy)
119 __gthrw(pthread_cond_init)
120 __gthrw(pthread_cond_signal)
121 __gthrw(pthread_cond_wait)
122 __gthrw(pthread_exit)
123 __gthrw(pthread_mutex_destroy)
124 __gthrw(pthread_self)
125 #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
126 #ifdef _POSIX_PRIORITY_SCHEDULING
127 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
128 __gthrw(sched_get_priority_max)
129 __gthrw(sched_get_priority_min)
130 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
131 #endif /* _POSIX_PRIORITY_SCHEDULING */
132 __gthrw(sched_yield)
133 __gthrw(pthread_attr_destroy)
134 __gthrw(pthread_attr_init)
135 __gthrw(pthread_attr_setdetachstate)
136 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
137 __gthrw(pthread_getschedparam)
138 __gthrw(pthread_setschedparam)
139 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
140 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
142 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
144 static inline int
145 __gthread_active_p (void)
147 static void *const __gthread_active_ptr
148 = __extension__ (void *) &__gthrw_(pthread_cancel);
149 return __gthread_active_ptr != 0;
152 #else /* not SUPPORTS_WEAK */
154 static inline int
155 __gthread_active_p (void)
157 return 1;
160 #endif /* SUPPORTS_WEAK */
162 #ifdef _LIBOBJC
164 /* This is the config.h file in libobjc/ */
165 #include <config.h>
167 #ifdef HAVE_SCHED_H
168 # include <sched.h>
169 #endif
171 /* Key structure for maintaining thread specific storage */
172 static pthread_key_t _objc_thread_storage;
173 static pthread_attr_t _objc_thread_attribs;
175 /* Thread local storage for a single thread */
176 static void *thread_local_storage = NULL;
178 /* Backend initialization functions */
180 /* Initialize the threads subsystem. */
181 static inline int
182 __gthread_objc_init_thread_system (void)
184 if (__gthread_active_p ())
186 /* Initialize the thread storage key. */
187 if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
189 /* The normal default detach state for threads is
190 * PTHREAD_CREATE_JOINABLE which causes threads to not die
191 * when you think they should. */
192 if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
193 && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
194 PTHREAD_CREATE_DETACHED) == 0)
195 return 0;
199 return -1;
202 /* Close the threads subsystem. */
203 static inline int
204 __gthread_objc_close_thread_system (void)
206 if (__gthread_active_p ()
207 && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
208 && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
209 return 0;
211 return -1;
214 /* Backend thread functions */
216 /* Create a new thread of execution. */
217 static inline objc_thread_t
218 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
220 objc_thread_t thread_id;
221 pthread_t new_thread_handle;
223 if (!__gthread_active_p ())
224 return NULL;
226 if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
227 thread_id = (objc_thread_t) new_thread_handle;
228 else
229 thread_id = NULL;
231 return thread_id;
234 /* Set the current thread's priority. */
235 static inline int
236 __gthread_objc_thread_set_priority (int priority)
238 if (!__gthread_active_p ())
239 return -1;
240 else
242 #ifdef _POSIX_PRIORITY_SCHEDULING
243 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
244 pthread_t thread_id = __gthrw_(pthread_self) ();
245 int policy;
246 struct sched_param params;
247 int priority_min, priority_max;
249 if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
251 if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
252 return -1;
254 if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
255 return -1;
257 if (priority > priority_max)
258 priority = priority_max;
259 else if (priority < priority_min)
260 priority = priority_min;
261 params.sched_priority = priority;
264 * The solaris 7 and several other man pages incorrectly state that
265 * this should be a pointer to policy but pthread.h is universally
266 * at odds with this.
268 if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
269 return 0;
271 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
272 #endif /* _POSIX_PRIORITY_SCHEDULING */
273 return -1;
277 /* Return the current thread's priority. */
278 static inline int
279 __gthread_objc_thread_get_priority (void)
281 #ifdef _POSIX_PRIORITY_SCHEDULING
282 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
283 if (__gthread_active_p ())
285 int policy;
286 struct sched_param params;
288 if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
289 return params.sched_priority;
290 else
291 return -1;
293 else
294 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
295 #endif /* _POSIX_PRIORITY_SCHEDULING */
296 return OBJC_THREAD_INTERACTIVE_PRIORITY;
299 /* Yield our process time to another thread. */
300 static inline void
301 __gthread_objc_thread_yield (void)
303 if (__gthread_active_p ())
304 __gthrw_(sched_yield) ();
307 /* Terminate the current thread. */
308 static inline int
309 __gthread_objc_thread_exit (void)
311 if (__gthread_active_p ())
312 /* exit the thread */
313 __gthrw_(pthread_exit) (&__objc_thread_exit_status);
315 /* Failed if we reached here */
316 return -1;
319 /* Returns an integer value which uniquely describes a thread. */
320 static inline objc_thread_t
321 __gthread_objc_thread_id (void)
323 if (__gthread_active_p ())
324 return (objc_thread_t) __gthrw_(pthread_self) ();
325 else
326 return (objc_thread_t) 1;
329 /* Sets the thread's local storage pointer. */
330 static inline int
331 __gthread_objc_thread_set_data (void *value)
333 if (__gthread_active_p ())
334 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
335 else
337 thread_local_storage = value;
338 return 0;
342 /* Returns the thread's local storage pointer. */
343 static inline void *
344 __gthread_objc_thread_get_data (void)
346 if (__gthread_active_p ())
347 return __gthrw_(pthread_getspecific) (_objc_thread_storage);
348 else
349 return thread_local_storage;
352 /* Backend mutex functions */
354 /* Allocate a mutex. */
355 static inline int
356 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
358 if (__gthread_active_p ())
360 mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
362 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
364 objc_free (mutex->backend);
365 mutex->backend = NULL;
366 return -1;
370 return 0;
373 /* Deallocate a mutex. */
374 static inline int
375 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
377 if (__gthread_active_p ())
379 int count;
382 * Posix Threads specifically require that the thread be unlocked
383 * for __gthrw_(pthread_mutex_destroy) to work.
388 count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
389 if (count < 0)
390 return -1;
392 while (count);
394 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
395 return -1;
397 objc_free (mutex->backend);
398 mutex->backend = NULL;
400 return 0;
403 /* Grab a lock on a mutex. */
404 static inline int
405 __gthread_objc_mutex_lock (objc_mutex_t mutex)
407 if (__gthread_active_p ()
408 && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
410 return -1;
413 return 0;
416 /* Try to grab a lock on a mutex. */
417 static inline int
418 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
420 if (__gthread_active_p ()
421 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
423 return -1;
426 return 0;
429 /* Unlock the mutex */
430 static inline int
431 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
433 if (__gthread_active_p ()
434 && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
436 return -1;
439 return 0;
442 /* Backend condition mutex functions */
444 /* Allocate a condition. */
445 static inline int
446 __gthread_objc_condition_allocate (objc_condition_t condition)
448 if (__gthread_active_p ())
450 condition->backend = objc_malloc (sizeof (pthread_cond_t));
452 if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
454 objc_free (condition->backend);
455 condition->backend = NULL;
456 return -1;
460 return 0;
463 /* Deallocate a condition. */
464 static inline int
465 __gthread_objc_condition_deallocate (objc_condition_t condition)
467 if (__gthread_active_p ())
469 if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
470 return -1;
472 objc_free (condition->backend);
473 condition->backend = NULL;
475 return 0;
478 /* Wait on the condition */
479 static inline int
480 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
482 if (__gthread_active_p ())
483 return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
484 (pthread_mutex_t *) mutex->backend);
485 else
486 return 0;
489 /* Wake up all threads waiting on this condition. */
490 static inline int
491 __gthread_objc_condition_broadcast (objc_condition_t condition)
493 if (__gthread_active_p ())
494 return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
495 else
496 return 0;
499 /* Wake up one thread waiting on this condition. */
500 static inline int
501 __gthread_objc_condition_signal (objc_condition_t condition)
503 if (__gthread_active_p ())
504 return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
505 else
506 return 0;
509 #else /* _LIBOBJC */
511 static inline int
512 __gthread_once (__gthread_once_t *once, void (*func) (void))
514 if (__gthread_active_p ())
515 return __gthrw_(pthread_once) (once, func);
516 else
517 return -1;
520 static inline int
521 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
523 return __gthrw_(pthread_key_create) (key, dtor);
526 static inline int
527 __gthread_key_delete (__gthread_key_t key)
529 return __gthrw_(pthread_key_delete) (key);
532 static inline void *
533 __gthread_getspecific (__gthread_key_t key)
535 return __gthrw_(pthread_getspecific) (key);
538 static inline int
539 __gthread_setspecific (__gthread_key_t key, const void *ptr)
541 return __gthrw_(pthread_setspecific) (key, ptr);
544 static inline int
545 __gthread_mutex_lock (__gthread_mutex_t *mutex)
547 if (__gthread_active_p ())
548 return __gthrw_(pthread_mutex_lock) (mutex);
549 else
550 return 0;
553 static inline int
554 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
556 if (__gthread_active_p ())
557 return __gthrw_(pthread_mutex_trylock) (mutex);
558 else
559 return 0;
562 static inline int
563 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
565 if (__gthread_active_p ())
566 return __gthrw_(pthread_mutex_unlock) (mutex);
567 else
568 return 0;
571 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
572 static inline int
573 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
575 if (__gthread_active_p ())
577 pthread_mutexattr_t attr;
578 int r;
580 r = __gthrw_(pthread_mutexattr_init) (&attr);
581 if (!r)
582 r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
583 if (!r)
584 r = __gthrw_(pthread_mutex_init) (mutex, &attr);
585 if (!r)
586 r = __gthrw_(pthread_mutexattr_destroy) (&attr);
587 return r;
589 return 0;
591 #endif
593 static inline int
594 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
596 return __gthread_mutex_lock (mutex);
599 static inline int
600 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
602 return __gthread_mutex_trylock (mutex);
605 static inline int
606 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
608 return __gthread_mutex_unlock (mutex);
611 #endif /* _LIBOBJC */
613 #endif /* ! GCC_GTHR_POSIX_H */