OSDN Git Service

gcc/fortran:
[pf3gnuchains/gcc-fork.git] / gcc / gthr-posix.h
1 /* Threads compatibility routines for libgcc2 and libobjc.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
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_POSIX_H
31 #define GCC_GTHR_POSIX_H
32
33 /* POSIX threads specific definitions.
34    Easy, since the interface is just one-to-one mapping.  */
35
36 #define __GTHREADS 1
37
38 /* Some implementations of <pthread.h> require this to be defined.  */
39 #if !defined(_REENTRANT) && defined(__osf__)
40 #define _REENTRANT 1
41 #endif
42
43 #include <pthread.h>
44 #include <unistd.h>
45
46 typedef pthread_key_t __gthread_key_t;
47 typedef pthread_once_t __gthread_once_t;
48 typedef pthread_mutex_t __gthread_mutex_t;
49 typedef pthread_mutex_t __gthread_recursive_mutex_t;
50
51 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
52 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
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
60
61 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
62 # ifndef __gthrw_pragma
63 #  define __gthrw_pragma(pragma)
64 # endif
65 # define __gthrw2(name,name2,type) \
66   static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
67   __gthrw_pragma(weak type)
68 # define __gthrw_(name) __gthrw_ ## name
69 #else
70 # define __gthrw2(name,name2,type)
71 # define __gthrw_(name) name
72 #endif
73
74 /* Typically, __gthrw_foo is a weak reference to symbol foo.  */
75 #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
76
77 /* On Tru64, /usr/include/pthread.h uses #pragma extern_prefix "__" to
78    map a subset of the POSIX pthread API to mangled versions of their
79    names.  */
80 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
81 #define __gthrw3(name) __gthrw2(__gthrw_ ## name, __ ## name, name)
82 __gthrw3(pthread_once)
83 __gthrw3(pthread_getspecific)
84 __gthrw3(pthread_setspecific)
85 __gthrw3(pthread_create)
86 __gthrw3(pthread_cancel)
87 __gthrw3(pthread_mutex_lock)
88 __gthrw3(pthread_mutex_trylock)
89 __gthrw3(pthread_mutex_unlock)
90 __gthrw3(pthread_mutex_init)
91 #else
92 __gthrw(pthread_once)
93 __gthrw(pthread_getspecific)
94 __gthrw(pthread_setspecific)
95 __gthrw(pthread_create)
96 __gthrw(pthread_cancel)
97 __gthrw(pthread_mutex_lock)
98 __gthrw(pthread_mutex_trylock)
99 __gthrw(pthread_mutex_unlock)
100 __gthrw(pthread_mutex_init)
101 #endif
102
103 __gthrw(pthread_key_create)
104 __gthrw(pthread_key_delete)
105 __gthrw(pthread_mutexattr_init)
106 __gthrw(pthread_mutexattr_settype)
107 __gthrw(pthread_mutexattr_destroy)
108
109
110 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
111 /* Objective-C.  */
112 #if defined(__osf__) && defined(_PTHREAD_USE_MANGLED_NAMES_)
113 __gthrw3(pthread_cond_broadcast)
114 __gthrw3(pthread_cond_destroy)
115 __gthrw3(pthread_cond_init)
116 __gthrw3(pthread_cond_signal)
117 __gthrw3(pthread_cond_wait)
118 __gthrw3(pthread_exit)
119 __gthrw3(pthread_mutex_destroy)
120 __gthrw3(pthread_self)
121 #else
122 __gthrw(pthread_cond_broadcast)
123 __gthrw(pthread_cond_destroy)
124 __gthrw(pthread_cond_init)
125 __gthrw(pthread_cond_signal)
126 __gthrw(pthread_cond_wait)
127 __gthrw(pthread_exit)
128 __gthrw(pthread_mutex_destroy)
129 __gthrw(pthread_self)
130 #endif /* __osf__ && _PTHREAD_USE_MANGLED_NAMES_ */
131 #ifdef _POSIX_PRIORITY_SCHEDULING
132 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
133 __gthrw(sched_get_priority_max)
134 __gthrw(sched_get_priority_min)
135 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
136 #endif /* _POSIX_PRIORITY_SCHEDULING */
137 __gthrw(sched_yield)
138 __gthrw(pthread_attr_destroy)
139 __gthrw(pthread_attr_init)
140 __gthrw(pthread_attr_setdetachstate)
141 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
142 __gthrw(pthread_getschedparam)
143 __gthrw(pthread_setschedparam)
144 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
145 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
146
147 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
148
149 /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
150    -pthreads is not specified.  The functions are dummies and most return an
151    error value.  However pthread_once returns 0 without invoking the routine
152    it is passed so we cannot pretend that the interface is active if -pthreads
153    is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
154    we need to play the usual game with weak symbols.  On Solaris 10 and up, a
155    working interface is always exposed.  */
156
157 #if defined(__sun) && defined(__svr4__)
158
159 static volatile int __gthread_active = -1;
160
161 static void
162 __gthread_trigger (void)
163 {
164   __gthread_active = 1;
165 }
166
167 static inline int
168 __gthread_active_p (void)
169 {
170   static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
171   static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
172
173   /* Avoid reading __gthread_active twice on the main code path.  */
174   int __gthread_active_latest_value = __gthread_active;
175
176   /* This test is not protected to avoid taking a lock on the main code
177      path so every update of __gthread_active in a threaded program must
178      be atomic with regard to the result of the test.  */
179   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
180     {
181       if (__gthrw_(pthread_once))
182         {
183           /* If this really is a threaded program, then we must ensure that
184              __gthread_active has been set to 1 before exiting this block.  */
185           __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
186           __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
187           __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
188         }
189
190       /* Make sure we'll never enter this block again.  */
191       if (__gthread_active < 0)
192         __gthread_active = 0;
193
194       __gthread_active_latest_value = __gthread_active;
195     }
196
197   return __gthread_active_latest_value != 0;
198 }
199
200 #else /* not Solaris */
201
202 static inline int
203 __gthread_active_p (void)
204 {
205   static void *const __gthread_active_ptr 
206     = __extension__ (void *) &__gthrw_(pthread_cancel);
207   return __gthread_active_ptr != 0;
208 }
209
210 #endif /* Solaris */
211
212 #else /* not SUPPORTS_WEAK */
213
214 static inline int
215 __gthread_active_p (void)
216 {
217   return 1;
218 }
219
220 #endif /* SUPPORTS_WEAK */
221
222 #ifdef _LIBOBJC
223
224 /* This is the config.h file in libobjc/ */
225 #include <config.h>
226
227 #ifdef HAVE_SCHED_H
228 # include <sched.h>
229 #endif
230
231 /* Key structure for maintaining thread specific storage */
232 static pthread_key_t _objc_thread_storage;
233 static pthread_attr_t _objc_thread_attribs;
234
235 /* Thread local storage for a single thread */
236 static void *thread_local_storage = NULL;
237
238 /* Backend initialization functions */
239
240 /* Initialize the threads subsystem.  */
241 static inline int
242 __gthread_objc_init_thread_system (void)
243 {
244   if (__gthread_active_p ())
245     {
246       /* Initialize the thread storage key.  */
247       if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
248         {
249           /* The normal default detach state for threads is
250            * PTHREAD_CREATE_JOINABLE which causes threads to not die
251            * when you think they should.  */
252           if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
253               && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
254                                               PTHREAD_CREATE_DETACHED) == 0)
255             return 0;
256         }
257     }
258
259   return -1;
260 }
261
262 /* Close the threads subsystem.  */
263 static inline int
264 __gthread_objc_close_thread_system (void)
265 {
266   if (__gthread_active_p ()
267       && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
268       && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
269     return 0;
270
271   return -1;
272 }
273
274 /* Backend thread functions */
275
276 /* Create a new thread of execution.  */
277 static inline objc_thread_t
278 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
279 {
280   objc_thread_t thread_id;
281   pthread_t new_thread_handle;
282
283   if (!__gthread_active_p ())
284     return NULL;
285
286   if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
287     thread_id = (objc_thread_t) new_thread_handle;
288   else
289     thread_id = NULL;
290
291   return thread_id;
292 }
293
294 /* Set the current thread's priority.  */
295 static inline int
296 __gthread_objc_thread_set_priority (int priority)
297 {
298   if (!__gthread_active_p ())
299     return -1;
300   else
301     {
302 #ifdef _POSIX_PRIORITY_SCHEDULING
303 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
304       pthread_t thread_id = __gthrw_(pthread_self) ();
305       int policy;
306       struct sched_param params;
307       int priority_min, priority_max;
308
309       if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
310         {
311           if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
312             return -1;
313
314           if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
315             return -1;
316
317           if (priority > priority_max)
318             priority = priority_max;
319           else if (priority < priority_min)
320             priority = priority_min;
321           params.sched_priority = priority;
322
323           /*
324            * The solaris 7 and several other man pages incorrectly state that
325            * this should be a pointer to policy but pthread.h is universally
326            * at odds with this.
327            */
328           if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
329             return 0;
330         }
331 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
332 #endif /* _POSIX_PRIORITY_SCHEDULING */
333       return -1;
334     }
335 }
336
337 /* Return the current thread's priority.  */
338 static inline int
339 __gthread_objc_thread_get_priority (void)
340 {
341 #ifdef _POSIX_PRIORITY_SCHEDULING
342 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
343   if (__gthread_active_p ())
344     {
345       int policy;
346       struct sched_param params;
347
348       if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
349         return params.sched_priority;
350       else
351         return -1;
352     }
353   else
354 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
355 #endif /* _POSIX_PRIORITY_SCHEDULING */
356     return OBJC_THREAD_INTERACTIVE_PRIORITY;
357 }
358
359 /* Yield our process time to another thread.  */
360 static inline void
361 __gthread_objc_thread_yield (void)
362 {
363   if (__gthread_active_p ())
364     __gthrw_(sched_yield) ();
365 }
366
367 /* Terminate the current thread.  */
368 static inline int
369 __gthread_objc_thread_exit (void)
370 {
371   if (__gthread_active_p ())
372     /* exit the thread */
373     __gthrw_(pthread_exit) (&__objc_thread_exit_status);
374
375   /* Failed if we reached here */
376   return -1;
377 }
378
379 /* Returns an integer value which uniquely describes a thread.  */
380 static inline objc_thread_t
381 __gthread_objc_thread_id (void)
382 {
383   if (__gthread_active_p ())
384     return (objc_thread_t) __gthrw_(pthread_self) ();
385   else
386     return (objc_thread_t) 1;
387 }
388
389 /* Sets the thread's local storage pointer.  */
390 static inline int
391 __gthread_objc_thread_set_data (void *value)
392 {
393   if (__gthread_active_p ())
394     return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
395   else
396     {
397       thread_local_storage = value;
398       return 0;
399     }
400 }
401
402 /* Returns the thread's local storage pointer.  */
403 static inline void *
404 __gthread_objc_thread_get_data (void)
405 {
406   if (__gthread_active_p ())
407     return __gthrw_(pthread_getspecific) (_objc_thread_storage);
408   else
409     return thread_local_storage;
410 }
411
412 /* Backend mutex functions */
413
414 /* Allocate a mutex.  */
415 static inline int
416 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
417 {
418   if (__gthread_active_p ())
419     {
420       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
421
422       if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
423         {
424           objc_free (mutex->backend);
425           mutex->backend = NULL;
426           return -1;
427         }
428     }
429
430   return 0;
431 }
432
433 /* Deallocate a mutex.  */
434 static inline int
435 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
436 {
437   if (__gthread_active_p ())
438     {
439       int count;
440
441       /*
442        * Posix Threads specifically require that the thread be unlocked
443        * for __gthrw_(pthread_mutex_destroy) to work.
444        */
445
446       do
447         {
448           count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
449           if (count < 0)
450             return -1;
451         }
452       while (count);
453
454       if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
455         return -1;
456
457       objc_free (mutex->backend);
458       mutex->backend = NULL;
459     }
460   return 0;
461 }
462
463 /* Grab a lock on a mutex.  */
464 static inline int
465 __gthread_objc_mutex_lock (objc_mutex_t mutex)
466 {
467   if (__gthread_active_p ()
468       && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
469     {
470       return -1;
471     }
472
473   return 0;
474 }
475
476 /* Try to grab a lock on a mutex.  */
477 static inline int
478 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
479 {
480   if (__gthread_active_p ()
481       && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
482     {
483       return -1;
484     }
485
486   return 0;
487 }
488
489 /* Unlock the mutex */
490 static inline int
491 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
492 {
493   if (__gthread_active_p ()
494       && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
495     {
496       return -1;
497     }
498
499   return 0;
500 }
501
502 /* Backend condition mutex functions */
503
504 /* Allocate a condition.  */
505 static inline int
506 __gthread_objc_condition_allocate (objc_condition_t condition)
507 {
508   if (__gthread_active_p ())
509     {
510       condition->backend = objc_malloc (sizeof (pthread_cond_t));
511
512       if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
513         {
514           objc_free (condition->backend);
515           condition->backend = NULL;
516           return -1;
517         }
518     }
519
520   return 0;
521 }
522
523 /* Deallocate a condition.  */
524 static inline int
525 __gthread_objc_condition_deallocate (objc_condition_t condition)
526 {
527   if (__gthread_active_p ())
528     {
529       if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
530         return -1;
531
532       objc_free (condition->backend);
533       condition->backend = NULL;
534     }
535   return 0;
536 }
537
538 /* Wait on the condition */
539 static inline int
540 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
541 {
542   if (__gthread_active_p ())
543     return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
544                               (pthread_mutex_t *) mutex->backend);
545   else
546     return 0;
547 }
548
549 /* Wake up all threads waiting on this condition.  */
550 static inline int
551 __gthread_objc_condition_broadcast (objc_condition_t condition)
552 {
553   if (__gthread_active_p ())
554     return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
555   else
556     return 0;
557 }
558
559 /* Wake up one thread waiting on this condition.  */
560 static inline int
561 __gthread_objc_condition_signal (objc_condition_t condition)
562 {
563   if (__gthread_active_p ())
564     return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
565   else
566     return 0;
567 }
568
569 #else /* _LIBOBJC */
570
571 static inline int
572 __gthread_once (__gthread_once_t *once, void (*func) (void))
573 {
574   if (__gthread_active_p ())
575     return __gthrw_(pthread_once) (once, func);
576   else
577     return -1;
578 }
579
580 static inline int
581 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
582 {
583   return __gthrw_(pthread_key_create) (key, dtor);
584 }
585
586 static inline int
587 __gthread_key_delete (__gthread_key_t key)
588 {
589   return __gthrw_(pthread_key_delete) (key);
590 }
591
592 static inline void *
593 __gthread_getspecific (__gthread_key_t key)
594 {
595   return __gthrw_(pthread_getspecific) (key);
596 }
597
598 static inline int
599 __gthread_setspecific (__gthread_key_t key, const void *ptr)
600 {
601   return __gthrw_(pthread_setspecific) (key, ptr);
602 }
603
604 static inline int
605 __gthread_mutex_lock (__gthread_mutex_t *mutex)
606 {
607   if (__gthread_active_p ())
608     return __gthrw_(pthread_mutex_lock) (mutex);
609   else
610     return 0;
611 }
612
613 static inline int
614 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
615 {
616   if (__gthread_active_p ())
617     return __gthrw_(pthread_mutex_trylock) (mutex);
618   else
619     return 0;
620 }
621
622 static inline int
623 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
624 {
625   if (__gthread_active_p ())
626     return __gthrw_(pthread_mutex_unlock) (mutex);
627   else
628     return 0;
629 }
630
631 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
632 static inline int
633 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
634 {
635   if (__gthread_active_p ())
636     {
637       pthread_mutexattr_t attr;
638       int r;
639
640       r = __gthrw_(pthread_mutexattr_init) (&attr);
641       if (!r)
642         r = __gthrw_(pthread_mutexattr_settype) (&attr, PTHREAD_MUTEX_RECURSIVE);
643       if (!r)
644         r = __gthrw_(pthread_mutex_init) (mutex, &attr);
645       if (!r)
646         r = __gthrw_(pthread_mutexattr_destroy) (&attr);
647       return r;
648     }
649   return 0;
650 }
651 #endif
652
653 static inline int
654 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
655 {
656   return __gthread_mutex_lock (mutex);
657 }
658
659 static inline int
660 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
661 {
662   return __gthread_mutex_trylock (mutex);
663 }
664
665 static inline int
666 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
667 {
668   return __gthread_mutex_unlock (mutex);
669 }
670
671 #endif /* _LIBOBJC */
672
673 #endif /* ! GCC_GTHR_POSIX_H */