OSDN Git Service

* config/xtensa/xtensa.c (xtensa_expand_builtin): Use CALL_EXPR_FN.
[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 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 static inline int
178 __gthread_active_p (void)
179 {
180   return 1;
181 }
182
183 #endif /* SUPPORTS_WEAK */
184
185 #ifdef _LIBOBJC
186
187 /* This is the config.h file in libobjc/ */
188 #include <config.h>
189
190 #ifdef HAVE_SCHED_H
191 # include <sched.h>
192 #endif
193
194 /* Key structure for maintaining thread specific storage */
195 static pthread_key_t _objc_thread_storage;
196 static pthread_attr_t _objc_thread_attribs;
197
198 /* Thread local storage for a single thread */
199 static void *thread_local_storage = NULL;
200
201 /* Backend initialization functions */
202
203 /* Initialize the threads subsystem.  */
204 static inline int
205 __gthread_objc_init_thread_system (void)
206 {
207   if (__gthread_active_p ())
208     {
209       /* Initialize the thread storage key.  */
210       if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
211         {
212           /* The normal default detach state for threads is
213            * PTHREAD_CREATE_JOINABLE which causes threads to not die
214            * when you think they should.  */
215           if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
216               && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
217                                               PTHREAD_CREATE_DETACHED) == 0)
218             return 0;
219         }
220     }
221
222   return -1;
223 }
224
225 /* Close the threads subsystem.  */
226 static inline int
227 __gthread_objc_close_thread_system (void)
228 {
229   if (__gthread_active_p ()
230       && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
231       && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
232     return 0;
233
234   return -1;
235 }
236
237 /* Backend thread functions */
238
239 /* Create a new thread of execution.  */
240 static inline objc_thread_t
241 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
242 {
243   objc_thread_t thread_id;
244   pthread_t new_thread_handle;
245
246   if (!__gthread_active_p ())
247     return NULL;
248
249   if (!(__gthrw_(pthread_create) (&new_thread_handle, NULL, (void *) func, arg)))
250     thread_id = (objc_thread_t) new_thread_handle;
251   else
252     thread_id = NULL;
253
254   return thread_id;
255 }
256
257 /* Set the current thread's priority.  */
258 static inline int
259 __gthread_objc_thread_set_priority (int priority)
260 {
261   if (!__gthread_active_p ())
262     return -1;
263   else
264     {
265 #ifdef _POSIX_PRIORITY_SCHEDULING
266 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
267       pthread_t thread_id = __gthrw_(pthread_self) ();
268       int policy;
269       struct sched_param params;
270       int priority_min, priority_max;
271
272       if (__gthrw_(pthread_getschedparam) (thread_id, &policy, &params) == 0)
273         {
274           if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
275             return -1;
276
277           if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
278             return -1;
279
280           if (priority > priority_max)
281             priority = priority_max;
282           else if (priority < priority_min)
283             priority = priority_min;
284           params.sched_priority = priority;
285
286           /*
287            * The solaris 7 and several other man pages incorrectly state that
288            * this should be a pointer to policy but pthread.h is universally
289            * at odds with this.
290            */
291           if (__gthrw_(pthread_setschedparam) (thread_id, policy, &params) == 0)
292             return 0;
293         }
294 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
295 #endif /* _POSIX_PRIORITY_SCHEDULING */
296       return -1;
297     }
298 }
299
300 /* Return the current thread's priority.  */
301 static inline int
302 __gthread_objc_thread_get_priority (void)
303 {
304 #ifdef _POSIX_PRIORITY_SCHEDULING
305 #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
306   if (__gthread_active_p ())
307     {
308       int policy;
309       struct sched_param params;
310
311       if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, &params) == 0)
312         return params.sched_priority;
313       else
314         return -1;
315     }
316   else
317 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
318 #endif /* _POSIX_PRIORITY_SCHEDULING */
319     return OBJC_THREAD_INTERACTIVE_PRIORITY;
320 }
321
322 /* Yield our process time to another thread.  */
323 static inline void
324 __gthread_objc_thread_yield (void)
325 {
326   if (__gthread_active_p ())
327     __gthrw_(sched_yield) ();
328 }
329
330 /* Terminate the current thread.  */
331 static inline int
332 __gthread_objc_thread_exit (void)
333 {
334   if (__gthread_active_p ())
335     /* exit the thread */
336     __gthrw_(pthread_exit) (&__objc_thread_exit_status);
337
338   /* Failed if we reached here */
339   return -1;
340 }
341
342 /* Returns an integer value which uniquely describes a thread.  */
343 static inline objc_thread_t
344 __gthread_objc_thread_id (void)
345 {
346   if (__gthread_active_p ())
347     return (objc_thread_t) __gthrw_(pthread_self) ();
348   else
349     return (objc_thread_t) 1;
350 }
351
352 /* Sets the thread's local storage pointer.  */
353 static inline int
354 __gthread_objc_thread_set_data (void *value)
355 {
356   if (__gthread_active_p ())
357     return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
358   else
359     {
360       thread_local_storage = value;
361       return 0;
362     }
363 }
364
365 /* Returns the thread's local storage pointer.  */
366 static inline void *
367 __gthread_objc_thread_get_data (void)
368 {
369   if (__gthread_active_p ())
370     return __gthrw_(pthread_getspecific) (_objc_thread_storage);
371   else
372     return thread_local_storage;
373 }
374
375 /* Backend mutex functions */
376
377 /* Allocate a mutex.  */
378 static inline int
379 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
380 {
381   if (__gthread_active_p ())
382     {
383       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
384
385       if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
386         {
387           objc_free (mutex->backend);
388           mutex->backend = NULL;
389           return -1;
390         }
391     }
392
393   return 0;
394 }
395
396 /* Deallocate a mutex.  */
397 static inline int
398 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
399 {
400   if (__gthread_active_p ())
401     {
402       int count;
403
404       /*
405        * Posix Threads specifically require that the thread be unlocked
406        * for __gthrw_(pthread_mutex_destroy) to work.
407        */
408
409       do
410         {
411           count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
412           if (count < 0)
413             return -1;
414         }
415       while (count);
416
417       if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
418         return -1;
419
420       objc_free (mutex->backend);
421       mutex->backend = NULL;
422     }
423   return 0;
424 }
425
426 /* Grab a lock on a mutex.  */
427 static inline int
428 __gthread_objc_mutex_lock (objc_mutex_t mutex)
429 {
430   if (__gthread_active_p ()
431       && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
432     {
433       return -1;
434     }
435
436   return 0;
437 }
438
439 /* Try to grab a lock on a mutex.  */
440 static inline int
441 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
442 {
443   if (__gthread_active_p ()
444       && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
445     {
446       return -1;
447     }
448
449   return 0;
450 }
451
452 /* Unlock the mutex */
453 static inline int
454 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
455 {
456   if (__gthread_active_p ()
457       && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
458     {
459       return -1;
460     }
461
462   return 0;
463 }
464
465 /* Backend condition mutex functions */
466
467 /* Allocate a condition.  */
468 static inline int
469 __gthread_objc_condition_allocate (objc_condition_t condition)
470 {
471   if (__gthread_active_p ())
472     {
473       condition->backend = objc_malloc (sizeof (pthread_cond_t));
474
475       if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
476         {
477           objc_free (condition->backend);
478           condition->backend = NULL;
479           return -1;
480         }
481     }
482
483   return 0;
484 }
485
486 /* Deallocate a condition.  */
487 static inline int
488 __gthread_objc_condition_deallocate (objc_condition_t condition)
489 {
490   if (__gthread_active_p ())
491     {
492       if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
493         return -1;
494
495       objc_free (condition->backend);
496       condition->backend = NULL;
497     }
498   return 0;
499 }
500
501 /* Wait on the condition */
502 static inline int
503 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
504 {
505   if (__gthread_active_p ())
506     return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
507                               (pthread_mutex_t *) mutex->backend);
508   else
509     return 0;
510 }
511
512 /* Wake up all threads waiting on this condition.  */
513 static inline int
514 __gthread_objc_condition_broadcast (objc_condition_t condition)
515 {
516   if (__gthread_active_p ())
517     return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
518   else
519     return 0;
520 }
521
522 /* Wake up one thread waiting on this condition.  */
523 static inline int
524 __gthread_objc_condition_signal (objc_condition_t condition)
525 {
526   if (__gthread_active_p ())
527     return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
528   else
529     return 0;
530 }
531
532 #else /* _LIBOBJC */
533
534 static inline int
535 __gthread_once (__gthread_once_t *once, void (*func) (void))
536 {
537   if (__gthread_active_p ())
538     return __gthrw_(pthread_once) (once, func);
539   else
540     return -1;
541 }
542
543 static inline int
544 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
545 {
546   return __gthrw_(pthread_key_create) (key, dtor);
547 }
548
549 static inline int
550 __gthread_key_delete (__gthread_key_t key)
551 {
552   return __gthrw_(pthread_key_delete) (key);
553 }
554
555 static inline void *
556 __gthread_getspecific (__gthread_key_t key)
557 {
558   return __gthrw_(pthread_getspecific) (key);
559 }
560
561 static inline int
562 __gthread_setspecific (__gthread_key_t key, const void *ptr)
563 {
564   return __gthrw_(pthread_setspecific) (key, ptr);
565 }
566
567 static inline int
568 __gthread_mutex_lock (__gthread_mutex_t *mutex)
569 {
570   if (__gthread_active_p ())
571     return __gthrw_(pthread_mutex_lock) (mutex);
572   else
573     return 0;
574 }
575
576 static inline int
577 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
578 {
579   if (__gthread_active_p ())
580     return __gthrw_(pthread_mutex_trylock) (mutex);
581   else
582     return 0;
583 }
584
585 static inline int
586 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
587 {
588   if (__gthread_active_p ())
589     return __gthrw_(pthread_mutex_unlock) (mutex);
590   else
591     return 0;
592 }
593
594 static inline int
595 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
596 {
597   mutex->depth = 0;
598   mutex->owner = (pthread_t) 0;
599   return __gthrw_(pthread_mutex_init) (&mutex->actual, NULL);
600 }
601
602 static inline int
603 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
604 {
605   if (__gthread_active_p ())
606     {
607       pthread_t me = __gthrw_(pthread_self) ();
608
609       if (mutex->owner != me)
610         {
611           __gthrw_(pthread_mutex_lock) (&mutex->actual);
612           mutex->owner = me;
613         }
614
615       mutex->depth++;
616     }
617   return 0;
618 }
619
620 static inline int
621 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
622 {
623   if (__gthread_active_p ())
624     {
625       pthread_t me = __gthrw_(pthread_self) ();
626
627       if (mutex->owner != me)
628         {
629           if (__gthrw_(pthread_mutex_trylock) (&mutex->actual))
630             return 1;
631           mutex->owner = me;
632         }
633
634       mutex->depth++;
635     }
636   return 0;
637 }
638
639 static inline int
640 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
641 {
642   if (__gthread_active_p ())
643     {
644       if (--mutex->depth == 0)
645         {
646            mutex->owner = (pthread_t) 0;
647            __gthrw_(pthread_mutex_unlock) (&mutex->actual);
648         }
649     }
650   return 0;
651 }
652
653 #endif /* _LIBOBJC */
654
655 #endif /* ! GCC_GTHR_POSIX_H */