OSDN Git Service

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