OSDN Git Service

PR c++/13684
[pf3gnuchains/gcc-fork.git] / gcc / gthr-dce.h
1 /* Threads compatibility routines for libgcc2 and libobjc.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22 /* As a special exception, if you link this library with other files,
23    some of which are compiled with GCC, to produce an executable,
24    this library does not by itself cause the resulting executable
25    to be covered by the GNU General Public License.
26    This exception does not however invalidate any other reasons why
27    the executable file might be covered by the GNU General Public License.  */
28
29 #ifndef GCC_GTHR_DCE_H
30 #define GCC_GTHR_DCE_H
31
32 /* If _DCE_THREADS is not defined, then we're building the single
33    threaded version of the libraries and do not want to reference
34    anything related to pthreads or dce.  */
35 #ifndef _DCE_THREADS
36 #include "gthr-single.h"
37 #else
38 /* DCE threads interface.
39    DCE threads are based on POSIX threads draft 4, and many things
40    have changed since then.  */
41
42 #define __GTHREADS 1
43
44 #include <pthread.h>
45
46 #ifdef __cplusplus
47 #define UNUSED(x) x
48 #else
49 #define UNUSED(x) x __attribute__((unused))
50 #endif
51
52 typedef pthread_key_t __gthread_key_t;
53 typedef pthread_once_t __gthread_once_t;
54 typedef pthread_mutex_t __gthread_mutex_t;
55 typedef pthread_mutex_t __gthread_recursive_mutex_t;
56
57 #define __GTHREAD_ONCE_INIT pthread_once_init
58
59 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
60 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
61
62 #define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init
63
64 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
65
66 #pragma weak pthread_once
67 #pragma weak pthread_once_init
68 #pragma weak pthread_keycreate
69 #pragma weak pthread_key_delete
70 #pragma weak pthread_getspecific
71 #pragma weak pthread_setspecific
72 #pragma weak pthread_create
73 #pragma weak pthread_mutex_init
74 #pragma weak pthread_mutex_lock
75 #pragma weak pthread_mutex_trylock
76 #pragma weak pthread_mutex_unlock
77
78 #ifdef _LIBOBJC
79 /* Objective-C.  */
80 #pragma weak pthread_cond_broadcast
81 #pragma weak pthread_cond_destroy
82 #pragma weak pthread_cond_init
83 #pragma weak pthread_cond_signal
84 #pragma weak pthread_cond_wait
85 #pragma weak pthread_exit
86 #pragma weak pthread_getunique_np
87 #pragma weak pthread_mutex_destroy
88 #pragma weak pthread_self
89 #pragma weak pthread_yield
90 #endif
91
92 static inline int
93 __gthread_active_p (void)
94 {
95   static void *const __gthread_active_ptr = (void *) &pthread_create;
96   return __gthread_active_ptr != 0;
97 }
98
99 #else /* not SUPPORTS_WEAK */
100
101 static inline int
102 __gthread_active_p (void)
103 {
104   return 1;
105 }
106
107 #endif /* SUPPORTS_WEAK */
108
109 #ifdef _LIBOBJC
110
111 /* Key structure for maintaining thread specific storage */
112 static pthread_key_t _objc_thread_storage;
113
114 /* Thread local storage for a single thread */
115 static void *thread_local_storage = NULL;
116
117 /* Backend initialization functions */
118
119 /* Initialize the threads subsystem.  */
120 static inline int
121 __gthread_objc_init_thread_system (void)
122 {
123   if (__gthread_active_p ())
124     /* Initialize the thread storage key */
125     return pthread_keycreate (&_objc_thread_storage, NULL);
126   else
127     return -1;
128 }
129
130 /* Close the threads subsystem.  */
131 static inline int
132 __gthread_objc_close_thread_system (void)
133 {
134   if (__gthread_active_p ())
135     return 0;
136   else
137     return -1;
138 }
139
140 /* Backend thread functions */
141
142 /* Create a new thread of execution.  */
143 static inline objc_thread_t
144 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
145 {
146   objc_thread_t thread_id;
147   pthread_t new_thread_handle;
148
149   if (!__gthread_active_p ())
150     return NULL;
151
152   if (!(pthread_create (&new_thread_handle, pthread_attr_default,
153                         (void *) func, arg)))
154     {
155       /* ??? May not work! (64bit) */
156       thread_id = *(objc_thread_t *) &new_thread_handle;
157       pthread_detach (&new_thread_handle); /* Fully detach thread.  */
158     }
159   else
160     thread_id = NULL;
161
162   return thread_id;
163 }
164
165 /* Set the current thread's priority.  */
166 static inline int
167 __gthread_objc_thread_set_priority (int priority)
168 {
169   int sys_priority = 0;
170
171   if (!__gthread_active_p ())
172     return -1;
173
174   switch (priority)
175     {
176     case OBJC_THREAD_INTERACTIVE_PRIORITY:
177       sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2;
178       break;
179     default:
180     case OBJC_THREAD_BACKGROUND_PRIORITY:
181       sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
182       break;
183     case OBJC_THREAD_LOW_PRIORITY:
184       sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2;
185       break;
186     }
187
188   /* Change the priority.  */
189   if (pthread_setprio (pthread_self (), sys_priority) >= 0)
190     return 0;
191   else
192     /* Failed */
193     return -1;
194 }
195
196 /* Return the current thread's priority.  */
197 static inline int
198 __gthread_objc_thread_get_priority (void)
199 {
200   int sys_priority;
201
202   if (__gthread_active_p ())
203     {
204       if ((sys_priority = pthread_getprio (pthread_self ())) >= 0)
205         {
206           if (sys_priority >= PRI_FG_MIN_NP
207               && sys_priority <= PRI_FG_MAX_NP)
208             return OBJC_THREAD_INTERACTIVE_PRIORITY;
209           if (sys_priority >= PRI_BG_MIN_NP
210               && sys_priority <= PRI_BG_MAX_NP)
211             return OBJC_THREAD_BACKGROUND_PRIORITY;
212           return OBJC_THREAD_LOW_PRIORITY;
213         }
214
215       /* Failed */
216       return -1;
217     }
218   else
219     return OBJC_THREAD_INTERACTIVE_PRIORITY;
220 }
221
222 /* Yield our process time to another thread.  */
223 static inline void
224 __gthread_objc_thread_yield (void)
225 {
226   if (__gthread_active_p ())
227     pthread_yield ();
228 }
229
230 /* Terminate the current thread.  */
231 static inline int
232 __gthread_objc_thread_exit (void)
233 {
234   if (__gthread_active_p ())
235     /* exit the thread */
236     pthread_exit (&__objc_thread_exit_status);
237
238   /* Failed if we reached here */
239   return -1;
240 }
241
242 /* Returns an integer value which uniquely describes a thread.  */
243 static inline objc_thread_t
244 __gthread_objc_thread_id (void)
245 {
246   if (__gthread_active_p ())
247     {
248       pthread_t self = pthread_self ();
249
250       return (objc_thread_t) pthread_getunique_np (&self);
251     }
252   else
253     return (objc_thread_t) 1;
254 }
255
256 /* Sets the thread's local storage pointer.  */
257 static inline int
258 __gthread_objc_thread_set_data (void *value)
259 {
260   if (__gthread_active_p ())
261     return pthread_setspecific (_objc_thread_storage, value);
262   else
263     {
264       thread_local_storage = value;
265       return 0;
266     }
267 }
268
269 /* Returns the thread's local storage pointer.  */
270 static inline void *
271 __gthread_objc_thread_get_data (void)
272 {
273   void *value = NULL;
274
275   if (__gthread_active_p ())
276     {
277       if (!(pthread_getspecific (_objc_thread_storage, &value)))
278         return value;
279
280       return NULL;
281     }
282   else
283     return thread_local_storage;
284 }
285
286 /* Backend mutex functions */
287
288 /* Allocate a mutex.  */
289 static inline int
290 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
291 {
292   if (__gthread_active_p ())
293     {
294       mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
295
296       if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend,
297                               pthread_mutexattr_default))
298         {
299           objc_free (mutex->backend);
300           mutex->backend = NULL;
301           return -1;
302         }
303     }
304
305   return 0;
306 }
307
308 /* Deallocate a mutex.  */
309 static inline int
310 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
311 {
312   if (__gthread_active_p ())
313     {
314       if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend))
315         return -1;
316
317       objc_free (mutex->backend);
318       mutex->backend = NULL;
319     }
320
321   return 0;
322 }
323
324 /* Grab a lock on a mutex.  */
325 static inline int
326 __gthread_objc_mutex_lock (objc_mutex_t mutex)
327 {
328   if (__gthread_active_p ())
329     return pthread_mutex_lock ((pthread_mutex_t *) mutex->backend);
330   else
331     return 0;
332 }
333
334 /* Try to grab a lock on a mutex.  */
335 static inline int
336 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
337 {
338   if (__gthread_active_p ()
339       && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 1)
340     return -1;
341
342   return 0;
343 }
344
345 /* Unlock the mutex */
346 static inline int
347 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
348 {
349   if (__gthread_active_p ())
350     return pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend);
351   else
352     return 0;
353 }
354
355 /* Backend condition mutex functions */
356
357 /* Allocate a condition.  */
358 static inline int
359 __gthread_objc_condition_allocate (objc_condition_t condition)
360 {
361   if (__gthread_active_p ())
362     /* Unimplemented.  */
363     return -1;
364   else
365     return 0;
366 }
367
368 /* Deallocate a condition.  */
369 static inline int
370 __gthread_objc_condition_deallocate (objc_condition_t condition)
371 {
372   if (__gthread_active_p ())
373     /* Unimplemented.  */
374     return -1;
375   else
376     return 0;
377 }
378
379 /* Wait on the condition */
380 static inline int
381 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
382 {
383   if (__gthread_active_p ())
384     /* Unimplemented.  */
385     return -1;
386   else
387     return 0;
388 }
389
390 /* Wake up all threads waiting on this condition.  */
391 static inline int
392 __gthread_objc_condition_broadcast (objc_condition_t condition)
393 {
394   if (__gthread_active_p ())
395     /* Unimplemented.  */
396     return -1;
397   else
398     return 0;
399 }
400
401 /* Wake up one thread waiting on this condition.  */
402 static inline int
403 __gthread_objc_condition_signal (objc_condition_t condition)
404 {
405   if (__gthread_active_p ())
406     /* Unimplemented.  */
407     return -1;
408   else
409     return 0;
410 }
411
412 #else /* _LIBOBJC */
413
414 static inline int
415 __gthread_once (__gthread_once_t *once, void (*func) (void))
416 {
417   if (__gthread_active_p ())
418     return pthread_once (once, func);
419   else
420     return -1;
421 }
422
423 static inline int
424 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
425 {
426   return pthread_keycreate (key, dtor);
427 }
428
429 static inline int
430 __gthread_key_delete (UNUSED (__gthread_key_t key))
431 {
432   /* Operation is not supported.  */
433   return -1;
434 }
435
436 static inline void *
437 __gthread_getspecific (__gthread_key_t key)
438 {
439   void *ptr;
440   if (pthread_getspecific (key, &ptr) == 0)
441     return ptr;
442   else
443     return 0;
444 }
445
446 static inline int
447 __gthread_setspecific (__gthread_key_t key, const void *ptr)
448 {
449   return pthread_setspecific (key, (void *) ptr);
450 }
451
452 static inline void
453 __gthread_mutex_init_function (__gthread_mutex_t *mutex)
454 {
455   if (__gthread_active_p ())
456     pthread_mutex_init (mutex, pthread_mutexattr_default);
457 }
458
459 static inline int
460 __gthread_mutex_lock (__gthread_mutex_t *mutex)
461 {
462   if (__gthread_active_p ())
463     return pthread_mutex_lock (mutex);
464   else
465     return 0;
466 }
467
468 static inline int
469 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
470 {
471   if (__gthread_active_p ())
472     return pthread_mutex_trylock (mutex);
473   else
474     return 0;
475 }
476
477 static inline int
478 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
479 {
480   if (__gthread_active_p ())
481     return pthread_mutex_unlock (mutex);
482   else
483     return 0;
484 }
485
486 static inline int
487 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
488 {
489   if (__gthread_active_p ())
490     {
491       pthread_mutexattr_t attr;
492       int r;
493
494       r = pthread_mutexattr_create (&attr);
495       if (!r)
496         r = pthread_mutexattr_setkind_np (&attr, MUTEX_RECURSIVE_NP);
497       if (!r)
498         r = pthread_mutex_init (mutex, attr);
499       if (!r)
500         r = pthread_mutexattr_delete (&attr);
501       return r;
502     }
503 }
504
505 static inline int
506 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
507 {
508   return __gthread_mutex_lock (mutex);
509 }
510
511 static inline int
512 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
513 {
514   return __gthread_mutex_trylock (mutex);
515 }
516
517 static inline int
518 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
519 {
520   return __gthread_mutex_unlock (mutex);
521 }
522
523 #endif /* _LIBOBJC */
524
525 #undef UNUSED
526
527 #endif
528 #endif /* ! GCC_GTHR_DCE_H */