OSDN Git Service

2006-01-16 Gabor Loki <loki@gcc.gnu.org>
[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 #else
63 # define __gthrw_asmname(cname) __gthrw_asmnamep (__USER_LABEL_PREFIX__, cname)
64 # define __gthrw_asmnamep(prefix, cname) __gthrw_string (prefix) cname
65 # define __gthrw_string(x) #x
66 # define __gthrw(name) \
67   extern __typeof(name) __gthrw_ ## name __asm (__gthrw_asmname (#name))
68 #endif
69
70 __gthrw(thr_keycreate);
71 __gthrw(thr_getspecific);
72 __gthrw(thr_setspecific);
73 __gthrw(thr_create);
74
75 __gthrw(mutex_lock);
76 __gthrw(mutex_trylock);
77 __gthrw(mutex_unlock);
78
79 #ifdef _LIBOBJC
80 __gthrw(thr_exit);
81 __gthrw(thr_keycreate);
82 __gthrw(thr_getprio);
83 __gthrw(thr_self);
84 __gthrw(thr_setprio);
85 __gthrw(thr_yield);
86
87 __gthrw(cond_init);
88 __gthrw(cond_destroy);
89 __gthrw(cond_wait);
90 __gthrw(cond_broadcast);
91 __gthrw(cond_signal);
92
93 __gthrw(mutex_init);
94 __gthrw(mutex_destroy);
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 || *key == (__gthread_key_t)-1)
433     return -1;
434   else
435     return 0;
436 }
437
438 static inline int
439 __gthread_key_delete (__gthread_key_t key)
440 {
441   /* Not possible.  */
442   return -1;
443 }
444
445 static inline void *
446 __gthread_getspecific (__gthread_key_t key)
447 {
448   void *ptr;
449   if (__gthrw_thr_getspecific (key, &ptr) == 0)
450     return ptr;
451   else
452     return 0;
453 }
454
455 static inline int
456 __gthread_setspecific (__gthread_key_t key, const void *ptr)
457 {
458   return __gthrw_thr_setspecific (key, (void *) ptr);
459 }
460
461 static inline int
462 __gthread_mutex_lock (__gthread_mutex_t *mutex)
463 {
464   if (__gthread_active_p ())
465     return __gthrw_mutex_lock (mutex);
466   else
467     return 0;
468 }
469
470 static inline int
471 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
472 {
473   if (__gthread_active_p ())
474     return __gthrw_mutex_trylock (mutex);
475   else
476     return 0;
477 }
478
479 static inline int
480 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
481 {
482   if (__gthread_active_p ())
483     return __gthrw_mutex_unlock (mutex);
484   else
485     return 0;
486 }
487
488 static inline int
489 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
490 {
491   mutex->depth = 0;
492   mutex->owner = (thread_t) 0;
493   return __gthrw_mutex_init (&mutex->actual, USYNC_THREAD, 0);
494 }
495
496 static inline int
497 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
498 {
499   if (__gthread_active_p ())
500     {
501       thread_t me = __gthrw_thr_self ();
502
503       if (mutex->owner != me)
504         {
505           __gthrw_mutex_lock (&mutex->actual);
506           mutex->owner = me;
507         }
508
509       mutex->depth++;
510     }
511   return 0;
512 }
513
514 static inline int
515 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
516 {
517   if (__gthread_active_p ())
518     {
519       thread_t me = __gthrw_thr_self ();
520
521       if (mutex->owner != me)
522         {
523           if (__gthrw_mutex_trylock (&mutex->actual))
524             return 1;
525           mutex->owner = me;
526         }
527
528       mutex->depth++;
529     }
530   return 0;
531 }
532
533 static inline int
534 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
535 {
536   if (__gthread_active_p ())
537     {
538       if (--mutex->depth == 0)
539         {
540            mutex->owner = (thread_t) 0;
541            __gthrw_mutex_unlock (&mutex->actual);
542         }
543     }
544   return 0;
545 }
546
547 #endif /* _LIBOBJC */
548
549 #endif /* ! GCC_GTHR_SOLARIS_H */