OSDN Git Service

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