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