OSDN Git Service

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