OSDN Git Service

* g++.old-deja/g++.pt/static11.C: Add xtensa-*-elf* to the
[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 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22 /* As a special exception, if you link this library with other files,
23    some of which are compiled with GCC, to produce an executable,
24    this library does not by itself cause the resulting executable
25    to be covered by the GNU General Public License.
26    This exception does not however invalidate any other reasons why
27    the executable file might be covered by the GNU General Public License.  */
28
29 #ifndef GCC_GTHR_SOLARIS_H
30 #define GCC_GTHR_SOLARIS_H
31
32 /* Solaris threads as found in Solaris 2.[456].
33    Actually these are Unix International (UI) threads, but I don't
34    know if anyone else implements these.  */
35
36 #define __GTHREADS 1
37
38 #include <thread.h>
39 #include <errno.h>
40
41 typedef thread_key_t __gthread_key_t;
42 typedef struct
43 {
44   mutex_t mutex;
45   int once;
46 } __gthread_once_t;
47 typedef mutex_t __gthread_mutex_t;
48
49 #define __GTHREAD_ONCE_INIT { DEFAULTMUTEX, 0 }
50 #define __GTHREAD_MUTEX_INIT DEFAULTMUTEX
51
52 #if SUPPORTS_WEAK && GTHREAD_USE_WEAK
53
54 #pragma weak thr_keycreate
55 #pragma weak thr_getspecific
56 #pragma weak thr_setspecific
57 #pragma weak thr_create
58
59 #pragma weak mutex_lock
60 #pragma weak mutex_trylock
61 #pragma weak mutex_unlock
62
63 #ifdef _LIBOBJC
64 #pragma weak thr_exit
65 #pragma weak thr_keycreate
66 #pragma weak thr_getprio
67 #pragma weak thr_self
68 #pragma weak thr_setprio
69 #pragma weak thr_yield
70
71 #pragma weak cond_init
72 #pragma weak cond_destroy
73 #pragma weak cond_wait
74 #pragma weak cond_broadcast
75 #pragma weak cond_signal
76
77 #pragma weak mutex_init
78 #pragma weak mutex_destroy
79 #endif
80
81 /* This will not actually work in Solaris 2.5, since libc contains
82    dummy symbols of all thr_* routines.  */
83
84 static inline int
85 __gthread_active_p (void)
86 {
87   static void *const __gthread_active_ptr = (void *) &thr_create;
88   return __gthread_active_ptr != 0;
89 }
90
91 #else /* not SUPPORTS_WEAK */
92
93 static inline int
94 __gthread_active_p (void)
95 {
96   return 1;
97 }
98
99 #endif /* SUPPORTS_WEAK */
100
101 #ifdef _LIBOBJC
102
103 /* Key structure for maintaining thread specific storage */
104 static thread_key_t _objc_thread_storage;
105
106 /* Thread local storage for a single thread */
107 static void *thread_local_storage = NULL;
108
109 /* Backend initialization functions */
110
111 /* Initialize the threads subsystem.  */
112 static inline int
113 __gthread_objc_init_thread_system(void)
114 {
115   /* Initialize the thread storage key */
116   if (__gthread_active_p ()
117       && thr_keycreate(&_objc_thread_storage, NULL) == 0)
118     return 0;
119
120   return -1;
121 }
122
123 /* Close the threads subsystem.  */
124 static inline int
125 __gthread_objc_close_thread_system(void)
126 {
127   if (__gthread_active_p ())
128     return 0;
129   else
130     return -1;
131 }
132
133 /* Backend thread functions */
134
135 /* Create a new thread of execution.  */
136 static inline objc_thread_t
137 __gthread_objc_thread_detach(void (*func)(void *), void *arg)
138 {
139   objc_thread_t thread_id;
140   thread_t new_thread_id = 0;
141
142   if (!__gthread_active_p ())
143     return NULL;
144
145   if (thr_create(NULL, 0, (void *)func, arg,
146                  THR_DETACHED | THR_NEW_LWP,
147                  &new_thread_id) == 0)
148     thread_id = *(objc_thread_t *)&new_thread_id;
149   else
150     thread_id = NULL;
151
152   return thread_id;
153 }
154
155 /* Set the current thread's priority.  */
156 static inline int
157 __gthread_objc_thread_set_priority(int priority)
158 {
159   int sys_priority = 0;
160
161   if (!__gthread_active_p ())
162     return -1;
163
164   switch (priority)
165     {
166     case OBJC_THREAD_INTERACTIVE_PRIORITY:
167       sys_priority = 300;
168       break;
169     default:
170     case OBJC_THREAD_BACKGROUND_PRIORITY:
171       sys_priority = 200;
172       break;
173     case OBJC_THREAD_LOW_PRIORITY:
174       sys_priority = 1000;
175       break;
176     }
177
178   /* Change priority */
179   if (thr_setprio(thr_self(), sys_priority) == 0)
180     return 0;
181   else
182     return -1;
183 }
184
185 /* Return the current thread's priority.  */
186 static inline int
187 __gthread_objc_thread_get_priority(void)
188 {
189   int sys_priority;
190
191   if (!__gthread_active_p ())
192     return OBJC_THREAD_INTERACTIVE_PRIORITY;
193
194   if (thr_getprio(thr_self(), &sys_priority) == 0)
195     {
196       if (sys_priority >= 250)
197         return OBJC_THREAD_INTERACTIVE_PRIORITY;
198       else if (sys_priority >= 150)
199         return OBJC_THREAD_BACKGROUND_PRIORITY;
200       return OBJC_THREAD_LOW_PRIORITY;
201     }
202
203   /* Couldn't get priority.  */
204   return -1;
205 }
206
207 /* Yield our process time to another thread.  */
208 static inline void
209 __gthread_objc_thread_yield(void)
210 {
211   if (__gthread_active_p ())
212     thr_yield();
213 }
214
215 /* Terminate the current thread.  */
216 static inline int
217 __gthread_objc_thread_exit(void)
218 {
219   if (__gthread_active_p ())
220     /* exit the thread */
221     thr_exit(&__objc_thread_exit_status);
222
223   /* Failed if we reached here */
224   return -1;
225 }
226
227 /* Returns an integer value which uniquely describes a thread.  */
228 static inline objc_thread_t
229 __gthread_objc_thread_id(void)
230 {
231   if (__gthread_active_p ())
232     return (objc_thread_t)thr_self();
233   else
234     return (objc_thread_t)1;
235 }
236
237 /* Sets the thread's local storage pointer.  */
238 static inline int
239 __gthread_objc_thread_set_data(void *value)
240 {
241   if (__gthread_active_p ())
242     {
243       if (thr_setspecific(_objc_thread_storage, value) == 0)
244         return 0;
245       else
246         return -1;
247     }
248   else
249     {
250       thread_local_storage = value;
251       return 0;
252     }
253 }
254
255 /* Returns the thread's local storage pointer.  */
256 static inline void *
257 __gthread_objc_thread_get_data(void)
258 {
259   void *value = NULL;
260
261   if (__gthread_active_p ())
262     {
263       if (thr_getspecific(_objc_thread_storage, &value) == 0)
264         return value;
265       else
266         return NULL;
267     }
268   else
269     return thread_local_storage;
270 }
271
272 /* Backend mutex functions */
273
274 /* Allocate a mutex.  */
275 static inline int
276 __gthread_objc_mutex_allocate(objc_mutex_t mutex)
277 {
278   if (__gthread_active_p ()
279       && mutex_init( (mutex_t *)(&(mutex->backend)), USYNC_THREAD, 0))
280     return -1;
281
282   return 0;
283 }
284
285 /* Deallocate a mutex.  */
286 static inline int
287 __gthread_objc_mutex_deallocate(objc_mutex_t mutex)
288 {
289   if (__gthread_active_p ())
290     mutex_destroy((mutex_t *)(&(mutex->backend)));
291
292   return 0;
293 }
294
295 /* Grab a lock on a mutex.  */
296 static inline int
297 __gthread_objc_mutex_lock(objc_mutex_t mutex)
298 {
299   if (__gthread_active_p ()
300       && mutex_lock((mutex_t *)(&(mutex->backend))) != 0)
301     return -1;
302
303   return 0;
304 }
305
306 /* Try to grab a lock on a mutex.  */
307 static inline int
308 __gthread_objc_mutex_trylock(objc_mutex_t mutex)
309 {
310   if (__gthread_active_p ()
311       && mutex_trylock((mutex_t *)(&(mutex->backend))) != 0)
312     return -1;
313
314   return 0;
315 }
316
317 /* Unlock the mutex */
318 static inline int
319 __gthread_objc_mutex_unlock(objc_mutex_t mutex)
320 {
321   if (__gthread_active_p ()
322       && mutex_unlock((mutex_t *)(&(mutex->backend))) != 0)
323     return -1;
324
325   return 0;
326 }
327
328 /* Backend condition mutex functions */
329
330 /* Allocate a condition.  */
331 static inline int
332 __gthread_objc_condition_allocate(objc_condition_t condition)
333 {
334   if (__gthread_active_p ())
335     return cond_init((cond_t *)(&(condition->backend)), USYNC_THREAD,
336                      NULL);
337   else
338     return 0;
339 }
340
341 /* Deallocate a condition.  */
342 static inline int
343 __gthread_objc_condition_deallocate(objc_condition_t condition)
344 {
345   if (__gthread_active_p ())
346     return cond_destroy((cond_t *)(&(condition->backend)));
347   else
348     return 0;
349 }
350
351 /* Wait on the condition */
352 static inline int
353 __gthread_objc_condition_wait(objc_condition_t condition, objc_mutex_t mutex)
354 {
355   if (__gthread_active_p ())
356     return cond_wait((cond_t *)(&(condition->backend)),
357                      (mutex_t *)(&(mutex->backend)));
358   else
359     return 0;
360 }
361
362 /* Wake up all threads waiting on this condition.  */
363 static inline int
364 __gthread_objc_condition_broadcast(objc_condition_t condition)
365 {
366   if (__gthread_active_p ())
367     return cond_broadcast((cond_t *)(&(condition->backend)));
368   else
369     return 0;
370 }
371
372 /* Wake up one thread waiting on this condition.  */
373 static inline int
374 __gthread_objc_condition_signal(objc_condition_t condition)
375 {
376   if (__gthread_active_p ())
377     return cond_signal((cond_t *)(&(condition->backend)));
378   else
379     return 0;
380 }
381
382 #else /* _LIBOBJC */
383
384 static inline int
385 __gthread_once (__gthread_once_t *once, void (*func) (void))
386 {
387   if (! __gthread_active_p ())
388     return -1;
389
390   if (once == 0 || func == 0)
391     return EINVAL;
392
393   if (once->once == 0)
394     {
395       int status = mutex_lock (&once->mutex);
396       if (status != 0)
397         return status;
398       if (once->once == 0)
399         {
400           (*func) ();
401           once->once ++;
402         }
403       mutex_unlock (&once->mutex);
404     }
405   return 0;
406 }
407
408 static inline int
409 __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
410 {
411   /* Solaris 2.5 contains thr_* routines no-op in libc, so test if we actually
412      got a reasonable key value, and if not, fail.  */
413   *key = -1;
414   if (thr_keycreate (key, dtor) != 0 || *key == -1)
415     return -1;
416   else
417     return 0;
418 }
419
420 static inline int
421 __gthread_key_dtor (__gthread_key_t key, void *ptr)
422 {
423   /* Nothing needed.  */
424   return 0;
425 }
426
427 static inline int
428 __gthread_key_delete (__gthread_key_t key)
429 {
430   /* Not possible.  */
431   return -1;
432 }
433
434 static inline void *
435 __gthread_getspecific (__gthread_key_t key)
436 {
437   void *ptr;
438   if (thr_getspecific (key, &ptr) == 0)
439     return ptr;
440   else
441     return 0;
442 }
443
444 static inline int
445 __gthread_setspecific (__gthread_key_t key, const void *ptr)
446 {
447   return thr_setspecific (key, (void *) ptr);
448 }
449
450 static inline int
451 __gthread_mutex_lock (__gthread_mutex_t *mutex)
452 {
453   if (__gthread_active_p ())
454     return mutex_lock (mutex);
455   else
456     return 0;
457 }
458
459 static inline int
460 __gthread_mutex_trylock (__gthread_mutex_t *mutex)
461 {
462   if (__gthread_active_p ())
463     return mutex_trylock (mutex);
464   else
465     return 0;
466 }
467
468 static inline int
469 __gthread_mutex_unlock (__gthread_mutex_t *mutex)
470 {
471   if (__gthread_active_p ())
472     return mutex_unlock (mutex);
473   else
474     return 0;
475 }
476
477 #endif /* _LIBOBJC */
478
479 #endif /* ! GCC_GTHR_SOLARIS_H */