OSDN Git Service

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