OSDN Git Service

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