OSDN Git Service

PR testsuite/21010
[pf3gnuchains/gcc-fork.git] / gcc / gthr-solaris.h
1 /* Threads compatibility routines for libgcc2 and libobjc.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1997, 1999, 2000, 2004 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_SOLARIS_H
30 #define GCC_GTHR_SOLARIS_H
31
32 /* Solaris threads as found in Solaris 2.[456].
33    Actually these are Unix International (UI) threads, but I don't
34    know if anyone else implements these.  */
35
36 #define __GTHREADS 1
37
38 #include <thread.h>
39 #include <errno.h>
40
41 typedef thread_key_t __gthread_key_t;
42 typedef struct {
43   mutex_t mutex;
44   int once;
45 } __gthread_once_t;
46 typedef mutex_t __gthread_mutex_t;
47
48 typedef struct {
49   long depth;
50   thread_t owner;
51   mutex_t actual;
52 } __gthread_recursive_mutex_t;
53
54 #define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
55 #define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
56 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
57
58 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
59
60 #pragma weak thr_keycreate
61 #pragma weak thr_getspecific
62 #pragma weak thr_setspecific
63 #pragma weak thr_create
64
65 #pragma weak mutex_lock
66 #pragma weak mutex_trylock
67 #pragma weak mutex_unlock
68
69 #ifdef _LIBOBJC
70 #pragma weak thr_exit
71 #pragma weak thr_keycreate
72 #pragma weak thr_getprio
73 #pragma weak thr_self
74 #pragma weak thr_setprio
75 #pragma weak thr_yield
76
77 #pragma weak cond_init
78 #pragma weak cond_destroy
79 #pragma weak cond_wait
80 #pragma weak cond_broadcast
81 #pragma weak cond_signal
82
83 #pragma weak mutex_init
84 #pragma weak mutex_destroy
85 #endif
86
87 /* This will not actually work in Solaris 2.5, since libc contains
88    dummy symbols of all thr_* routines.  */
89
90 static inline int
91 __gthread_active_p (void)
92 {
93   static void *const __gthread_active_ptr = (void *) &thr_create;
94   return __gthread_active_ptr != 0;
95 }
96
97 #else /* not SUPPORTS_WEAK */
98
99 static inline int
100 __gthread_active_p (void)
101 {
102   return 1;
103 }
104
105 #endif /* SUPPORTS_WEAK */
106
107 #ifdef _LIBOBJC
108
109 /* Key structure for maintaining thread specific storage */
110 static thread_key_t _objc_thread_storage;
111
112 /* Thread local storage for a single thread */
113 static void *thread_local_storage = NULL;
114
115 /* Backend initialization functions */
116
117 /* Initialize the threads subsystem.  */
118 static inline int
119 __gthread_objc_init_thread_system (void)
120 {
121   /* Initialize the thread storage key.  */
122   if (__gthread_active_p ()
123       && thr_keycreate (&_objc_thread_storage, NULL) == 0)
124     return 0;
125
126   return -1;
127 }
128
129 /* Close the threads subsystem.  */
130 static inline int
131 __gthread_objc_close_thread_system (void)
132 {
133   if (__gthread_active_p ())
134     return 0;
135   else
136     return -1;
137 }
138
139 /* Backend thread functions */
140
141 /* Create a new thread of execution.  */
142 static inline objc_thread_t
143 __gthread_objc_thread_detach (void (*func)(void *), void *arg)
144 {
145   objc_thread_t thread_id;
146   thread_t new_thread_id = 0;
147
148   if (!__gthread_active_p ())
149     return NULL;
150
151   if (thr_create (NULL, 0, (void *) func, arg,
152                   THR_DETACHED | THR_NEW_LWP,
153                   &new_thread_id) == 0)
154     thread_id = *(objc_thread_t *) &new_thread_id;
155   else
156     thread_id = NULL;
157
158   return thread_id;
159 }
160
161 /* Set the current thread's priority.  */
162 static inline int
163 __gthread_objc_thread_set_priority (int priority)
164 {
165   int sys_priority = 0;
166
167   if (!__gthread_active_p ())
168     return -1;
169
170   switch (priority)
171     {
172     case OBJC_THREAD_INTERACTIVE_PRIORITY:
173       sys_priority = 300;
174       break;
175     default:
176     case OBJC_THREAD_BACKGROUND_PRIORITY:
177       sys_priority = 200;
178       break;
179     case OBJC_THREAD_LOW_PRIORITY:
180       sys_priority = 1000;
181       break;
182     }
183
184   /* Change priority */
185   if (thr_setprio (thr_self (), sys_priority) == 0)
186     return 0;
187   else
188     return -1;
189 }
190
191 /* Return the current thread's priority.  */
192 static inline int
193 __gthread_objc_thread_get_priority (void)
194 {
195   int sys_priority;
196
197   if (!__gthread_active_p ())
198     return OBJC_THREAD_INTERACTIVE_PRIORITY;
199
200   if (thr_getprio (thr_self (), &sys_priority) == 0)
201     {
202       if (sys_priority >= 250)
203         return OBJC_THREAD_INTERACTIVE_PRIORITY;
204       else if (sys_priority >= 150)
205         return OBJC_THREAD_BACKGROUND_PRIORITY;
206       return OBJC_THREAD_LOW_PRIORITY;
207     }
208
209   /* Couldn't get priority.  */
210   return -1;
211 }
212
213 /* Yield our process time to another thread.  */
214 static inline void
215 __gthread_objc_thread_yield (void)
216 {
217   if (__gthread_active_p ())
218     thr_yield ();
219 }
220
221 /* Terminate the current thread.  */
222 static inline int
223 __gthread_objc_thread_exit (void)
224 {
225   if (__gthread_active_p ())
226     /* exit the thread */
227     thr_exit (&__objc_thread_exit_status);
228
229   /* Failed if we reached here */
230   return -1;
231 }
232
233 /* Returns an integer value which uniquely describes a thread.  */
234 static inline objc_thread_t
235 __gthread_objc_thread_id (void)
236 {
237   if (__gthread_active_p ())
238     return (objc_thread_t) thr_self ();
239   else
240     return (objc_thread_t) 1;
241 }
242
243 /* Sets the thread's local storage pointer.  */
244 static inline int
245 __gthread_objc_thread_set_data (void *value)
246 {
247   if (__gthread_active_p ())
248     {
249       if (thr_setspecific (_objc_thread_storage, value) == 0)
250         return 0;
251       else
252         return -1;
253     }
254   else
255     {
256       thread_local_storage = value;
257       return 0;
258     }
259 }
260
261 /* Returns the thread's local storage pointer.  */
262 static inline void *
263 __gthread_objc_thread_get_data (void)
264 {
265   void *value = NULL;
266
267   if (__gthread_active_p ())
268     {
269       if (thr_getspecific (_objc_thread_storage, &value) == 0)
270         return value;
271       else
272         return NULL;
273     }
274   else
275     return thread_local_storage;
276 }
277
278 /* Backend mutex functions */
279
280 /* Allocate a mutex.  */
281 static inline int
282 __gthread_objc_mutex_allocate (objc_mutex_t mutex)
283 {
284   if (__gthread_active_p ()
285       && mutex_init ((mutex_t *) (&(mutex->backend)), USYNC_THREAD, 0))
286     return -1;
287
288   return 0;
289 }
290
291 /* Deallocate a mutex.  */
292 static inline int
293 __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
294 {
295   if (__gthread_active_p ())
296     mutex_destroy ((mutex_t *) (&(mutex->backend)));
297
298   return 0;
299 }
300
301 /* Grab a lock on a mutex.  */
302 static inline int
303 __gthread_objc_mutex_lock (objc_mutex_t mutex)
304 {
305   if (__gthread_active_p ()
306       && mutex_lock ((mutex_t *) (&(mutex->backend))) != 0)
307     return -1;
308
309   return 0;
310 }
311
312 /* Try to grab a lock on a mutex.  */
313 static inline int
314 __gthread_objc_mutex_trylock (objc_mutex_t mutex)
315 {
316   if (__gthread_active_p ()
317       && mutex_trylock ((mutex_t *) (&(mutex->backend))) != 0)
318     return -1;
319
320   return 0;
321 }
322
323 /* Unlock the mutex */
324 static inline int
325 __gthread_objc_mutex_unlock (objc_mutex_t mutex)
326 {
327   if (__gthread_active_p ()
328       && mutex_unlock ((mutex_t *) (&(mutex->backend))) != 0)
329     return -1;
330
331   return 0;
332 }
333
334 /* Backend condition mutex functions */
335
336 /* Allocate a condition.  */
337 static inline int
338 __gthread_objc_condition_allocate (objc_condition_t condition)
339 {
340   if (__gthread_active_p ())
341     return cond_init ((cond_t *) (&(condition->backend)), USYNC_THREAD,
342                       NULL);
343   else
344     return 0;
345 }
346
347 /* Deallocate a condition.  */
348 static inline int
349 __gthread_objc_condition_deallocate (objc_condition_t condition)
350 {
351   if (__gthread_active_p ())
352     return cond_destroy ((cond_t *) (&(condition->backend)));
353   else
354     return 0;
355 }
356
357 /* Wait on the condition */
358 static inline int
359 __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
360 {
361   if (__gthread_active_p ())
362     return cond_wait ((cond_t *) (&(condition->backend)),
363                       (mutex_t *) (&(mutex->backend)));
364   else
365     return 0;
366 }
367
368 /* Wake up all threads waiting on this condition.  */
369 static inline int
370 __gthread_objc_condition_broadcast (objc_condition_t condition)
371 {
372   if (__gthread_active_p ())
373     return cond_broadcast ((cond_t *) (&(condition->backend)));
374   else
375     return 0;
376 }
377
378 /* Wake up one thread waiting on this condition.  */
379 static inline int
380 __gthread_objc_condition_signal (objc_condition_t condition)
381 {
382   if (__gthread_active_p ())
383     return cond_signal ((cond_t *) (&(condition->backend)));
384   else
385     return 0;
386 }
387
388 #else /* _LIBOBJC */
389
390 static inline int
391 __gthread_once (__gthread_once_t *once, void (*func) (void))
392 {
393   if (! __gthread_active_p ())
394     return -1;
395
396   if (once == 0 || func == 0)
397     return EINVAL;
398
399   if (once->once == 0)
400     {
401       int status = mutex_lock (&once->mutex);
402       if (status != 0)
403         return status;
404       if (once->once == 0)
405         {
406           (*func) ();
407           once->once++;
408         }
409       mutex_unlock (&once->mutex);
410     }
411   return 0;
412 }
413
414 static inline int
415 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
416 {
417   /* Solaris 2.5 contains thr_* routines no-op in libc, so test if we actually
418      got a reasonable key value, and if not, fail.  */
419   *key = (__gthread_key_t)-1;
420   if (thr_keycreate (key, dtor) != 0 || *key == (__gthread_key_t)-1)
421     return -1;
422   else
423     return 0;
424 }
425
426 static inline int
427 __gthread_key_delete (__gthread_key_t key)
428 {
429   /* Not possible.  */
430   return -1;
431 }
432
433 static inline void *
434 __gthread_getspecific (__gthread_key_t key)
435 {
436   void *ptr;
437   if (thr_getspecific (key, &ptr) == 0)
438     return ptr;
439   else
440     return 0;
441 }
442
443 static inline int
444 __gthread_setspecific (__gthread_key_t key, const void *ptr)
445 {
446   return thr_setspecific (key, (void *) ptr);
447 }
448
449 static inline int
450 __gthread_mutex_lock (__gthread_mutex_t *mutex)
451 {
452   if (__gthread_active_p ())
453     return mutex_lock (mutex);
454   else
455     return 0;
456 }
457
458 static inline int
459 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
460 {
461   if (__gthread_active_p ())
462     return mutex_trylock (mutex);
463   else
464     return 0;
465 }
466
467 static inline int
468 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
469 {
470   if (__gthread_active_p ())
471     return mutex_unlock (mutex);
472   else
473     return 0;
474 }
475
476 static inline int
477 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
478 {
479   mutex->depth = 0;
480   mutex->owner = (thread_t) 0;
481   return mutex_init (&mutex->actual, USYNC_THREAD, 0);
482 }
483
484 static inline int
485 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
486 {
487   if (__gthread_active_p ())
488     {
489       thread_t me = thr_self ();
490
491       if (mutex->owner != me)
492         {
493           mutex_lock (&mutex->actual);
494           mutex->owner = me;
495         }
496
497       mutex->depth++;
498     }
499   return 0;
500 }
501
502 static inline int
503 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
504 {
505   if (__gthread_active_p ())
506     {
507       thread_t me = thr_self ();
508
509       if (mutex->owner != me)
510         {
511           if (mutex_trylock (&mutex->actual))
512             return 1;
513           mutex->owner = me;
514         }
515
516       mutex->depth++;
517     }
518   return 0;
519 }
520
521 static inline int
522 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
523 {
524   if (__gthread_active_p ())
525     {
526       if (--mutex->depth == 0)
527         {
528            mutex->owner = (thread_t) 0;
529            mutex_unlock (&mutex->actual);
530         }
531     }
532   return 0;
533 }
534
535 #endif /* _LIBOBJC */
536
537 #endif /* ! GCC_GTHR_SOLARIS_H */