OSDN Git Service

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