Mercurial > hg > CbC > CbC_gcc
comparison gcc/gthr-solaris.h @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 77e2b8dfacca |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
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 = (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 | |
433 || *__key == (__gthread_key_t)-1) | |
434 return -1; | |
435 else | |
436 return 0; | |
437 } | |
438 | |
439 static inline int | |
440 __gthread_key_delete (__gthread_key_t UNUSED (__key)) | |
441 { | |
442 /* Not possible. */ | |
443 return -1; | |
444 } | |
445 | |
446 static inline void * | |
447 __gthread_getspecific (__gthread_key_t __key) | |
448 { | |
449 void *__ptr; | |
450 if (__gthrw_(thr_getspecific) (__key, &__ptr) == 0) | |
451 return __ptr; | |
452 else | |
453 return 0; | |
454 } | |
455 | |
456 static inline int | |
457 __gthread_setspecific (__gthread_key_t __key, const void *__ptr) | |
458 { | |
459 return __gthrw_(thr_setspecific) (__key, (void *) __ptr); | |
460 } | |
461 | |
462 static inline int | |
463 __gthread_mutex_destroy (__gthread_mutex_t * UNUSED(__mutex)) | |
464 { | |
465 if (__gthread_active_p ()) | |
466 return __gthrw_(mutex_destroy) (__mutex); | |
467 else | |
468 return 0; | |
469 } | |
470 | |
471 static inline int | |
472 __gthread_mutex_lock (__gthread_mutex_t *__mutex) | |
473 { | |
474 if (__gthread_active_p ()) | |
475 return __gthrw_(mutex_lock) (__mutex); | |
476 else | |
477 return 0; | |
478 } | |
479 | |
480 static inline int | |
481 __gthread_mutex_trylock (__gthread_mutex_t *__mutex) | |
482 { | |
483 if (__gthread_active_p ()) | |
484 return __gthrw_(mutex_trylock) (__mutex); | |
485 else | |
486 return 0; | |
487 } | |
488 | |
489 static inline int | |
490 __gthread_mutex_unlock (__gthread_mutex_t *__mutex) | |
491 { | |
492 if (__gthread_active_p ()) | |
493 return __gthrw_(mutex_unlock) (__mutex); | |
494 else | |
495 return 0; | |
496 } | |
497 | |
498 static inline int | |
499 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) | |
500 { | |
501 __mutex->depth = 0; | |
502 __mutex->owner = (thread_t) 0; | |
503 return __gthrw_(mutex_init) (&__mutex->actual, USYNC_THREAD, 0); | |
504 } | |
505 | |
506 static inline int | |
507 __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) | |
508 { | |
509 if (__gthread_active_p ()) | |
510 { | |
511 thread_t __me = __gthrw_(thr_self) (); | |
512 | |
513 if (__mutex->owner != __me) | |
514 { | |
515 __gthrw_(mutex_lock) (&__mutex->actual); | |
516 __mutex->owner = __me; | |
517 } | |
518 | |
519 __mutex->depth++; | |
520 } | |
521 return 0; | |
522 } | |
523 | |
524 static inline int | |
525 __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) | |
526 { | |
527 if (__gthread_active_p ()) | |
528 { | |
529 thread_t __me = __gthrw_(thr_self) (); | |
530 | |
531 if (__mutex->owner != __me) | |
532 { | |
533 if (__gthrw_(mutex_trylock) (&__mutex->actual)) | |
534 return 1; | |
535 __mutex->owner = __me; | |
536 } | |
537 | |
538 __mutex->depth++; | |
539 } | |
540 return 0; | |
541 } | |
542 | |
543 static inline int | |
544 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) | |
545 { | |
546 if (__gthread_active_p ()) | |
547 { | |
548 if (--__mutex->depth == 0) | |
549 { | |
550 __mutex->owner = (thread_t) 0; | |
551 __gthrw_(mutex_unlock) (&__mutex->actual); | |
552 } | |
553 } | |
554 return 0; | |
555 } | |
556 | |
557 #endif /* _LIBOBJC */ | |
558 | |
559 #undef UNUSED | |
560 | |
561 #endif /* ! GCC_GTHR_SOLARIS_H */ |