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