OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / gthr-posix95.h
1 /* Threads compatibility routines for libgcc2 and libobjc.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
20
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 <http://www.gnu.org/licenses/>.  */
25
26 #ifndef GCC_GTHR_POSIX_H
27 #define GCC_GTHR_POSIX_H
28
29 /* POSIX threads specific definitions.
30    Easy, since the interface is just one-to-one mapping.  */
31
32 #define __GTHREADS 1
33
34 /* Some implementations of <pthread.h> require this to be defined.  */
35 #ifndef _REENTRANT
36 #define _REENTRANT 1
37 #endif
38
39 #include <pthread.h>
40 #include <unistd.h>
41
42 typedef pthread_key_t __gthread_key_t;
43 typedef pthread_once_t __gthread_once_t;
44 typedef pthread_mutex_t __gthread_mutex_t;
45 typedef pthread_cond_t __gthread_cond_t;
46
47 /* POSIX like conditional variables are supported.  Please look at comments
48    in gthr.h for details. */
49 #define __GTHREAD_HAS_COND      1
50
51 typedef struct {
52   long depth;
53   pthread_t owner;
54   pthread_mutex_t actual;
55 } __gthread_recursive_mutex_t;
56
57 #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
58 #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
59 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
60 #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
61
62 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
63 # define __gthrw(name) \
64   static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name)));
65 # define __gthrw_(name) __gthrw_ ## name
66 #else
67 # define __gthrw(name)
68 # define __gthrw_(name) name
69 #endif
70
71 __gthrw(pthread_once)
72 __gthrw(pthread_key_create)
73 __gthrw(pthread_key_delete)
74 __gthrw(pthread_getspecific)
75 __gthrw(pthread_setspecific)
76 __gthrw(pthread_create)
77 __gthrw(pthread_cancel)
78 __gthrw(pthread_self)
79
80 __gthrw(pthread_mutex_init)
81 __gthrw(pthread_mutex_destroy)
82 __gthrw(pthread_mutex_lock)
83 __gthrw(pthread_mutex_trylock)
84 __gthrw(pthread_mutex_unlock)
85 __gthrw(pthread_mutexattr_init)
86 __gthrw(pthread_mutexattr_destroy)
87
88 __gthrw(pthread_cond_broadcast)
89 __gthrw(pthread_cond_wait)
90
91 #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
92 /* Objective-C.  */
93 __gthrw(pthread_cond_destroy)
94 __gthrw(pthread_cond_init)
95 __gthrw(pthread_cond_signal)
96 __gthrw(pthread_exit)
97 #ifdef _POSIX_PRIORITY_SCHEDULING
98 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
99 __gthrw(sched_get_priority_max)
100 __gthrw(sched_get_priority_min)
101 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
102 #endif /* _POSIX_PRIORITY_SCHEDULING */
103 __gthrw(sched_yield)
104 __gthrw(pthread_attr_destroy)
105 __gthrw(pthread_attr_init)
106 __gthrw(pthread_attr_setdetachstate)
107 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
108 __gthrw(pthread_getschedparam)
109 __gthrw(pthread_setschedparam)
110 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
111 #endif /* _LIBOBJC || _LIBOBJC_WEAK */
112
113 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
114
115 /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
116    -pthreads is not specified.  The functions are dummies and most return an
117    error value.  However pthread_once returns 0 without invoking the routine
118    it is passed so we cannot pretend that the interface is active if -pthreads
119    is not specified.  On Solaris 2.5.1, the interface is not exposed at all so
120    we need to play the usual game with weak symbols.  On Solaris 10 and up, a
121    working interface is always exposed.  On FreeBSD 6 and later, libc also
122    exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
123    to 9 does.  FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
124    which means the alternate __gthread_active_p below cannot be used there.  */
125
126 #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
127
128 static volatile int __gthread_active = -1;
129
130 static void
131 __gthread_trigger (void)
132 {
133   __gthread_active = 1;
134 }
135
136 static inline int
137 __gthread_active_p (void)
138 {
139   static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
140   static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
141
142   /* Avoid reading __gthread_active twice on the main code path.  */
143   int __gthread_active_latest_value = __gthread_active;
144
145   /* This test is not protected to avoid taking a lock on the main code
146      path so every update of __gthread_active in a threaded program must
147      be atomic with regard to the result of the test.  */
148   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
149     {
150       if (__gthrw_(pthread_once))
151         {
152           /* If this really is a threaded program, then we must ensure that
153              __gthread_active has been set to 1 before exiting this block.  */
154           __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
155           __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
156           __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
157         }
158
159       /* Make sure we'll never enter this block again.  */
160       if (__gthread_active < 0)
161         __gthread_active = 0;
162
163       __gthread_active_latest_value = __gthread_active;
164     }
165
166   return __gthread_active_latest_value != 0;
167 }
168
169 #else /* neither FreeBSD nor Solaris */
170
171 static inline int
172 __gthread_active_p (void)
173 {
174   static void *const __gthread_active_ptr
175     = __extension__ (void *) &__gthrw_(pthread_cancel);
176   return __gthread_active_ptr != 0;
177 }
178
179 #endif /* FreeBSD or Solaris */
180
181 #else /* not SUPPORTS_WEAK */
182
183 /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
184    calls in shared flavors of the HP-UX C library.  Most of the stubs
185    have no functionality.  The details are described in the "libc cumulative
186    patch" for each subversion of HP-UX 11.  There are two special interfaces
187    provided for checking whether an application is linked to a shared pthread
188    library or not.  However, these interfaces aren't available in early
189    pthread libraries.  We also need a test that works for archive
190    libraries.  We can't use pthread_once as some libc versions call the
191    init function.  We also can't use pthread_create or pthread_attr_init
192    as these create a thread and thereby prevent changing the default stack
193    size.  The function pthread_default_stacksize_np is available in both
194    the archive and shared versions of libpthread.   It can be used to
195    determine the default pthread stack size.  There is a stub in some
196    shared libc versions which returns a zero size if pthreads are not
197    active.  We provide an equivalent stub to handle cases where libc
198    doesn't provide one.  */
199
200 #if defined(__hppa__) && defined(__hpux__)
201
202 static volatile int __gthread_active = -1;
203
204 static inline int
205 __gthread_active_p (void)
206 {
207   /* Avoid reading __gthread_active twice on the main code path.  */
208   int __gthread_active_latest_value = __gthread_active;
209   size_t __s;
210
211   if (__builtin_expect (__gthread_active_latest_value < 0, 0))
212     {
213       pthread_default_stacksize_np (0, &__s);
214       __gthread_active = __s ? 1 : 0;
215       __gthread_active_latest_value = __gthread_active;
216     }
217
218   return __gthread_active_latest_value != 0;
219 }
220
221 #else /* not hppa-hpux */
222
223 static inline int
224 __gthread_active_p (void)
225 {
226   return 1;
227 }
228
229 #endif /* hppa-hpux */
230
231 #endif /* SUPPORTS_WEAK */
232
233 #ifdef _LIBOBJC
234
235 /* This is the config.h file in libobjc/ */
236 #include <config.h>
237
238 #ifdef HAVE_SCHED_H
239 # include <sched.h>
240 #endif
241
242 /* Key structure for maintaining thread specific storage */
243 static pthread_key_t _objc_thread_storage;
244 static pthread_attr_t _objc_thread_attribs;
245
246 /* Thread local storage for a single thread */
247 static void *thread_local_storage = NULL;
248
249 /* Backend initialization functions */
250
251 /* Initialize the threads subsystem.  */
252 static inline int
253 __gthread_objc_init_thread_system (void)
254 {
255   if (__gthread_active_p ())
256     {
257       /* Initialize the thread storage key.  */
258       if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
259         {
260           /* The normal default detach state for threads is
261            * PTHREAD_CREATE_JOINABLE which causes threads to not die
262            * when you think they should.  */
263           if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
264               && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
265                                               PTHREAD_CREATE_DETACHED) == 0)
266             return 0;
267         }
268     }
269
270   return -1;
271 }
272
273 /* Close the threads subsystem.  */
274 static inline int
275 __gthread_objc_close_thread_system (void)
276 {
277   if (__gthread_active_p ()
278       && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
279       && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
280     return 0;
281
282   return -1;
283 }
284
285 /* Backend thread functions */
286
287 /* Create a new thread of execution.  */
288 static inline objc_thread_t
289 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
290 {
291   objc_thread_t thread_id;
292   pthread_t new_thread_handle;
293
294   if (!__gthread_active_p ())
295     return NULL;
296
297   if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs,
298                                   (void *) func, arg)))
299     thread_id = (objc_thread_t) new_thread_handle;
300   else
301     thread_id = NULL;
302
303   return thread_id;
304 }
305
306 /* Set the current thread's priority.  */
307 static inline int
308 __gthread_objc_thread_set_priority (int priority)
309 {
310   if (!__gthread_active_p ())
311     return -1;
312   else
313     {
314 #ifdef _POSIX_PRIORITY_SCHEDULING
315 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
316       pthread_t thread_id = __gthrw_(pthread_self) ();
317       int policy;
318       struct sched_param params;
319       int priority_min, priority_max;
320
321       if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
322         {
323           if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
324             return -1;
325
326           if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
327             return -1;
328
329           if (priority > priority_max)
330             priority = priority_max;
331           else if (priority < priority_min)
332             priority = priority_min;
333           params.sched_priority = priority;
334
335           /*
336            * The solaris 7 and several other man pages incorrectly state that
337            * this should be a pointer to policy but pthread.h is universally
338            * at odds with this.
339            */
340           if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
341             return 0;
342         }
343 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
344 #endif /* _POSIX_PRIORITY_SCHEDULING */
345       return -1;
346     }
347 }
348
349 /* Return the current thread's priority.  */
350 static inline int
351 __gthread_objc_thread_get_priority (void)
352 {
353 #ifdef _POSIX_PRIORITY_SCHEDULING
354 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
355   if (__gthread_active_p ())
356     {
357       int policy;
358       struct sched_param params;
359
360       if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
361         return params.sched_priority;
362       else
363         return -1;
364     }
365   else
366 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
367 #endif /* _POSIX_PRIORITY_SCHEDULING */
368     return OBJC_THREAD_INTERACTIVE_PRIORITY;
369 }
370
371 /* Yield our process time to another thread.  */
372 static inline void
373 __gthread_objc_thread_yield (void)
374 {
375   if (__gthread_active_p ())
376     __gthrw_(sched_yield) ();
377 }
378
379 /* Terminate the current thread.  */
380 static inline int
381 __gthread_objc_thread_exit (void)
382 {
383   if (__gthread_active_p ())
384     /* exit the thread */
385     __gthrw_(pthread_exit) (&__objc_thread_exit_status);
386
387   /* Failed if we reached here */
388   return -1;
389 }
390
391 /* Returns an integer value which uniquely describes a thread.  */
392 static inline objc_thread_t
393 __gthread_objc_thread_id (void)
394 {
395   if (__gthread_active_p ())
396     return (objc_thread_t) __gthrw_(pthread_self) ();
397   else
398     return (objc_thread_t) 1;
399 }
400
401 /* Sets the thread's local storage pointer.  */
402 static inline int
403 __gthread_objc_thread_set_data (void *value)
404 {
405   if (__gthread_active_p ())
406     return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
407   else
408     {
409       thread_local_storage = value;
410       return 0;
411     }
412 }
413
414 /* Returns the thread's local storage pointer.  */
415 static inline void *
416 __gthread_objc_thread_get_data (void)
417 {
418   if (__gthread_active_p ())
419     return __gthrw_(pthread_getspecific) (_objc_thread_storage);
420   else
421     return thread_local_storage;
422 }
423
424 /* Backend mutex functions */
425
426 /* Allocate a mutex.  */
427 static inline int
428 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
429 {
430   if (__gthread_active_p ())
431     {
432       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
433
434       if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
435         {
436           objc_free (mutex->backend);
437           mutex->backend = NULL;
438           return -1;
439         }
440     }
441
442   return 0;
443 }
444
445 /* Deallocate a mutex.  */
446 static inline int
447 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
448 {
449   if (__gthread_active_p ())
450     {
451       int count;
452
453       /*
454        * Posix Threads specifically require that the thread be unlocked
455        * for __gthrw_(pthread_mutex_destroy) to work.
456        */
457
458       do
459         {
460           count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
461           if (count < 0)
462             return -1;
463         }
464       while (count);
465
466       if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
467         return -1;
468
469       objc_free (mutex->backend);
470       mutex->backend = NULL;
471     }
472   return 0;
473 }
474
475 /* Grab a lock on a mutex.  */
476 static inline int
477 __gthread_objc_mutex_lock (objc_mutex_t mutex)
478 {
479   if (__gthread_active_p ()
480       && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
481     {
482       return -1;
483     }
484
485   return 0;
486 }
487
488 /* Try to grab a lock on a mutex.  */
489 static inline int
490 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
491 {
492   if (__gthread_active_p ()
493       && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
494     {
495       return -1;
496     }
497
498   return 0;
499 }
500
501 /* Unlock the mutex */
502 static inline int
503 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
504 {
505   if (__gthread_active_p ()
506       && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
507     {
508       return -1;
509     }
510
511   return 0;
512 }
513
514 /* Backend condition mutex functions */
515
516 /* Allocate a condition.  */
517 static inline int
518 __gthread_objc_condition_allocate (objc_condition_t condition)
519 {
520   if (__gthread_active_p ())
521     {
522       condition->backend = objc_malloc (sizeof (pthread_cond_t));
523
524       if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
525         {
526           objc_free (condition->backend);
527           condition->backend = NULL;
528           return -1;
529         }
530     }
531
532   return 0;
533 }
534
535 /* Deallocate a condition.  */
536 static inline int
537 __gthread_objc_condition_deallocate (objc_condition_t condition)
538 {
539   if (__gthread_active_p ())
540     {
541       if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
542         return -1;
543
544       objc_free (condition->backend);
545       condition->backend = NULL;
546     }
547   return 0;
548 }
549
550 /* Wait on the condition */
551 static inline int
552 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
553 {
554   if (__gthread_active_p ())
555     return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
556                               (pthread_mutex_t *) mutex->backend);
557   else
558     return 0;
559 }
560
561 /* Wake up all threads waiting on this condition.  */
562 static inline int
563 __gthread_objc_condition_broadcast (objc_condition_t condition)
564 {
565   if (__gthread_active_p ())
566     return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
567   else
568     return 0;
569 }
570
571 /* Wake up one thread waiting on this condition.  */
572 static inline int
573 __gthread_objc_condition_signal (objc_condition_t condition)
574 {
575   if (__gthread_active_p ())
576     return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
577   else
578     return 0;
579 }
580
581 #else /* _LIBOBJC */
582
583 static inline int
584 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
585 {
586   if (__gthread_active_p ())
587     return __gthrw_(pthread_once) (__once, __func);
588   else
589     return -1;
590 }
591
592 static inline int
593 __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
594 {
595   return __gthrw_(pthread_key_create) (__key, __dtor);
596 }
597
598 static inline int
599 __gthread_key_delete (__gthread_key_t __key)
600 {
601   return __gthrw_(pthread_key_delete) (__key);
602 }
603
604 static inline void *
605 __gthread_getspecific (__gthread_key_t __key)
606 {
607   return __gthrw_(pthread_getspecific) (__key);
608 }
609
610 static inline int
611 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
612 {
613   return __gthrw_(pthread_setspecific) (__key, __ptr);
614 }
615
616 static inline int
617 __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
618 {
619   if (__gthread_active_p ())
620     return __gthrw_(pthread_mutex_destroy) (__mutex);
621   else
622     return 0;
623 }
624
625 static inline int
626 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
627 {
628   if (__gthread_active_p ())
629     return __gthrw_(pthread_mutex_lock) (__mutex);
630   else
631     return 0;
632 }
633
634 static inline int
635 __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
636 {
637   if (__gthread_active_p ())
638     return __gthrw_(pthread_mutex_trylock) (__mutex);
639   else
640     return 0;
641 }
642
643 static inline int
644 __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
645 {
646   if (__gthread_active_p ())
647     return __gthrw_(pthread_mutex_unlock) (__mutex);
648   else
649     return 0;
650 }
651
652 static inline int
653 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
654 {
655   __mutex->depth = 0;
656   __mutex->owner = (pthread_t) 0;
657   return __gthrw_(pthread_mutex_init) (&__mutex->actual, NULL);
658 }
659
660 static inline int
661 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
662 {
663   if (__gthread_active_p ())
664     {
665       pthread_t __me = __gthrw_(pthread_self) ();
666
667       if (__mutex->owner != __me)
668         {
669           __gthrw_(pthread_mutex_lock) (&__mutex->actual);
670           __mutex->owner = __me;
671         }
672
673       __mutex->depth++;
674     }
675   return 0;
676 }
677
678 static inline int
679 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
680 {
681   if (__gthread_active_p ())
682     {
683       pthread_t __me = __gthrw_(pthread_self) ();
684
685       if (__mutex->owner != __me)
686         {
687           if (__gthrw_(pthread_mutex_trylock) (&__mutex->actual))
688             return 1;
689           __mutex->owner = __me;
690         }
691
692       __mutex->depth++;
693     }
694   return 0;
695 }
696
697 static inline int
698 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
699 {
700   if (__gthread_active_p ())
701     {
702       if (--__mutex->depth == 0)
703         {
704            __mutex->owner = (pthread_t) 0;
705            __gthrw_(pthread_mutex_unlock) (&__mutex->actual);
706         }
707     }
708   return 0;
709 }
710
711 static inline int
712 __gthread_cond_broadcast (__gthread_cond_t *__cond)
713 {
714   return __gthrw_(pthread_cond_broadcast) (__cond);
715 }
716
717 static inline int
718 __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
719 {
720   return __gthrw_(pthread_cond_wait) (__cond, __mutex);
721 }
722
723 static inline int
724 __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
725                                __gthread_recursive_mutex_t *__mutex)
726 {
727   return __gthrw_(pthread_cond_wait) (__cond, &__mutex->actual);
728 }
729
730 #endif /* _LIBOBJC */
731
732 #endif /* ! GCC_GTHR_POSIX_H */