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