OSDN Git Service

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