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