OSDN Git Service

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