]>
Commit | Line | Data |
---|---|---|
18167442 EB |
1 | /* Threads compatibility routines for libgcc2 and libobjc. */ |
2 | /* Compile this one with gcc. */ | |
d652f226 JJ |
3 | /* Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 |
4 | Free Software Foundation, Inc. | |
18167442 EB |
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 | |
748086b7 | 10 | Software Foundation; either version 3, or (at your option) any later |
18167442 EB |
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 | ||
748086b7 JJ |
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/>. */ | |
18167442 EB |
26 | |
27 | #ifndef GCC_GTHR_POSIX_H | |
28 | #define GCC_GTHR_POSIX_H | |
29 | ||
30 | /* POSIX threads specific definitions. | |
31 | Easy, since the interface is just one-to-one mapping. */ | |
32 | ||
33 | #define __GTHREADS 1 | |
34 | ||
35 | /* Some implementations of <pthread.h> require this to be defined. */ | |
36 | #ifndef _REENTRANT | |
37 | #define _REENTRANT 1 | |
38 | #endif | |
39 | ||
40 | #include <pthread.h> | |
41 | #include <unistd.h> | |
42 | ||
43 | typedef pthread_key_t __gthread_key_t; | |
44 | typedef pthread_once_t __gthread_once_t; | |
45 | typedef pthread_mutex_t __gthread_mutex_t; | |
afd82ef5 DK |
46 | typedef pthread_cond_t __gthread_cond_t; |
47 | ||
48 | /* POSIX like conditional variables are supported. Please look at comments | |
49 | in gthr.h for details. */ | |
50 | #define __GTHREAD_HAS_COND 1 | |
18167442 EB |
51 | |
52 | typedef struct { | |
53 | long depth; | |
54 | pthread_t owner; | |
55 | pthread_mutex_t actual; | |
56 | } __gthread_recursive_mutex_t; | |
57 | ||
58 | #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER | |
59 | #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT | |
60 | #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function | |
afd82ef5 | 61 | #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER |
18167442 EB |
62 | |
63 | #if SUPPORTS_WEAK && GTHREAD_USE_WEAK | |
7ef67393 | 64 | # define __gthrw(name) \ |
72b16773 AO |
65 | static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))); |
66 | # define __gthrw_(name) __gthrw_ ## name | |
7ef67393 | 67 | #else |
72b16773 AO |
68 | # define __gthrw(name) |
69 | # define __gthrw_(name) name | |
7ef67393 | 70 | #endif |
18167442 | 71 | |
72b16773 AO |
72 | __gthrw(pthread_once) |
73 | __gthrw(pthread_key_create) | |
74 | __gthrw(pthread_key_delete) | |
75 | __gthrw(pthread_getspecific) | |
76 | __gthrw(pthread_setspecific) | |
77 | __gthrw(pthread_create) | |
78 | __gthrw(pthread_cancel) | |
79 | __gthrw(pthread_self) | |
18167442 | 80 | |
4dabf736 JB |
81 | __gthrw(pthread_mutex_init) |
82 | __gthrw(pthread_mutex_destroy) | |
72b16773 AO |
83 | __gthrw(pthread_mutex_lock) |
84 | __gthrw(pthread_mutex_trylock) | |
85 | __gthrw(pthread_mutex_unlock) | |
86 | __gthrw(pthread_mutexattr_init) | |
87 | __gthrw(pthread_mutexattr_destroy) | |
18167442 | 88 | |
afd82ef5 DK |
89 | __gthrw(pthread_cond_broadcast) |
90 | __gthrw(pthread_cond_wait) | |
18167442 EB |
91 | |
92 | #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) | |
93 | /* Objective-C. */ | |
72b16773 AO |
94 | __gthrw(pthread_cond_destroy) |
95 | __gthrw(pthread_cond_init) | |
96 | __gthrw(pthread_cond_signal) | |
72b16773 | 97 | __gthrw(pthread_exit) |
18167442 EB |
98 | #ifdef _POSIX_PRIORITY_SCHEDULING |
99 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING | |
72b16773 AO |
100 | __gthrw(sched_get_priority_max) |
101 | __gthrw(sched_get_priority_min) | |
18167442 EB |
102 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
103 | #endif /* _POSIX_PRIORITY_SCHEDULING */ | |
72b16773 AO |
104 | __gthrw(sched_yield) |
105 | __gthrw(pthread_attr_destroy) | |
106 | __gthrw(pthread_attr_init) | |
107 | __gthrw(pthread_attr_setdetachstate) | |
18167442 | 108 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
72b16773 AO |
109 | __gthrw(pthread_getschedparam) |
110 | __gthrw(pthread_setschedparam) | |
18167442 EB |
111 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
112 | #endif /* _LIBOBJC || _LIBOBJC_WEAK */ | |
113 | ||
7ef67393 AO |
114 | #if SUPPORTS_WEAK && GTHREAD_USE_WEAK |
115 | ||
efd6ef80 EB |
116 | /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if |
117 | -pthreads is not specified. The functions are dummies and most return an | |
118 | error value. However pthread_once returns 0 without invoking the routine | |
119 | it is passed so we cannot pretend that the interface is active if -pthreads | |
120 | is not specified. On Solaris 2.5.1, the interface is not exposed at all so | |
121 | we need to play the usual game with weak symbols. On Solaris 10 and up, a | |
799cff46 MS |
122 | working interface is always exposed. On FreeBSD 6 and later, libc also |
123 | exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up | |
124 | to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc, | |
125 | which means the alternate __gthread_active_p below cannot be used there. */ | |
efd6ef80 | 126 | |
799cff46 | 127 | #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__)) |
efd6ef80 EB |
128 | |
129 | static volatile int __gthread_active = -1; | |
130 | ||
131 | static void | |
132 | __gthread_trigger (void) | |
133 | { | |
134 | __gthread_active = 1; | |
135 | } | |
136 | ||
137 | static inline int | |
138 | __gthread_active_p (void) | |
139 | { | |
140 | static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; | |
141 | static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT; | |
142 | ||
143 | /* Avoid reading __gthread_active twice on the main code path. */ | |
144 | int __gthread_active_latest_value = __gthread_active; | |
145 | ||
146 | /* This test is not protected to avoid taking a lock on the main code | |
147 | path so every update of __gthread_active in a threaded program must | |
148 | be atomic with regard to the result of the test. */ | |
149 | if (__builtin_expect (__gthread_active_latest_value < 0, 0)) | |
150 | { | |
151 | if (__gthrw_(pthread_once)) | |
152 | { | |
153 | /* If this really is a threaded program, then we must ensure that | |
154 | __gthread_active has been set to 1 before exiting this block. */ | |
155 | __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); | |
156 | __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger); | |
157 | __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); | |
158 | } | |
159 | ||
160 | /* Make sure we'll never enter this block again. */ | |
161 | if (__gthread_active < 0) | |
162 | __gthread_active = 0; | |
163 | ||
164 | __gthread_active_latest_value = __gthread_active; | |
165 | } | |
166 | ||
167 | return __gthread_active_latest_value != 0; | |
168 | } | |
169 | ||
799cff46 | 170 | #else /* neither FreeBSD nor Solaris */ |
efd6ef80 | 171 | |
18167442 EB |
172 | static inline int |
173 | __gthread_active_p (void) | |
174 | { | |
b8698a0f | 175 | static void *const __gthread_active_ptr |
72b16773 | 176 | = __extension__ (void *) &__gthrw_(pthread_cancel); |
18167442 EB |
177 | return __gthread_active_ptr != 0; |
178 | } | |
179 | ||
799cff46 | 180 | #endif /* FreeBSD or Solaris */ |
efd6ef80 | 181 | |
18167442 EB |
182 | #else /* not SUPPORTS_WEAK */ |
183 | ||
f74eeed4 JDA |
184 | /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread |
185 | calls in shared flavors of the HP-UX C library. Most of the stubs | |
186 | have no functionality. The details are described in the "libc cumulative | |
187 | patch" for each subversion of HP-UX 11. There are two special interfaces | |
8c157f90 | 188 | provided for checking whether an application is linked to a shared pthread |
f74eeed4 | 189 | library or not. However, these interfaces aren't available in early |
8c157f90 JDA |
190 | pthread libraries. We also need a test that works for archive |
191 | libraries. We can't use pthread_once as some libc versions call the | |
192 | init function. We also can't use pthread_create or pthread_attr_init | |
193 | as these create a thread and thereby prevent changing the default stack | |
194 | size. The function pthread_default_stacksize_np is available in both | |
195 | the archive and shared versions of libpthread. It can be used to | |
196 | determine the default pthread stack size. There is a stub in some | |
197 | shared libc versions which returns a zero size if pthreads are not | |
198 | active. We provide an equivalent stub to handle cases where libc | |
199 | doesn't provide one. */ | |
f74eeed4 JDA |
200 | |
201 | #if defined(__hppa__) && defined(__hpux__) | |
202 | ||
f74eeed4 JDA |
203 | static volatile int __gthread_active = -1; |
204 | ||
f74eeed4 JDA |
205 | static inline int |
206 | __gthread_active_p (void) | |
207 | { | |
208 | /* Avoid reading __gthread_active twice on the main code path. */ | |
209 | int __gthread_active_latest_value = __gthread_active; | |
8c157f90 | 210 | size_t __s; |
f74eeed4 | 211 | |
f74eeed4 JDA |
212 | if (__builtin_expect (__gthread_active_latest_value < 0, 0)) |
213 | { | |
8c157f90 JDA |
214 | pthread_default_stacksize_np (0, &__s); |
215 | __gthread_active = __s ? 1 : 0; | |
f74eeed4 JDA |
216 | __gthread_active_latest_value = __gthread_active; |
217 | } | |
218 | ||
219 | return __gthread_active_latest_value != 0; | |
220 | } | |
221 | ||
222 | #else /* not hppa-hpux */ | |
223 | ||
18167442 EB |
224 | static inline int |
225 | __gthread_active_p (void) | |
226 | { | |
227 | return 1; | |
228 | } | |
229 | ||
f74eeed4 JDA |
230 | #endif /* hppa-hpux */ |
231 | ||
18167442 EB |
232 | #endif /* SUPPORTS_WEAK */ |
233 | ||
234 | #ifdef _LIBOBJC | |
235 | ||
236 | /* This is the config.h file in libobjc/ */ | |
237 | #include <config.h> | |
238 | ||
239 | #ifdef HAVE_SCHED_H | |
240 | # include <sched.h> | |
241 | #endif | |
242 | ||
243 | /* Key structure for maintaining thread specific storage */ | |
244 | static pthread_key_t _objc_thread_storage; | |
245 | static pthread_attr_t _objc_thread_attribs; | |
246 | ||
247 | /* Thread local storage for a single thread */ | |
248 | static void *thread_local_storage = NULL; | |
249 | ||
250 | /* Backend initialization functions */ | |
251 | ||
252 | /* Initialize the threads subsystem. */ | |
253 | static inline int | |
254 | __gthread_objc_init_thread_system (void) | |
255 | { | |
256 | if (__gthread_active_p ()) | |
257 | { | |
258 | /* Initialize the thread storage key. */ | |
72b16773 | 259 | if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0) |
18167442 EB |
260 | { |
261 | /* The normal default detach state for threads is | |
262 | * PTHREAD_CREATE_JOINABLE which causes threads to not die | |
263 | * when you think they should. */ | |
72b16773 AO |
264 | if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0 |
265 | && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs, | |
18167442 EB |
266 | PTHREAD_CREATE_DETACHED) == 0) |
267 | return 0; | |
268 | } | |
269 | } | |
270 | ||
271 | return -1; | |
272 | } | |
273 | ||
274 | /* Close the threads subsystem. */ | |
275 | static inline int | |
276 | __gthread_objc_close_thread_system (void) | |
277 | { | |
278 | if (__gthread_active_p () | |
72b16773 AO |
279 | && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0 |
280 | && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0) | |
18167442 EB |
281 | return 0; |
282 | ||
283 | return -1; | |
284 | } | |
285 | ||
286 | /* Backend thread functions */ | |
287 | ||
288 | /* Create a new thread of execution. */ | |
289 | static inline objc_thread_t | |
290 | __gthread_objc_thread_detach (void (*func)(void *), void *arg) | |
291 | { | |
292 | objc_thread_t thread_id; | |
293 | pthread_t new_thread_handle; | |
294 | ||
295 | if (!__gthread_active_p ()) | |
296 | return NULL; | |
297 | ||
708e07fb NP |
298 | if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs, |
299 | (void *) func, arg))) | |
18167442 EB |
300 | thread_id = (objc_thread_t) new_thread_handle; |
301 | else | |
302 | thread_id = NULL; | |
303 | ||
304 | return thread_id; | |
305 | } | |
306 | ||
307 | /* Set the current thread's priority. */ | |
308 | static inline int | |
309 | __gthread_objc_thread_set_priority (int priority) | |
310 | { | |
311 | if (!__gthread_active_p ()) | |
312 | return -1; | |
313 | else | |
314 | { | |
315 | #ifdef _POSIX_PRIORITY_SCHEDULING | |
316 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING | |
72b16773 | 317 | pthread_t thread_id = __gthrw_(pthread_self) (); |
18167442 EB |
318 | int policy; |
319 | struct sched_param params; | |
320 | int priority_min, priority_max; | |
321 | ||
72b16773 | 322 | if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0) |
18167442 | 323 | { |
72b16773 | 324 | if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1) |
18167442 EB |
325 | return -1; |
326 | ||
72b16773 | 327 | if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1) |
18167442 EB |
328 | return -1; |
329 | ||
330 | if (priority > priority_max) | |
331 | priority = priority_max; | |
332 | else if (priority < priority_min) | |
333 | priority = priority_min; | |
334 | params.sched_priority = priority; | |
335 | ||
336 | /* | |
337 | * The solaris 7 and several other man pages incorrectly state that | |
338 | * this should be a pointer to policy but pthread.h is universally | |
339 | * at odds with this. | |
340 | */ | |
72b16773 | 341 | if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0) |
18167442 EB |
342 | return 0; |
343 | } | |
344 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ | |
345 | #endif /* _POSIX_PRIORITY_SCHEDULING */ | |
346 | return -1; | |
347 | } | |
348 | } | |
349 | ||
350 | /* Return the current thread's priority. */ | |
351 | static inline int | |
352 | __gthread_objc_thread_get_priority (void) | |
353 | { | |
354 | #ifdef _POSIX_PRIORITY_SCHEDULING | |
355 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING | |
356 | if (__gthread_active_p ()) | |
357 | { | |
358 | int policy; | |
359 | struct sched_param params; | |
360 | ||
72b16773 | 361 | if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0) |
18167442 EB |
362 | return params.sched_priority; |
363 | else | |
364 | return -1; | |
365 | } | |
366 | else | |
367 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ | |
368 | #endif /* _POSIX_PRIORITY_SCHEDULING */ | |
369 | return OBJC_THREAD_INTERACTIVE_PRIORITY; | |
370 | } | |
371 | ||
372 | /* Yield our process time to another thread. */ | |
373 | static inline void | |
374 | __gthread_objc_thread_yield (void) | |
375 | { | |
376 | if (__gthread_active_p ()) | |
72b16773 | 377 | __gthrw_(sched_yield) (); |
18167442 EB |
378 | } |
379 | ||
380 | /* Terminate the current thread. */ | |
381 | static inline int | |
382 | __gthread_objc_thread_exit (void) | |
383 | { | |
384 | if (__gthread_active_p ()) | |
385 | /* exit the thread */ | |
72b16773 | 386 | __gthrw_(pthread_exit) (&__objc_thread_exit_status); |
18167442 EB |
387 | |
388 | /* Failed if we reached here */ | |
389 | return -1; | |
390 | } | |
391 | ||
392 | /* Returns an integer value which uniquely describes a thread. */ | |
393 | static inline objc_thread_t | |
394 | __gthread_objc_thread_id (void) | |
395 | { | |
396 | if (__gthread_active_p ()) | |
72b16773 | 397 | return (objc_thread_t) __gthrw_(pthread_self) (); |
18167442 EB |
398 | else |
399 | return (objc_thread_t) 1; | |
400 | } | |
401 | ||
402 | /* Sets the thread's local storage pointer. */ | |
403 | static inline int | |
404 | __gthread_objc_thread_set_data (void *value) | |
405 | { | |
406 | if (__gthread_active_p ()) | |
72b16773 | 407 | return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); |
18167442 EB |
408 | else |
409 | { | |
410 | thread_local_storage = value; | |
411 | return 0; | |
412 | } | |
413 | } | |
414 | ||
415 | /* Returns the thread's local storage pointer. */ | |
416 | static inline void * | |
417 | __gthread_objc_thread_get_data (void) | |
418 | { | |
419 | if (__gthread_active_p ()) | |
72b16773 | 420 | return __gthrw_(pthread_getspecific) (_objc_thread_storage); |
18167442 EB |
421 | else |
422 | return thread_local_storage; | |
423 | } | |
424 | ||
425 | /* Backend mutex functions */ | |
426 | ||
427 | /* Allocate a mutex. */ | |
428 | static inline int | |
429 | __gthread_objc_mutex_allocate (objc_mutex_t mutex) | |
430 | { | |
431 | if (__gthread_active_p ()) | |
432 | { | |
433 | mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); | |
434 | ||
72b16773 | 435 | if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL)) |
18167442 EB |
436 | { |
437 | objc_free (mutex->backend); | |
438 | mutex->backend = NULL; | |
439 | return -1; | |
440 | } | |
441 | } | |
442 | ||
443 | return 0; | |
444 | } | |
445 | ||
446 | /* Deallocate a mutex. */ | |
447 | static inline int | |
448 | __gthread_objc_mutex_deallocate (objc_mutex_t mutex) | |
449 | { | |
450 | if (__gthread_active_p ()) | |
451 | { | |
452 | int count; | |
453 | ||
454 | /* | |
455 | * Posix Threads specifically require that the thread be unlocked | |
72b16773 | 456 | * for __gthrw_(pthread_mutex_destroy) to work. |
18167442 EB |
457 | */ |
458 | ||
459 | do | |
460 | { | |
72b16773 | 461 | count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); |
18167442 EB |
462 | if (count < 0) |
463 | return -1; | |
464 | } | |
465 | while (count); | |
466 | ||
72b16773 | 467 | if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) |
18167442 EB |
468 | return -1; |
469 | ||
470 | objc_free (mutex->backend); | |
471 | mutex->backend = NULL; | |
472 | } | |
473 | return 0; | |
474 | } | |
475 | ||
476 | /* Grab a lock on a mutex. */ | |
477 | static inline int | |
478 | __gthread_objc_mutex_lock (objc_mutex_t mutex) | |
479 | { | |
480 | if (__gthread_active_p () | |
72b16773 | 481 | && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0) |
18167442 EB |
482 | { |
483 | return -1; | |
484 | } | |
485 | ||
486 | return 0; | |
487 | } | |
488 | ||
489 | /* Try to grab a lock on a mutex. */ | |
490 | static inline int | |
491 | __gthread_objc_mutex_trylock (objc_mutex_t mutex) | |
492 | { | |
493 | if (__gthread_active_p () | |
72b16773 | 494 | && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0) |
18167442 EB |
495 | { |
496 | return -1; | |
497 | } | |
498 | ||
499 | return 0; | |
500 | } | |
501 | ||
502 | /* Unlock the mutex */ | |
503 | static inline int | |
504 | __gthread_objc_mutex_unlock (objc_mutex_t mutex) | |
505 | { | |
506 | if (__gthread_active_p () | |
72b16773 | 507 | && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0) |
18167442 EB |
508 | { |
509 | return -1; | |
510 | } | |
511 | ||
512 | return 0; | |
513 | } | |
514 | ||
515 | /* Backend condition mutex functions */ | |
516 | ||
517 | /* Allocate a condition. */ | |
518 | static inline int | |
519 | __gthread_objc_condition_allocate (objc_condition_t condition) | |
520 | { | |
521 | if (__gthread_active_p ()) | |
522 | { | |
523 | condition->backend = objc_malloc (sizeof (pthread_cond_t)); | |
524 | ||
72b16773 | 525 | if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL)) |
18167442 EB |
526 | { |
527 | objc_free (condition->backend); | |
528 | condition->backend = NULL; | |
529 | return -1; | |
530 | } | |
531 | } | |
532 | ||
533 | return 0; | |
534 | } | |
535 | ||
536 | /* Deallocate a condition. */ | |
537 | static inline int | |
538 | __gthread_objc_condition_deallocate (objc_condition_t condition) | |
539 | { | |
540 | if (__gthread_active_p ()) | |
541 | { | |
72b16773 | 542 | if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend)) |
18167442 EB |
543 | return -1; |
544 | ||
545 | objc_free (condition->backend); | |
546 | condition->backend = NULL; | |
547 | } | |
548 | return 0; | |
549 | } | |
550 | ||
551 | /* Wait on the condition */ | |
552 | static inline int | |
553 | __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) | |
554 | { | |
555 | if (__gthread_active_p ()) | |
72b16773 | 556 | return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend, |
18167442 EB |
557 | (pthread_mutex_t *) mutex->backend); |
558 | else | |
559 | return 0; | |
560 | } | |
561 | ||
562 | /* Wake up all threads waiting on this condition. */ | |
563 | static inline int | |
564 | __gthread_objc_condition_broadcast (objc_condition_t condition) | |
565 | { | |
566 | if (__gthread_active_p ()) | |
72b16773 | 567 | return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend); |
18167442 EB |
568 | else |
569 | return 0; | |
570 | } | |
571 | ||
572 | /* Wake up one thread waiting on this condition. */ | |
573 | static inline int | |
574 | __gthread_objc_condition_signal (objc_condition_t condition) | |
575 | { | |
576 | if (__gthread_active_p ()) | |
72b16773 | 577 | return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend); |
18167442 EB |
578 | else |
579 | return 0; | |
580 | } | |
581 | ||
582 | #else /* _LIBOBJC */ | |
583 | ||
584 | static inline int | |
09e361bb | 585 | __gthread_once (__gthread_once_t *__once, void (*__func) (void)) |
18167442 EB |
586 | { |
587 | if (__gthread_active_p ()) | |
09e361bb | 588 | return __gthrw_(pthread_once) (__once, __func); |
18167442 EB |
589 | else |
590 | return -1; | |
591 | } | |
592 | ||
593 | static inline int | |
09e361bb | 594 | __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) |
18167442 | 595 | { |
09e361bb | 596 | return __gthrw_(pthread_key_create) (__key, __dtor); |
18167442 EB |
597 | } |
598 | ||
599 | static inline int | |
09e361bb | 600 | __gthread_key_delete (__gthread_key_t __key) |
18167442 | 601 | { |
09e361bb | 602 | return __gthrw_(pthread_key_delete) (__key); |
18167442 EB |
603 | } |
604 | ||
605 | static inline void * | |
09e361bb | 606 | __gthread_getspecific (__gthread_key_t __key) |
18167442 | 607 | { |
09e361bb | 608 | return __gthrw_(pthread_getspecific) (__key); |
18167442 EB |
609 | } |
610 | ||
611 | static inline int | |
09e361bb | 612 | __gthread_setspecific (__gthread_key_t __key, const void *__ptr) |
18167442 | 613 | { |
09e361bb | 614 | return __gthrw_(pthread_setspecific) (__key, __ptr); |
18167442 EB |
615 | } |
616 | ||
4dabf736 | 617 | static inline int |
09e361bb | 618 | __gthread_mutex_destroy (__gthread_mutex_t *__mutex) |
4dabf736 JB |
619 | { |
620 | if (__gthread_active_p ()) | |
09e361bb | 621 | return __gthrw_(pthread_mutex_destroy) (__mutex); |
4dabf736 JB |
622 | else |
623 | return 0; | |
624 | } | |
625 | ||
18167442 | 626 | static inline int |
09e361bb | 627 | __gthread_mutex_lock (__gthread_mutex_t *__mutex) |
18167442 EB |
628 | { |
629 | if (__gthread_active_p ()) | |
09e361bb | 630 | return __gthrw_(pthread_mutex_lock) (__mutex); |
18167442 EB |
631 | else |
632 | return 0; | |
633 | } | |
634 | ||
635 | static inline int | |
09e361bb | 636 | __gthread_mutex_trylock (__gthread_mutex_t *__mutex) |
18167442 EB |
637 | { |
638 | if (__gthread_active_p ()) | |
09e361bb | 639 | return __gthrw_(pthread_mutex_trylock) (__mutex); |
18167442 EB |
640 | else |
641 | return 0; | |
642 | } | |
643 | ||
644 | static inline int | |
09e361bb | 645 | __gthread_mutex_unlock (__gthread_mutex_t *__mutex) |
18167442 EB |
646 | { |
647 | if (__gthread_active_p ()) | |
09e361bb | 648 | return __gthrw_(pthread_mutex_unlock) (__mutex); |
18167442 EB |
649 | else |
650 | return 0; | |
651 | } | |
652 | ||
653 | static inline int | |
09e361bb | 654 | __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) |
18167442 | 655 | { |
09e361bb JJ |
656 | __mutex->depth = 0; |
657 | __mutex->owner = (pthread_t) 0; | |
658 | return __gthrw_(pthread_mutex_init) (&__mutex->actual, NULL); | |
18167442 EB |
659 | } |
660 | ||
661 | static inline int | |
09e361bb | 662 | __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) |
18167442 EB |
663 | { |
664 | if (__gthread_active_p ()) | |
665 | { | |
09e361bb | 666 | pthread_t __me = __gthrw_(pthread_self) (); |
18167442 | 667 | |
09e361bb | 668 | if (__mutex->owner != __me) |
18167442 | 669 | { |
09e361bb JJ |
670 | __gthrw_(pthread_mutex_lock) (&__mutex->actual); |
671 | __mutex->owner = __me; | |
18167442 EB |
672 | } |
673 | ||
09e361bb | 674 | __mutex->depth++; |
18167442 EB |
675 | } |
676 | return 0; | |
677 | } | |
678 | ||
679 | static inline int | |
09e361bb | 680 | __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) |
18167442 EB |
681 | { |
682 | if (__gthread_active_p ()) | |
683 | { | |
09e361bb | 684 | pthread_t __me = __gthrw_(pthread_self) (); |
18167442 | 685 | |
09e361bb | 686 | if (__mutex->owner != __me) |
18167442 | 687 | { |
09e361bb | 688 | if (__gthrw_(pthread_mutex_trylock) (&__mutex->actual)) |
18167442 | 689 | return 1; |
09e361bb | 690 | __mutex->owner = __me; |
18167442 EB |
691 | } |
692 | ||
09e361bb | 693 | __mutex->depth++; |
18167442 EB |
694 | } |
695 | return 0; | |
696 | } | |
697 | ||
698 | static inline int | |
09e361bb | 699 | __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) |
18167442 EB |
700 | { |
701 | if (__gthread_active_p ()) | |
702 | { | |
09e361bb | 703 | if (--__mutex->depth == 0) |
e2e9b7b8 | 704 | { |
09e361bb JJ |
705 | __mutex->owner = (pthread_t) 0; |
706 | __gthrw_(pthread_mutex_unlock) (&__mutex->actual); | |
18167442 EB |
707 | } |
708 | } | |
709 | return 0; | |
710 | } | |
711 | ||
afd82ef5 | 712 | static inline int |
09e361bb | 713 | __gthread_cond_broadcast (__gthread_cond_t *__cond) |
afd82ef5 | 714 | { |
09e361bb | 715 | return __gthrw_(pthread_cond_broadcast) (__cond); |
afd82ef5 DK |
716 | } |
717 | ||
718 | static inline int | |
09e361bb | 719 | __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex) |
afd82ef5 | 720 | { |
09e361bb | 721 | return __gthrw_(pthread_cond_wait) (__cond, __mutex); |
afd82ef5 DK |
722 | } |
723 | ||
724 | static inline int | |
09e361bb JJ |
725 | __gthread_cond_wait_recursive (__gthread_cond_t *__cond, |
726 | __gthread_recursive_mutex_t *__mutex) | |
afd82ef5 | 727 | { |
09e361bb | 728 | return __gthrw_(pthread_cond_wait) (__cond, &__mutex->actual); |
afd82ef5 DK |
729 | } |
730 | ||
18167442 EB |
731 | #endif /* _LIBOBJC */ |
732 | ||
733 | #endif /* ! GCC_GTHR_POSIX_H */ |