]>
Commit | Line | Data |
---|---|---|
58febf9e | 1 | |
2 | /* Compile this one with gcc. */ | |
501b786e | 3 | /* Copyright (C) 1997, 1999, 2000, 2001 Free Software Foundation, Inc. |
58febf9e | 4 | |
f12b58b3 | 5 | This file is part of GCC. |
58febf9e | 6 | |
f12b58b3 | 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. | |
58febf9e | 11 | |
f12b58b3 | 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. | |
58febf9e | 16 | |
17 | You should have received a copy of the GNU General Public License | |
f12b58b3 | 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. */ | |
58febf9e | 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 | ||
2a281353 | 29 | #ifndef GCC_GTHR_DCE_H |
30 | #define GCC_GTHR_DCE_H | |
58febf9e | 31 | |
e8a5b0ad | 32 | /* If _DCE_THREADS is not defined, then we're building the single |
33 | threaded version of the libraries and do not want to reference | |
34 | anything related to pthreads or dce. */ | |
35 | #ifndef _DCE_THREADS | |
36 | #include "gthr-single.h" | |
37 | #else | |
58febf9e | 38 | /* DCE threads interface. |
39 | DCE threads are based on POSIX threads draft 4, and many things | |
5a54c45e | 40 | have changed since then. */ |
58febf9e | 41 | |
42 | #define __GTHREADS 1 | |
43 | ||
44 | #include <pthread.h> | |
45 | ||
501b786e | 46 | #ifdef __cplusplus |
47 | #define UNUSED(x) x | |
48 | #else | |
49 | #define UNUSED(x) x __attribute__((unused)) | |
50 | #endif | |
51 | ||
58febf9e | 52 | typedef pthread_key_t __gthread_key_t; |
53 | typedef pthread_once_t __gthread_once_t; | |
54 | typedef pthread_mutex_t __gthread_mutex_t; | |
55 | ||
56 | #define __GTHREAD_ONCE_INIT pthread_once_init | |
f76548a9 | 57 | |
58 | #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function | |
59 | ||
60 | #define __GTHREAD_MUTEX_INIT_DEFAULT pthread_once_init | |
58febf9e | 61 | |
62 | #if SUPPORTS_WEAK && GTHREAD_USE_WEAK | |
63 | ||
64 | #pragma weak pthread_once | |
65 | #pragma weak pthread_once_init | |
6319d58e | 66 | #pragma weak pthread_keycreate |
58febf9e | 67 | #pragma weak pthread_key_delete |
68 | #pragma weak pthread_getspecific | |
69 | #pragma weak pthread_setspecific | |
70 | #pragma weak pthread_create | |
f76548a9 | 71 | #pragma weak pthread_mutex_init |
58febf9e | 72 | #pragma weak pthread_mutex_lock |
73 | #pragma weak pthread_mutex_trylock | |
74 | #pragma weak pthread_mutex_unlock | |
75 | ||
6319d58e | 76 | #ifdef _LIBOBJC |
7fd957fe | 77 | /* Objective-C. */ |
6319d58e | 78 | #pragma weak pthread_cond_broadcast |
79 | #pragma weak pthread_cond_destroy | |
80 | #pragma weak pthread_cond_init | |
81 | #pragma weak pthread_cond_signal | |
82 | #pragma weak pthread_cond_wait | |
83 | #pragma weak pthread_exit | |
84 | #pragma weak pthread_getunique_np | |
6319d58e | 85 | #pragma weak pthread_mutex_destroy |
86 | #pragma weak pthread_self | |
87 | #pragma weak pthread_yield | |
88 | #endif | |
89 | ||
58febf9e | 90 | static inline int |
205b5771 | 91 | __gthread_active_p (void) |
58febf9e | 92 | { |
cee68eb1 | 93 | static void *const __gthread_active_ptr = (void *) &pthread_create; |
58febf9e | 94 | return __gthread_active_ptr != 0; |
95 | } | |
96 | ||
97 | #else /* not SUPPORTS_WEAK */ | |
98 | ||
99 | static inline int | |
205b5771 | 100 | __gthread_active_p (void) |
58febf9e | 101 | { |
102 | return 1; | |
103 | } | |
104 | ||
105 | #endif /* SUPPORTS_WEAK */ | |
106 | ||
6319d58e | 107 | #ifdef _LIBOBJC |
108 | ||
109 | /* Key structure for maintaining thread specific storage */ | |
110 | static pthread_key_t _objc_thread_storage; | |
111 | ||
112 | /* Thread local storage for a single thread */ | |
113 | static void *thread_local_storage = NULL; | |
114 | ||
115 | /* Backend initialization functions */ | |
116 | ||
5a54c45e | 117 | /* Initialize the threads subsystem. */ |
6319d58e | 118 | static inline int |
141c6b3e | 119 | __gthread_objc_init_thread_system (void) |
6319d58e | 120 | { |
121 | if (__gthread_active_p ()) | |
122 | /* Initialize the thread storage key */ | |
123 | return pthread_keycreate (&_objc_thread_storage, NULL); | |
124 | else | |
125 | return -1; | |
126 | } | |
127 | ||
5a54c45e | 128 | /* Close the threads subsystem. */ |
6319d58e | 129 | static inline int |
141c6b3e | 130 | __gthread_objc_close_thread_system (void) |
6319d58e | 131 | { |
132 | if (__gthread_active_p ()) | |
133 | return 0; | |
134 | else | |
135 | return -1; | |
136 | } | |
137 | ||
138 | /* Backend thread functions */ | |
139 | ||
5a54c45e | 140 | /* Create a new thread of execution. */ |
6319d58e | 141 | static inline objc_thread_t |
141c6b3e | 142 | __gthread_objc_thread_detach (void (*func)(void *), void *arg) |
6319d58e | 143 | { |
144 | objc_thread_t thread_id; | |
145 | pthread_t new_thread_handle; | |
146 | ||
147 | if (!__gthread_active_p ()) | |
148 | return NULL; | |
3cfec666 | 149 | |
141c6b3e | 150 | if (!(pthread_create (&new_thread_handle, pthread_attr_default, |
151 | (void *) func, arg))) | |
6319d58e | 152 | { |
153 | /* ??? May not work! (64bit) */ | |
141c6b3e | 154 | thread_id = *(objc_thread_t *) &new_thread_handle; |
155 | pthread_detach (&new_thread_handle); /* Fully detach thread. */ | |
6319d58e | 156 | } |
157 | else | |
158 | thread_id = NULL; | |
3cfec666 | 159 | |
6319d58e | 160 | return thread_id; |
161 | } | |
162 | ||
5a54c45e | 163 | /* Set the current thread's priority. */ |
6319d58e | 164 | static inline int |
141c6b3e | 165 | __gthread_objc_thread_set_priority (int priority) |
6319d58e | 166 | { |
167 | int sys_priority = 0; | |
168 | ||
169 | if (!__gthread_active_p ()) | |
170 | return -1; | |
171 | ||
172 | switch (priority) | |
173 | { | |
174 | case OBJC_THREAD_INTERACTIVE_PRIORITY: | |
175 | sys_priority = (PRI_FG_MIN_NP + PRI_FG_MAX_NP) / 2; | |
176 | break; | |
177 | default: | |
178 | case OBJC_THREAD_BACKGROUND_PRIORITY: | |
179 | sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2; | |
180 | break; | |
181 | case OBJC_THREAD_LOW_PRIORITY: | |
182 | sys_priority = (PRI_BG_MIN_NP + PRI_BG_MAX_NP) / 2; | |
183 | break; | |
184 | } | |
3cfec666 | 185 | |
5a54c45e | 186 | /* Change the priority. */ |
141c6b3e | 187 | if (pthread_setprio (pthread_self (), sys_priority) >= 0) |
6319d58e | 188 | return 0; |
189 | else | |
190 | /* Failed */ | |
191 | return -1; | |
192 | } | |
193 | ||
5a54c45e | 194 | /* Return the current thread's priority. */ |
6319d58e | 195 | static inline int |
141c6b3e | 196 | __gthread_objc_thread_get_priority (void) |
6319d58e | 197 | { |
198 | int sys_priority; | |
199 | ||
200 | if (__gthread_active_p ()) | |
201 | { | |
141c6b3e | 202 | if ((sys_priority = pthread_getprio (pthread_self ())) >= 0) |
3cfec666 | 203 | { |
6319d58e | 204 | if (sys_priority >= PRI_FG_MIN_NP |
205 | && sys_priority <= PRI_FG_MAX_NP) | |
206 | return OBJC_THREAD_INTERACTIVE_PRIORITY; | |
207 | if (sys_priority >= PRI_BG_MIN_NP | |
208 | && sys_priority <= PRI_BG_MAX_NP) | |
209 | return OBJC_THREAD_BACKGROUND_PRIORITY; | |
210 | return OBJC_THREAD_LOW_PRIORITY; | |
211 | } | |
212 | ||
213 | /* Failed */ | |
214 | return -1; | |
215 | } | |
216 | else | |
217 | return OBJC_THREAD_INTERACTIVE_PRIORITY; | |
218 | } | |
219 | ||
5a54c45e | 220 | /* Yield our process time to another thread. */ |
6319d58e | 221 | static inline void |
141c6b3e | 222 | __gthread_objc_thread_yield (void) |
6319d58e | 223 | { |
224 | if (__gthread_active_p ()) | |
141c6b3e | 225 | pthread_yield (); |
6319d58e | 226 | } |
227 | ||
5a54c45e | 228 | /* Terminate the current thread. */ |
6319d58e | 229 | static inline int |
141c6b3e | 230 | __gthread_objc_thread_exit (void) |
6319d58e | 231 | { |
232 | if (__gthread_active_p ()) | |
233 | /* exit the thread */ | |
141c6b3e | 234 | pthread_exit (&__objc_thread_exit_status); |
6319d58e | 235 | |
236 | /* Failed if we reached here */ | |
237 | return -1; | |
238 | } | |
239 | ||
5a54c45e | 240 | /* Returns an integer value which uniquely describes a thread. */ |
6319d58e | 241 | static inline objc_thread_t |
141c6b3e | 242 | __gthread_objc_thread_id (void) |
6319d58e | 243 | { |
244 | if (__gthread_active_p ()) | |
245 | { | |
141c6b3e | 246 | pthread_t self = pthread_self (); |
6319d58e | 247 | |
248 | return (objc_thread_t) pthread_getunique_np (&self); | |
249 | } | |
250 | else | |
141c6b3e | 251 | return (objc_thread_t) 1; |
6319d58e | 252 | } |
253 | ||
5a54c45e | 254 | /* Sets the thread's local storage pointer. */ |
6319d58e | 255 | static inline int |
141c6b3e | 256 | __gthread_objc_thread_set_data (void *value) |
6319d58e | 257 | { |
258 | if (__gthread_active_p ()) | |
141c6b3e | 259 | return pthread_setspecific (_objc_thread_storage, value); |
6319d58e | 260 | else |
261 | { | |
262 | thread_local_storage = value; | |
263 | return 0; | |
264 | } | |
265 | } | |
266 | ||
5a54c45e | 267 | /* Returns the thread's local storage pointer. */ |
6319d58e | 268 | static inline void * |
141c6b3e | 269 | __gthread_objc_thread_get_data (void) |
6319d58e | 270 | { |
271 | void *value = NULL; | |
272 | ||
273 | if (__gthread_active_p ()) | |
274 | { | |
141c6b3e | 275 | if (!(pthread_getspecific (_objc_thread_storage, &value))) |
6319d58e | 276 | return value; |
277 | ||
278 | return NULL; | |
279 | } | |
280 | else | |
281 | return thread_local_storage; | |
282 | } | |
283 | ||
284 | /* Backend mutex functions */ | |
285 | ||
5a54c45e | 286 | /* Allocate a mutex. */ |
6319d58e | 287 | static inline int |
141c6b3e | 288 | __gthread_objc_mutex_allocate (objc_mutex_t mutex) |
6319d58e | 289 | { |
9cdfb95d | 290 | if (__gthread_active_p ()) |
291 | { | |
141c6b3e | 292 | mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); |
9cdfb95d | 293 | |
141c6b3e | 294 | if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend, |
295 | pthread_mutexattr_default)) | |
3cfec666 | 296 | { |
141c6b3e | 297 | objc_free (mutex->backend); |
3cfec666 | 298 | mutex->backend = NULL; |
299 | return -1; | |
300 | } | |
9cdfb95d | 301 | } |
6319d58e | 302 | |
303 | return 0; | |
304 | } | |
305 | ||
5a54c45e | 306 | /* Deallocate a mutex. */ |
6319d58e | 307 | static inline int |
141c6b3e | 308 | __gthread_objc_mutex_deallocate (objc_mutex_t mutex) |
6319d58e | 309 | { |
fe1bbdcb | 310 | if (__gthread_active_p ()) |
311 | { | |
141c6b3e | 312 | if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend)) |
3cfec666 | 313 | return -1; |
fe1bbdcb | 314 | |
141c6b3e | 315 | objc_free (mutex->backend); |
fe1bbdcb | 316 | mutex->backend = NULL; |
317 | } | |
6319d58e | 318 | |
319 | return 0; | |
320 | } | |
321 | ||
5a54c45e | 322 | /* Grab a lock on a mutex. */ |
6319d58e | 323 | static inline int |
141c6b3e | 324 | __gthread_objc_mutex_lock (objc_mutex_t mutex) |
6319d58e | 325 | { |
326 | if (__gthread_active_p ()) | |
141c6b3e | 327 | return pthread_mutex_lock ((pthread_mutex_t *) mutex->backend); |
6319d58e | 328 | else |
329 | return 0; | |
330 | } | |
331 | ||
5a54c45e | 332 | /* Try to grab a lock on a mutex. */ |
6319d58e | 333 | static inline int |
141c6b3e | 334 | __gthread_objc_mutex_trylock (objc_mutex_t mutex) |
6319d58e | 335 | { |
336 | if (__gthread_active_p () | |
141c6b3e | 337 | && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 1) |
6319d58e | 338 | return -1; |
339 | ||
340 | return 0; | |
341 | } | |
342 | ||
343 | /* Unlock the mutex */ | |
344 | static inline int | |
141c6b3e | 345 | __gthread_objc_mutex_unlock (objc_mutex_t mutex) |
6319d58e | 346 | { |
347 | if (__gthread_active_p ()) | |
141c6b3e | 348 | return pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend); |
6319d58e | 349 | else |
350 | return 0; | |
351 | } | |
352 | ||
353 | /* Backend condition mutex functions */ | |
354 | ||
5a54c45e | 355 | /* Allocate a condition. */ |
6319d58e | 356 | static inline int |
141c6b3e | 357 | __gthread_objc_condition_allocate (objc_condition_t condition) |
6319d58e | 358 | { |
7e4da544 | 359 | if (__gthread_active_p ()) |
5a54c45e | 360 | /* Unimplemented. */ |
6319d58e | 361 | return -1; |
362 | else | |
363 | return 0; | |
364 | } | |
365 | ||
5a54c45e | 366 | /* Deallocate a condition. */ |
6319d58e | 367 | static inline int |
141c6b3e | 368 | __gthread_objc_condition_deallocate (objc_condition_t condition) |
6319d58e | 369 | { |
370 | if (__gthread_active_p ()) | |
5a54c45e | 371 | /* Unimplemented. */ |
6319d58e | 372 | return -1; |
373 | else | |
374 | return 0; | |
375 | } | |
376 | ||
377 | /* Wait on the condition */ | |
378 | static inline int | |
141c6b3e | 379 | __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) |
6319d58e | 380 | { |
381 | if (__gthread_active_p ()) | |
5a54c45e | 382 | /* Unimplemented. */ |
6319d58e | 383 | return -1; |
384 | else | |
385 | return 0; | |
386 | } | |
387 | ||
5a54c45e | 388 | /* Wake up all threads waiting on this condition. */ |
6319d58e | 389 | static inline int |
141c6b3e | 390 | __gthread_objc_condition_broadcast (objc_condition_t condition) |
6319d58e | 391 | { |
392 | if (__gthread_active_p ()) | |
5a54c45e | 393 | /* Unimplemented. */ |
6319d58e | 394 | return -1; |
395 | else | |
396 | return 0; | |
397 | } | |
398 | ||
5a54c45e | 399 | /* Wake up one thread waiting on this condition. */ |
6319d58e | 400 | static inline int |
141c6b3e | 401 | __gthread_objc_condition_signal (objc_condition_t condition) |
6319d58e | 402 | { |
403 | if (__gthread_active_p ()) | |
5a54c45e | 404 | /* Unimplemented. */ |
6319d58e | 405 | return -1; |
406 | else | |
407 | return 0; | |
408 | } | |
409 | ||
410 | #else /* _LIBOBJC */ | |
411 | ||
58febf9e | 412 | static inline int |
205b5771 | 413 | __gthread_once (__gthread_once_t *once, void (*func) (void)) |
58febf9e | 414 | { |
415 | if (__gthread_active_p ()) | |
416 | return pthread_once (once, func); | |
417 | else | |
418 | return -1; | |
419 | } | |
420 | ||
421 | static inline int | |
422 | __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) | |
423 | { | |
424 | return pthread_keycreate (key, dtor); | |
425 | } | |
426 | ||
501b786e | 427 | static inline int |
428 | __gthread_key_delete (UNUSED (__gthread_key_t key)) | |
429 | { | |
430 | /* Operation is not supported. */ | |
431 | return -1; | |
432 | } | |
58febf9e | 433 | |
434 | static inline void * | |
435 | __gthread_getspecific (__gthread_key_t key) | |
436 | { | |
437 | void *ptr; | |
438 | if (pthread_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 pthread_setspecific (key, (void *) ptr); | |
448 | } | |
449 | ||
f76548a9 | 450 | static inline void |
451 | __gthread_mutex_init_function (__gthread_mutex_t *mutex) | |
452 | { | |
453 | if (__gthread_active_p ()) | |
454 | pthread_mutex_init (mutex, pthread_mutexattr_default); | |
455 | } | |
456 | ||
58febf9e | 457 | static inline int |
458 | __gthread_mutex_lock (__gthread_mutex_t *mutex) | |
459 | { | |
460 | if (__gthread_active_p ()) | |
461 | return pthread_mutex_lock (mutex); | |
462 | else | |
463 | return 0; | |
464 | } | |
465 | ||
466 | static inline int | |
467 | __gthread_mutex_trylock (__gthread_mutex_t *mutex) | |
468 | { | |
469 | if (__gthread_active_p ()) | |
470 | return pthread_mutex_trylock (mutex); | |
471 | else | |
472 | return 0; | |
473 | } | |
474 | ||
475 | static inline int | |
476 | __gthread_mutex_unlock (__gthread_mutex_t *mutex) | |
477 | { | |
478 | if (__gthread_active_p ()) | |
479 | return pthread_mutex_unlock (mutex); | |
480 | else | |
481 | return 0; | |
482 | } | |
483 | ||
6319d58e | 484 | #endif /* _LIBOBJC */ |
485 | ||
501b786e | 486 | #undef UNUSED |
487 | ||
e8a5b0ad | 488 | #endif |
2a281353 | 489 | #endif /* ! GCC_GTHR_DCE_H */ |