OSDN Git Service

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