OSDN Git Service

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