rs6000.md (fseldfsf4): Add TARGET_SINGLE_FLOAT condition.
[gcc.git] / gcc / gthr-dce.h
1 /* Threads compatibility routines for libgcc2 and libobjc. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1997, 1999, 2000, 2001, 2004, 2005
4 Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
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.
12
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.
17
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. */
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
30 #ifndef GCC_GTHR_DCE_H
31 #define GCC_GTHR_DCE_H
32
33 /* If _DCE_THREADS is not defined, then we're building the single
34 threaded version of the libraries and do not want to reference
35 anything related to pthreads or dce. */
36 #ifndef _DCE_THREADS
37 #include "gthr-single.h"
38 #else
39 /* DCE threads interface.
40 DCE threads are based on POSIX threads draft 4, and many things
41 have changed since then. */
42
43 #define __GTHREADS 1
44
45 #include <pthread.h>
46
47 typedef pthread_key_t __gthread_key_t;
48 typedef pthread_once_t __gthread_once_t;
49 typedef pthread_mutex_t __gthread_mutex_t;
50 typedef pthread_mutex_t __gthread_recursive_mutex_t;
51
52 #define __GTHREAD_ONCE_INIT pthread_once_init
53
54 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
55 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
56
57 #define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init
58
59 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
60 # define __gthrw(name) \
61 static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
62 # define __gthrw_(name) __gthrw_ ## name
63 #else
64 # define __gthrw(name)
65 # define __gthrw_(name) name
66 #endif
67
68 __gthrw(pthread_once)
69 __gthrw(pthread_keycreate)
70 __gthrw(pthread_getspecific)
71 __gthrw(pthread_setspecific)
72 __gthrw(pthread_create)
73 __gthrw(pthread_mutex_init)
74 __gthrw(pthread_mutex_destroy)
75 __gthrw(pthread_mutex_lock)
76 __gthrw(pthread_mutex_trylock)
77 __gthrw(pthread_mutex_unlock)
78 __gthrw(pthread_mutexattr_create)
79 __gthrw(pthread_mutexattr_setkind_np)
80 __gthrw(pthread_mutexattr_delete)
81
82 #ifdef _LIBOBJC
83 /* Objective-C. */
84 __gthrw(pthread_cond_broadcast)
85 __gthrw(pthread_cond_destroy)
86 __gthrw(pthread_cond_init)
87 __gthrw(pthread_cond_signal)
88 __gthrw(pthread_cond_wait)
89 __gthrw(pthread_exit)
90
91 #ifdef pthread_getunique_np
92 # define __gthrw_pthread_getunique_np pthread_getunique_np
93 #else
94 __gthrw(pthread_getunique_np)
95 # define __gthrw_pthread_getunique_np __gthrw_(pthread_getunique_np)
96 #endif
97
98 __gthrw(pthread_mutex_destroy)
99 __gthrw(pthread_self)
100 __gthrw(pthread_yield)
101 #endif
102
103 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
104
105 static inline int
106 __gthread_active_p (void)
107 {
108 static void *const __gthread_active_ptr = (void *) &__gthrw_(pthread_create);
109 return __gthread_active_ptr != 0;
110 }
111
112 #else /* not SUPPORTS_WEAK */
113
114 static inline int
115 __gthread_active_p (void)
116 {
117 return 1;
118 }
119
120 #endif /* SUPPORTS_WEAK */
121
122 #ifdef _LIBOBJC
123
124 /* Key structure for maintaining thread specific storage */
125 static pthread_key_t _objc_thread_storage;
126
127 /* Thread local storage for a single thread */
128 static void *thread_local_storage = NULL;
129
130 /* Backend initialization functions */
131
132 /* Initialize the threads subsystem. */
133 static inline int
134 __gthread_objc_init_thread_system (void)
135 {
136 if (__gthread_active_p ())
137 /* Initialize the thread storage key. */
138 return __gthrw_(pthread_keycreate) (&_objc_thread_storage, NULL);
139 else
140 return -1;
141 }
142
143 /* Close the threads subsystem. */
144 static inline int
145 __gthread_objc_close_thread_system (void)
146 {
147 if (__gthread_active_p ())
148 return 0;
149 else
150 return -1;
151 }
152
153 /* Backend thread functions */
154
155 /* Create a new thread of execution. */
156 static inline objc_thread_t
157 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
158 {
159 objc_thread_t thread_id;
160 pthread_t new_thread_handle;
161
162 if (!__gthread_active_p ())
163 return NULL;
164
165 if (!(__gthrw_(pthread_create) (&new_thread_handle, pthread_attr_default,
166 (void *) func, arg)))
167 {
168 /* ??? May not work! (64bit) */
169 thread_id = *(objc_thread_t *) &new_thread_handle;
170 pthread_detach (&new_thread_handle); /* Fully detach thread. */
171 }
172 else
173 thread_id = NULL;
174
175 return thread_id;
176 }
177
178 /* Set the current thread's priority. */
179 static inline int
180 __gthread_objc_thread_set_priority (int priority)
181 {
182 int sys_priority = 0;
183
184 if (!__gthread_active_p ())
185 return -1;
186
187 switch (priority)
188 {
189 case OBJC_THREAD_INTERACTIVE_PRIORITY:
190 sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2;
191 break;
192 default:
193 case OBJC_THREAD_BACKGROUND_PRIORITY:
194 sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
195 break;
196 case OBJC_THREAD_LOW_PRIORITY:
197 sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
198 break;
199 }
200
201 /* Change the priority. */
202 if (pthread_setprio (__gthrw_(pthread_self) (), sys_priority) >= 0)
203 return 0;
204 else
205 /* Failed */
206 return -1;
207 }
208
209 /* Return the current thread's priority. */
210 static inline int
211 __gthread_objc_thread_get_priority (void)
212 {
213 int sys_priority;
214
215 if (__gthread_active_p ())
216 {
217 if ((sys_priority = pthread_getprio (__gthrw_(pthread_self) ())) >= 0)
218 {
219 if (sys_priority >= PRI_FG_MIN_NP
220 && sys_priority <= PRI_FG_MAX_NP)
221 return OBJC_THREAD_INTERACTIVE_PRIORITY;
222 if (sys_priority >= PRI_BG_MIN_NP
223 && sys_priority <= PRI_BG_MAX_NP)
224 return OBJC_THREAD_BACKGROUND_PRIORITY;
225 return OBJC_THREAD_LOW_PRIORITY;
226 }
227
228 /* Failed */
229 return -1;
230 }
231 else
232 return OBJC_THREAD_INTERACTIVE_PRIORITY;
233 }
234
235 /* Yield our process time to another thread. */
236 static inline void
237 __gthread_objc_thread_yield (void)
238 {
239 if (__gthread_active_p ())
240 __gthrw_(pthread_yield) ();
241 }
242
243 /* Terminate the current thread. */
244 static inline int
245 __gthread_objc_thread_exit (void)
246 {
247 if (__gthread_active_p ())
248 /* exit the thread */
249 __gthrw_(pthread_exit) (&__objc_thread_exit_status);
250
251 /* Failed if we reached here */
252 return -1;
253 }
254
255 /* Returns an integer value which uniquely describes a thread. */
256 static inline objc_thread_t
257 __gthread_objc_thread_id (void)
258 {
259 if (__gthread_active_p ())
260 {
261 pthread_t self = __gthrw_(pthread_self) ();
262
263 return (objc_thread_t) __gthrw_pthread_getunique_np (&self);
264 }
265 else
266 return (objc_thread_t) 1;
267 }
268
269 /* Sets the thread's local storage pointer. */
270 static inline int
271 __gthread_objc_thread_set_data (void *value)
272 {
273 if (__gthread_active_p ())
274 return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
275 else
276 {
277 thread_local_storage = value;
278 return 0;
279 }
280 }
281
282 /* Returns the thread's local storage pointer. */
283 static inline void *
284 __gthread_objc_thread_get_data (void)
285 {
286 void *value = NULL;
287
288 if (__gthread_active_p ())
289 {
290 if (!(__gthrw_(pthread_getspecific) (_objc_thread_storage, &value)))
291 return value;
292
293 return NULL;
294 }
295 else
296 return thread_local_storage;
297 }
298
299 /* Backend mutex functions */
300
301 /* Allocate a mutex. */
302 static inline int
303 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
304 {
305 if (__gthread_active_p ())
306 {
307 mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
308
309 if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend,
310 pthread_mutexattr_default))
311 {
312 objc_free (mutex->backend);
313 mutex->backend = NULL;
314 return -1;
315 }
316 }
317
318 return 0;
319 }
320
321 /* Deallocate a mutex. */
322 static inline int
323 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
324 {
325 if (__gthread_active_p ())
326 {
327 if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
328 return -1;
329
330 objc_free (mutex->backend);
331 mutex->backend = NULL;
332 }
333
334 return 0;
335 }
336
337 /* Grab a lock on a mutex. */
338 static inline int
339 __gthread_objc_mutex_lock (objc_mutex_t mutex)
340 {
341 if (__gthread_active_p ())
342 return __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend);
343 else
344 return 0;
345 }
346
347 /* Try to grab a lock on a mutex. */
348 static inline int
349 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
350 {
351 if (__gthread_active_p ()
352 && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 1)
353 return -1;
354
355 return 0;
356 }
357
358 /* Unlock the mutex */
359 static inline int
360 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
361 {
362 if (__gthread_active_p ())
363 return __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
364 else
365 return 0;
366 }
367
368 /* Backend condition mutex functions */
369
370 /* Allocate a condition. */
371 static inline int
372 __gthread_objc_condition_allocate (objc_condition_t condition
373 __attribute__ ((__unused__)))
374 {
375 if (__gthread_active_p ())
376 /* Unimplemented. */
377 return -1;
378 else
379 return 0;
380 }
381
382 /* Deallocate a condition. */
383 static inline int
384 __gthread_objc_condition_deallocate (objc_condition_t condition
385 __attribute__ ((__unused__)))
386 {
387 if (__gthread_active_p ())
388 /* Unimplemented. */
389 return -1;
390 else
391 return 0;
392 }
393
394 /* Wait on the condition */
395 static inline int
396 __gthread_objc_condition_wait (objc_condition_t condition
397 __attribute__ ((__unused__)),
398 objc_mutex_t mutex __attribute__ ((__unused__)))
399 {
400 if (__gthread_active_p ())
401 /* Unimplemented. */
402 return -1;
403 else
404 return 0;
405 }
406
407 /* Wake up all threads waiting on this condition. */
408 static inline int
409 __gthread_objc_condition_broadcast (objc_condition_t condition
410 __attribute__ ((__unused__)))
411 {
412 if (__gthread_active_p ())
413 /* Unimplemented. */
414 return -1;
415 else
416 return 0;
417 }
418
419 /* Wake up one thread waiting on this condition. */
420 static inline int
421 __gthread_objc_condition_signal (objc_condition_t condition
422 __attribute__ ((__unused__)))
423 {
424 if (__gthread_active_p ())
425 /* Unimplemented. */
426 return -1;
427 else
428 return 0;
429 }
430
431 #else /* _LIBOBJC */
432
433 static inline int
434 __gthread_once (__gthread_once_t *once, void (*func) (void))
435 {
436 if (__gthread_active_p ())
437 return __gthrw_(pthread_once) (once, func);
438 else
439 return -1;
440 }
441
442 static inline int
443 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
444 {
445 return __gthrw_(pthread_keycreate) (key, dtor);
446 }
447
448 static inline int
449 __gthread_key_delete (__gthread_key_t key __attribute__ ((__unused__)))
450 {
451 /* Operation is not supported. */
452 return -1;
453 }
454
455 static inline void *
456 __gthread_getspecific (__gthread_key_t key)
457 {
458 void *ptr;
459 if (__gthrw_(pthread_getspecific) (key, &ptr) == 0)
460 return ptr;
461 else
462 return 0;
463 }
464
465 static inline int
466 __gthread_setspecific (__gthread_key_t key, const void *ptr)
467 {
468 return __gthrw_(pthread_setspecific) (key, (void *) ptr);
469 }
470
471 static inline void
472 __gthread_mutex_init_function (__gthread_mutex_t *mutex)
473 {
474 if (__gthread_active_p ())
475 __gthrw_(pthread_mutex_init) (mutex, pthread_mutexattr_default);
476 }
477
478 static inline int
479 __gthread_mutx_destroy (__gthread_mutex_t *mutex)
480 {
481 if (__gthread_active_p ())
482 return __gthrw_(pthread_mutex_destroy) (mutex);
483 else
484 return 0;
485 }
486
487 static inline int
488 __gthread_mutex_lock (__gthread_mutex_t *mutex)
489 {
490 if (__gthread_active_p ())
491 return __gthrw_(pthread_mutex_lock) (mutex);
492 else
493 return 0;
494 }
495
496 static inline int
497 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
498 {
499 if (__gthread_active_p ())
500 return __gthrw_(pthread_mutex_trylock) (mutex);
501 else
502 return 0;
503 }
504
505 static inline int
506 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
507 {
508 if (__gthread_active_p ())
509 return __gthrw_(pthread_mutex_unlock) (mutex);
510 else
511 return 0;
512 }
513
514 static inline int
515 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
516 {
517 if (__gthread_active_p ())
518 {
519 pthread_mutexattr_t attr;
520 int r;
521
522 r = __gthrw_(pthread_mutexattr_create) (&attr);
523 if (!r)
524 r = __gthrw_(pthread_mutexattr_setkind_np) (&attr, MUTEX_RECURSIVE_NP);
525 if (!r)
526 r = __gthrw_(pthread_mutex_init) (mutex, attr);
527 if (!r)
528 r = __gthrw_(pthread_mutexattr_delete) (&attr);
529 return r;
530 }
531 return 0;
532 }
533
534 static inline int
535 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
536 {
537 return __gthread_mutex_lock (mutex);
538 }
539
540 static inline int
541 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
542 {
543 return __gthread_mutex_trylock (mutex);
544 }
545
546 static inline int
547 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
548 {
549 return __gthread_mutex_unlock (mutex);
550 }
551
552 #endif /* _LIBOBJC */
553
554 #endif
555 #endif /* ! GCC_GTHR_DCE_H */