OSDN Git Service

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