OSDN Git Service

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