]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gthr-posix.h
* predict.c (propagate_freq): Make bitno unsigned. Move
[thirdparty/gcc.git] / gcc / gthr-posix.h
CommitLineData
6319d58e 1/* Threads compatibility routines for libgcc2 and libobjc. */
58febf9e 2/* Compile this one with gcc. */
0ba508e4 3/* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004
ecd34a08 4 Free Software Foundation, Inc.
58febf9e 5
f12b58b3 6This file is part of GCC.
58febf9e 7
f12b58b3 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.
58febf9e 12
f12b58b3 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.
58febf9e 17
18You should have received a copy of the GNU General Public License
f12b58b3 19along with GCC; see the file COPYING. If not, write to the Free
20Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2102111-1307, USA. */
58febf9e 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
2a281353 30#ifndef GCC_GTHR_POSIX_H
31#define GCC_GTHR_POSIX_H
58febf9e 32
33/* POSIX threads specific definitions.
5a54c45e 34 Easy, since the interface is just one-to-one mapping. */
58febf9e 35
36#define __GTHREADS 1
37
ecd34a08 38/* Some implementations of <pthread.h> require this to be defined. */
39#ifndef _REENTRANT
40#define _REENTRANT 1
41#endif
42
58febf9e 43#include <pthread.h>
f9f6f55a 44#include <unistd.h>
58febf9e 45
46typedef pthread_key_t __gthread_key_t;
47typedef pthread_once_t __gthread_once_t;
48typedef pthread_mutex_t __gthread_mutex_t;
4813f5af 49typedef pthread_mutex_t __gthread_recursive_mutex_t;
58febf9e 50
51#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
52#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
4813f5af 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
ff00b6c5 57#elif defined(PTHREAD_MUTEX_RECURSIVE)
4813f5af 58#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
ff00b6c5 59#else
60#define __GTHREAD_RECURSIVE_MUTEX_INIT RECURSIVE_ERRORCHECKMUTEX
4813f5af 61#endif
58febf9e 62
63#if SUPPORTS_WEAK && GTHREAD_USE_WEAK
64
6319d58e 65#pragma weak pthread_once
66#pragma weak pthread_key_create
67#pragma weak pthread_key_delete
68#pragma weak pthread_getspecific
69#pragma weak pthread_setspecific
70#pragma weak pthread_create
2f5d30d9 71
3cfec666 72#pragma weak pthread_mutex_lock
73#pragma weak pthread_mutex_trylock
74#pragma weak pthread_mutex_unlock
fcbbb04c 75#pragma weak pthread_mutexattr_init
76#pragma weak pthread_mutexattr_settype
77#pragma weak pthread_mutexattr_destroy
78
79#pragma weak pthread_mutex_init
6319d58e 80
ecd34a08 81#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
7fd957fe 82/* Objective-C. */
6319d58e 83#pragma weak pthread_cond_broadcast
84#pragma weak pthread_cond_destroy
85#pragma weak pthread_cond_init
86#pragma weak pthread_cond_signal
87#pragma weak pthread_cond_wait
88#pragma weak pthread_exit
6319d58e 89#pragma weak pthread_mutex_destroy
90#pragma weak pthread_self
a55f666d 91#ifdef _POSIX_PRIORITY_SCHEDULING
f9f6f55a 92#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
23ab4af6 93#pragma weak sched_get_priority_max
94#pragma weak sched_get_priority_min
f9f6f55a 95#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
a55f666d 96#endif /* _POSIX_PRIORITY_SCHEDULING */
6319d58e 97#pragma weak sched_yield
92f25da5 98#pragma weak pthread_attr_destroy
99#pragma weak pthread_attr_init
100#pragma weak pthread_attr_setdetachstate
f9f6f55a 101#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
92f25da5 102#pragma weak pthread_getschedparam
103#pragma weak pthread_setschedparam
f9f6f55a 104#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
ecd34a08 105#endif /* _LIBOBJC || _LIBOBJC_WEAK */
58febf9e 106
58febf9e 107static inline int
205b5771 108__gthread_active_p (void)
58febf9e 109{
c3e6a7ce 110 static void *const __gthread_active_ptr
111 = __extension__ (void *) &pthread_create;
58febf9e 112 return __gthread_active_ptr != 0;
113}
114
115#else /* not SUPPORTS_WEAK */
116
117static inline int
205b5771 118__gthread_active_p (void)
58febf9e 119{
120 return 1;
121}
122
123#endif /* SUPPORTS_WEAK */
124
6319d58e 125#ifdef _LIBOBJC
126
53f5af15 127/* This is the config.h file in libobjc/ */
128#include <config.h>
129
130#ifdef HAVE_SCHED_H
131# include <sched.h>
132#endif
133
6319d58e 134/* Key structure for maintaining thread specific storage */
135static pthread_key_t _objc_thread_storage;
eb7dae3a 136static pthread_attr_t _objc_thread_attribs;
6319d58e 137
138/* Thread local storage for a single thread */
139static void *thread_local_storage = NULL;
140
141/* Backend initialization functions */
142
5a54c45e 143/* Initialize the threads subsystem. */
6319d58e 144static inline int
b6546344 145__gthread_objc_init_thread_system (void)
6319d58e 146{
147 if (__gthread_active_p ())
eb7dae3a 148 {
778ac06a 149 /* Initialize the thread storage key. */
b6546344 150 if (pthread_key_create (&_objc_thread_storage, NULL) == 0)
3cfec666 151 {
152 /* The normal default detach state for threads is
153 * PTHREAD_CREATE_JOINABLE which causes threads to not die
154 * when you think they should. */
b6546344 155 if (pthread_attr_init (&_objc_thread_attribs) == 0
156 && pthread_attr_setdetachstate (&_objc_thread_attribs,
157 PTHREAD_CREATE_DETACHED) == 0)
3cfec666 158 return 0;
159 }
eb7dae3a 160 }
02cb9619 161
162 return -1;
6319d58e 163}
164
5a54c45e 165/* Close the threads subsystem. */
6319d58e 166static inline int
b6546344 167__gthread_objc_close_thread_system (void)
6319d58e 168{
eb7dae3a 169 if (__gthread_active_p ()
b6546344 170 && pthread_key_delete (_objc_thread_storage) == 0
171 && pthread_attr_destroy (&_objc_thread_attribs) == 0)
6319d58e 172 return 0;
eb7dae3a 173
174 return -1;
6319d58e 175}
176
177/* Backend thread functions */
178
5a54c45e 179/* Create a new thread of execution. */
6319d58e 180static inline objc_thread_t
b6546344 181__gthread_objc_thread_detach (void (*func)(void *), void *arg)
6319d58e 182{
183 objc_thread_t thread_id;
184 pthread_t new_thread_handle;
185
186 if (!__gthread_active_p ())
187 return NULL;
3cfec666 188
b6546344 189 if (!(pthread_create (&new_thread_handle, NULL, (void *) func, arg)))
05036d9f 190 thread_id = (objc_thread_t) new_thread_handle;
6319d58e 191 else
192 thread_id = NULL;
3cfec666 193
6319d58e 194 return thread_id;
195}
196
5a54c45e 197/* Set the current thread's priority. */
6319d58e 198static inline int
b6546344 199__gthread_objc_thread_set_priority (int priority)
6319d58e 200{
b6546344 201 if (!__gthread_active_p ())
eb7dae3a 202 return -1;
b6546344 203 else
204 {
a55f666d 205#ifdef _POSIX_PRIORITY_SCHEDULING
f9f6f55a 206#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
b6546344 207 pthread_t thread_id = pthread_self ();
208 int policy;
209 struct sched_param params;
210 int priority_min, priority_max;
3cfec666 211
b6546344 212 if (pthread_getschedparam (thread_id, &policy, &params) == 0)
213 {
214 if ((priority_max = sched_get_priority_max (policy)) == -1)
215 return -1;
216
217 if ((priority_min = sched_get_priority_min (policy)) == -1)
218 return -1;
3cfec666 219
b6546344 220 if (priority > priority_max)
221 priority = priority_max;
222 else if (priority < priority_min)
223 priority = priority_min;
224 params.sched_priority = priority;
225
226 /*
227 * The solaris 7 and several other man pages incorrectly state that
228 * this should be a pointer to policy but pthread.h is universally
229 * at odds with this.
230 */
231 if (pthread_setschedparam (thread_id, policy, &params) == 0)
232 return 0;
233 }
f9f6f55a 234#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
a55f666d 235#endif /* _POSIX_PRIORITY_SCHEDULING */
b6546344 236 return -1;
237 }
6319d58e 238}
239
5a54c45e 240/* Return the current thread's priority. */
6319d58e 241static inline int
b6546344 242__gthread_objc_thread_get_priority (void)
6319d58e 243{
a55f666d 244#ifdef _POSIX_PRIORITY_SCHEDULING
f9f6f55a 245#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
6319d58e 246 if (__gthread_active_p ())
eb7dae3a 247 {
248 int policy;
249 struct sched_param params;
250
b6546344 251 if (pthread_getschedparam (pthread_self (), &policy, &params) == 0)
3cfec666 252 return params.sched_priority;
eb7dae3a 253 else
3cfec666 254 return -1;
eb7dae3a 255 }
6319d58e 256 else
f9f6f55a 257#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
a55f666d 258#endif /* _POSIX_PRIORITY_SCHEDULING */
6319d58e 259 return OBJC_THREAD_INTERACTIVE_PRIORITY;
260}
261
5a54c45e 262/* Yield our process time to another thread. */
6319d58e 263static inline void
b6546344 264__gthread_objc_thread_yield (void)
6319d58e 265{
266 if (__gthread_active_p ())
b6546344 267 sched_yield ();
6319d58e 268}
269
5a54c45e 270/* Terminate the current thread. */
6319d58e 271static inline int
b6546344 272__gthread_objc_thread_exit (void)
6319d58e 273{
274 if (__gthread_active_p ())
275 /* exit the thread */
b6546344 276 pthread_exit (&__objc_thread_exit_status);
6319d58e 277
278 /* Failed if we reached here */
279 return -1;
280}
281
5a54c45e 282/* Returns an integer value which uniquely describes a thread. */
6319d58e 283static inline objc_thread_t
b6546344 284__gthread_objc_thread_id (void)
6319d58e 285{
286 if (__gthread_active_p ())
b6546344 287 return (objc_thread_t) pthread_self ();
6319d58e 288 else
05036d9f 289 return (objc_thread_t) 1;
6319d58e 290}
291
5a54c45e 292/* Sets the thread's local storage pointer. */
6319d58e 293static inline int
b6546344 294__gthread_objc_thread_set_data (void *value)
6319d58e 295{
296 if (__gthread_active_p ())
b6546344 297 return pthread_setspecific (_objc_thread_storage, value);
6319d58e 298 else
299 {
300 thread_local_storage = value;
301 return 0;
302 }
303}
304
5a54c45e 305/* Returns the thread's local storage pointer. */
6319d58e 306static inline void *
b6546344 307__gthread_objc_thread_get_data (void)
6319d58e 308{
309 if (__gthread_active_p ())
b6546344 310 return pthread_getspecific (_objc_thread_storage);
6319d58e 311 else
312 return thread_local_storage;
313}
314
315/* Backend mutex functions */
316
5a54c45e 317/* Allocate a mutex. */
6319d58e 318static inline int
b6546344 319__gthread_objc_mutex_allocate (objc_mutex_t mutex)
6319d58e 320{
321 if (__gthread_active_p ())
322 {
b6546344 323 mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
6319d58e 324
b6546344 325 if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL))
6319d58e 326 {
b6546344 327 objc_free (mutex->backend);
6319d58e 328 mutex->backend = NULL;
329 return -1;
330 }
331 }
332
333 return 0;
334}
335
5a54c45e 336/* Deallocate a mutex. */
6319d58e 337static inline int
b6546344 338__gthread_objc_mutex_deallocate (objc_mutex_t mutex)
6319d58e 339{
340 if (__gthread_active_p ())
341 {
342 int count;
343
344 /*
345 * Posix Threads specifically require that the thread be unlocked
346 * for pthread_mutex_destroy to work.
347 */
348
349 do
350 {
b6546344 351 count = pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
6319d58e 352 if (count < 0)
353 return -1;
354 }
355 while (count);
356
b6546344 357 if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
6319d58e 358 return -1;
359
b6546344 360 objc_free (mutex->backend);
6319d58e 361 mutex->backend = NULL;
362 }
363 return 0;
364}
365
5a54c45e 366/* Grab a lock on a mutex. */
6319d58e 367static inline int
b6546344 368__gthread_objc_mutex_lock (objc_mutex_t mutex)
6319d58e 369{
3cfec666 370 if (__gthread_active_p ()
b6546344 371 && pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0)
273f030c 372 {
373 return -1;
374 }
375
376 return 0;
6319d58e 377}
378
5a54c45e 379/* Try to grab a lock on a mutex. */
6319d58e 380static inline int
b6546344 381__gthread_objc_mutex_trylock (objc_mutex_t mutex)
6319d58e 382{
3cfec666 383 if (__gthread_active_p ()
b6546344 384 && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0)
273f030c 385 {
386 return -1;
387 }
388
389 return 0;
6319d58e 390}
391
392/* Unlock the mutex */
393static inline int
b6546344 394__gthread_objc_mutex_unlock (objc_mutex_t mutex)
6319d58e 395{
3cfec666 396 if (__gthread_active_p ()
b6546344 397 && pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0)
273f030c 398 {
399 return -1;
400 }
401
402 return 0;
6319d58e 403}
404
405/* Backend condition mutex functions */
406
5a54c45e 407/* Allocate a condition. */
6319d58e 408static inline int
b6546344 409__gthread_objc_condition_allocate (objc_condition_t condition)
6319d58e 410{
411 if (__gthread_active_p ())
412 {
b6546344 413 condition->backend = objc_malloc (sizeof (pthread_cond_t));
6319d58e 414
b6546344 415 if (pthread_cond_init ((pthread_cond_t *) condition->backend, NULL))
6319d58e 416 {
b6546344 417 objc_free (condition->backend);
6319d58e 418 condition->backend = NULL;
419 return -1;
420 }
421 }
422
423 return 0;
424}
425
5a54c45e 426/* Deallocate a condition. */
6319d58e 427static inline int
b6546344 428__gthread_objc_condition_deallocate (objc_condition_t condition)
6319d58e 429{
430 if (__gthread_active_p ())
431 {
b6546344 432 if (pthread_cond_destroy ((pthread_cond_t *) condition->backend))
6319d58e 433 return -1;
434
b6546344 435 objc_free (condition->backend);
6319d58e 436 condition->backend = NULL;
437 }
438 return 0;
439}
440
441/* Wait on the condition */
442static inline int
b6546344 443__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
6319d58e 444{
445 if (__gthread_active_p ())
b6546344 446 return pthread_cond_wait ((pthread_cond_t *) condition->backend,
447 (pthread_mutex_t *) mutex->backend);
6319d58e 448 else
449 return 0;
450}
451
5a54c45e 452/* Wake up all threads waiting on this condition. */
6319d58e 453static inline int
b6546344 454__gthread_objc_condition_broadcast (objc_condition_t condition)
6319d58e 455{
456 if (__gthread_active_p ())
b6546344 457 return pthread_cond_broadcast ((pthread_cond_t *) condition->backend);
6319d58e 458 else
459 return 0;
460}
461
5a54c45e 462/* Wake up one thread waiting on this condition. */
6319d58e 463static inline int
b6546344 464__gthread_objc_condition_signal (objc_condition_t condition)
6319d58e 465{
466 if (__gthread_active_p ())
b6546344 467 return pthread_cond_signal ((pthread_cond_t *) condition->backend);
6319d58e 468 else
469 return 0;
470}
471
472#else /* _LIBOBJC */
473
58febf9e 474static inline int
205b5771 475__gthread_once (__gthread_once_t *once, void (*func) (void))
58febf9e 476{
477 if (__gthread_active_p ())
478 return pthread_once (once, func);
479 else
480 return -1;
481}
482
483static inline int
484__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
485{
486 return pthread_key_create (key, dtor);
487}
488
58febf9e 489static inline int
490__gthread_key_delete (__gthread_key_t key)
491{
492 return pthread_key_delete (key);
493}
494
495static inline void *
496__gthread_getspecific (__gthread_key_t key)
497{
498 return pthread_getspecific (key);
499}
500
501static inline int
502__gthread_setspecific (__gthread_key_t key, const void *ptr)
503{
504 return pthread_setspecific (key, ptr);
505}
506
507static inline int
508__gthread_mutex_lock (__gthread_mutex_t *mutex)
509{
510 if (__gthread_active_p ())
511 return pthread_mutex_lock (mutex);
512 else
513 return 0;
514}
515
516static inline int
517__gthread_mutex_trylock (__gthread_mutex_t *mutex)
518{
519 if (__gthread_active_p ())
520 return pthread_mutex_trylock (mutex);
521 else
522 return 0;
523}
524
525static inline int
526__gthread_mutex_unlock (__gthread_mutex_t *mutex)
527{
528 if (__gthread_active_p ())
529 return pthread_mutex_unlock (mutex);
530 else
531 return 0;
532}
533
ff00b6c5 534#if !defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_MUTEX_RECURSIVE)
4813f5af 535static inline int
536__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
537{
538 if (__gthread_active_p ())
539 {
540 pthread_mutexattr_t attr;
541 int r;
542
543 r = pthread_mutexattr_init (&attr);
544 if (!r)
545 r = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
546 if (!r)
547 r = pthread_mutex_init (mutex, &attr);
548 if (!r)
549 r = pthread_mutexattr_destroy (&attr);
550 return r;
551 }
552}
553#endif
554
555static inline int
556__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
557{
558 return __gthread_mutex_lock (mutex);
559}
560
561static inline int
562__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
563{
564 return __gthread_mutex_trylock (mutex);
565}
566
567static inline int
568__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
569{
570 return __gthread_mutex_unlock (mutex);
571}
572
6319d58e 573#endif /* _LIBOBJC */
574
2a281353 575#endif /* ! GCC_GTHR_POSIX_H */