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