Branch data Line data Source code
1 : : /* Threads compatibility routines for libgcc2 and libobjc. */
2 : : /* Compile this one with gcc. */
3 : : /* Copyright (C) 1997-2013 Free Software Foundation, Inc.
4 : :
5 : : This file is part of GCC.
6 : :
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 3, or (at your option) any later
10 : : version.
11 : :
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.
16 : :
17 : : Under Section 7 of GPL version 3, you are granted additional
18 : : permissions described in the GCC Runtime Library Exception, version
19 : : 3.1, as published by the Free Software Foundation.
20 : :
21 : : You should have received a copy of the GNU General Public License and
22 : : a copy of the GCC Runtime Library Exception along with this program;
23 : : see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 : : <http://www.gnu.org/licenses/>. */
25 : :
26 : : #ifndef _GLIBCXX_GCC_GTHR_POSIX_H
27 : : #define _GLIBCXX_GCC_GTHR_POSIX_H
28 : :
29 : : /* POSIX threads specific definitions.
30 : : Easy, since the interface is just one-to-one mapping. */
31 : :
32 : : #define __GTHREADS 1
33 : : #define __GTHREADS_CXX0X 1
34 : :
35 : : #include <pthread.h>
36 : :
37 : : #if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \
38 : : || !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK))
39 : : # include <unistd.h>
40 : : # if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 0
41 : : # define _GTHREAD_USE_MUTEX_TIMEDLOCK 1
42 : : # else
43 : : # define _GTHREAD_USE_MUTEX_TIMEDLOCK 0
44 : : # endif
45 : : #endif
46 : :
47 : : typedef pthread_t __gthread_t;
48 : : typedef pthread_key_t __gthread_key_t;
49 : : typedef pthread_once_t __gthread_once_t;
50 : : typedef pthread_mutex_t __gthread_mutex_t;
51 : : typedef pthread_mutex_t __gthread_recursive_mutex_t;
52 : : typedef pthread_cond_t __gthread_cond_t;
53 : : typedef struct timespec __gthread_time_t;
54 : :
55 : : /* POSIX like conditional variables are supported. Please look at comments
56 : : in gthr.h for details. */
57 : : #define __GTHREAD_HAS_COND 1
58 : :
59 : : #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER
60 : : #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
61 : : #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
62 : : #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
63 : : #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER
64 : : #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
65 : : #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
66 : : #else
67 : : #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
68 : : #endif
69 : : #define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER
70 : : #define __GTHREAD_TIME_INIT {0,0}
71 : :
72 : : #ifdef _GTHREAD_USE_MUTEX_INIT_FUNC
73 : : # undef __GTHREAD_MUTEX_INIT
74 : : #endif
75 : : #ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC
76 : : # undef __GTHREAD_RECURSIVE_MUTEX_INIT
77 : : # undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
78 : : # define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
79 : : #endif
80 : : #ifdef _GTHREAD_USE_COND_INIT_FUNC
81 : : # undef __GTHREAD_COND_INIT
82 : : # define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
83 : : #endif
84 : :
85 : : #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
86 : : # ifndef __gthrw_pragma
87 : : # define __gthrw_pragma(pragma)
88 : : # endif
89 : : # define __gthrw2(name,name2,type) \
90 : : static __typeof(type) name __attribute__ ((__weakref__(#name2))); \
91 : : __gthrw_pragma(weak type)
92 : : # define __gthrw_(name) __gthrw_ ## name
93 : : #else
94 : : # define __gthrw2(name,name2,type)
95 : : # define __gthrw_(name) name
96 : : #endif
97 : :
98 : : /* Typically, __gthrw_foo is a weak reference to symbol foo. */
99 : : #define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name)
100 : :
101 : : __gthrw(pthread_once)
102 : : __gthrw(pthread_getspecific)
103 : : __gthrw(pthread_setspecific)
104 : :
105 : : __gthrw(pthread_create)
106 : : __gthrw(pthread_join)
107 : : __gthrw(pthread_equal)
108 : : __gthrw(pthread_self)
109 : : __gthrw(pthread_detach)
110 : : #ifndef __BIONIC__
111 : : __gthrw(pthread_cancel)
112 : : #endif
113 : : __gthrw(sched_yield)
114 : :
115 : : __gthrw(pthread_mutex_lock)
116 : : __gthrw(pthread_mutex_trylock)
117 : : #if _GTHREAD_USE_MUTEX_TIMEDLOCK
118 : : __gthrw(pthread_mutex_timedlock)
119 : : #endif
120 : : __gthrw(pthread_mutex_unlock)
121 : : __gthrw(pthread_mutex_init)
122 : : __gthrw(pthread_mutex_destroy)
123 : :
124 : : __gthrw(pthread_cond_init)
125 : : __gthrw(pthread_cond_broadcast)
126 : : __gthrw(pthread_cond_signal)
127 : : __gthrw(pthread_cond_wait)
128 : : __gthrw(pthread_cond_timedwait)
129 : : __gthrw(pthread_cond_destroy)
130 : :
131 : : __gthrw(pthread_key_create)
132 : : __gthrw(pthread_key_delete)
133 : : __gthrw(pthread_mutexattr_init)
134 : : __gthrw(pthread_mutexattr_settype)
135 : : __gthrw(pthread_mutexattr_destroy)
136 : :
137 : :
138 : : #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)
139 : : /* Objective-C. */
140 : : __gthrw(pthread_exit)
141 : : #ifdef _POSIX_PRIORITY_SCHEDULING
142 : : #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
143 : : __gthrw(sched_get_priority_max)
144 : : __gthrw(sched_get_priority_min)
145 : : #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
146 : : #endif /* _POSIX_PRIORITY_SCHEDULING */
147 : : __gthrw(pthread_attr_destroy)
148 : : __gthrw(pthread_attr_init)
149 : : __gthrw(pthread_attr_setdetachstate)
150 : : #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
151 : : __gthrw(pthread_getschedparam)
152 : : __gthrw(pthread_setschedparam)
153 : : #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
154 : : #endif /* _LIBOBJC || _LIBOBJC_WEAK */
155 : :
156 : : #if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK
157 : :
158 : : /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if
159 : : -pthreads is not specified. The functions are dummies and most return an
160 : : error value. However pthread_once returns 0 without invoking the routine
161 : : it is passed so we cannot pretend that the interface is active if -pthreads
162 : : is not specified. On Solaris 2.5.1, the interface is not exposed at all so
163 : : we need to play the usual game with weak symbols. On Solaris 10 and up, a
164 : : working interface is always exposed. On FreeBSD 6 and later, libc also
165 : : exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up
166 : : to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc,
167 : : which means the alternate __gthread_active_p below cannot be used there. */
168 : :
169 : : #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__))
170 : :
171 : : static volatile int __gthread_active = -1;
172 : :
173 : : static void
174 : : __gthread_trigger (void)
175 : : {
176 : : __gthread_active = 1;
177 : : }
178 : :
179 : : static inline int
180 : : __gthread_active_p (void)
181 : : {
182 : : static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER;
183 : : static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT;
184 : :
185 : : /* Avoid reading __gthread_active twice on the main code path. */
186 : : int __gthread_active_latest_value = __gthread_active;
187 : :
188 : : /* This test is not protected to avoid taking a lock on the main code
189 : : path so every update of __gthread_active in a threaded program must
190 : : be atomic with regard to the result of the test. */
191 : : if (__builtin_expect (__gthread_active_latest_value < 0, 0))
192 : : {
193 : : if (__gthrw_(pthread_once))
194 : : {
195 : : /* If this really is a threaded program, then we must ensure that
196 : : __gthread_active has been set to 1 before exiting this block. */
197 : : __gthrw_(pthread_mutex_lock) (&__gthread_active_mutex);
198 : : __gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger);
199 : : __gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex);
200 : : }
201 : :
202 : : /* Make sure we'll never enter this block again. */
203 : : if (__gthread_active < 0)
204 : : __gthread_active = 0;
205 : :
206 : : __gthread_active_latest_value = __gthread_active;
207 : : }
208 : :
209 : : return __gthread_active_latest_value != 0;
210 : : }
211 : :
212 : : #else /* neither FreeBSD nor Solaris */
213 : :
214 : : /* For a program to be multi-threaded the only thing that it certainly must
215 : : be using is pthread_create. However, there may be other libraries that
216 : : intercept pthread_create with their own definitions to wrap pthreads
217 : : functionality for some purpose. In those cases, pthread_create being
218 : : defined might not necessarily mean that libpthread is actually linked
219 : : in.
220 : :
221 : : For the GNU C library, we can use a known internal name. This is always
222 : : available in the ABI, but no other library would define it. That is
223 : : ideal, since any public pthread function might be intercepted just as
224 : : pthread_create might be. __pthread_key_create is an "internal"
225 : : implementation symbol, but it is part of the public exported ABI. Also,
226 : : it's among the symbols that the static libpthread.a always links in
227 : : whenever pthread_create is used, so there is no danger of a false
228 : : negative result in any statically-linked, multi-threaded program.
229 : :
230 : : For others, we choose pthread_cancel as a function that seems unlikely
231 : : to be redefined by an interceptor library. The bionic (Android) C
232 : : library does not provide pthread_cancel, so we do use pthread_create
233 : : there (and interceptor libraries lose). */
234 : :
235 : : #ifdef __GLIBC__
236 : : __gthrw2(__gthrw_(__pthread_key_create),
237 : : __pthread_key_create,
238 : : pthread_key_create)
239 : : # define GTHR_ACTIVE_PROXY __gthrw_(__pthread_key_create)
240 : : #elif defined (__BIONIC__)
241 : : # define GTHR_ACTIVE_PROXY __gthrw_(pthread_create)
242 : : #else
243 : : # define GTHR_ACTIVE_PROXY __gthrw_(pthread_cancel)
244 : : #endif
245 : :
246 : : static inline int
247 : 0 : __gthread_active_p (void)
248 : : {
249 : : static void *const __gthread_active_ptr
250 : : = __extension__ (void *) >HR_ACTIVE_PROXY;
251 : 0 : return __gthread_active_ptr != 0;
252 : : }
253 : :
254 : : #endif /* FreeBSD or Solaris */
255 : :
256 : : #else /* not __GXX_WEAK__ */
257 : :
258 : : /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread
259 : : calls in shared flavors of the HP-UX C library. Most of the stubs
260 : : have no functionality. The details are described in the "libc cumulative
261 : : patch" for each subversion of HP-UX 11. There are two special interfaces
262 : : provided for checking whether an application is linked to a shared pthread
263 : : library or not. However, these interfaces aren't available in early
264 : : libpthread libraries. We also need a test that works for archive
265 : : libraries. We can't use pthread_once as some libc versions call the
266 : : init function. We also can't use pthread_create or pthread_attr_init
267 : : as these create a thread and thereby prevent changing the default stack
268 : : size. The function pthread_default_stacksize_np is available in both
269 : : the archive and shared versions of libpthread. It can be used to
270 : : determine the default pthread stack size. There is a stub in some
271 : : shared libc versions which returns a zero size if pthreads are not
272 : : active. We provide an equivalent stub to handle cases where libc
273 : : doesn't provide one. */
274 : :
275 : : #if defined(__hppa__) && defined(__hpux__)
276 : :
277 : : static volatile int __gthread_active = -1;
278 : :
279 : : static inline int
280 : : __gthread_active_p (void)
281 : : {
282 : : /* Avoid reading __gthread_active twice on the main code path. */
283 : : int __gthread_active_latest_value = __gthread_active;
284 : : size_t __s;
285 : :
286 : : if (__builtin_expect (__gthread_active_latest_value < 0, 0))
287 : : {
288 : : pthread_default_stacksize_np (0, &__s);
289 : : __gthread_active = __s ? 1 : 0;
290 : : __gthread_active_latest_value = __gthread_active;
291 : : }
292 : :
293 : : return __gthread_active_latest_value != 0;
294 : : }
295 : :
296 : : #else /* not hppa-hpux */
297 : :
298 : : static inline int
299 : : __gthread_active_p (void)
300 : : {
301 : : return 1;
302 : : }
303 : :
304 : : #endif /* hppa-hpux */
305 : :
306 : : #endif /* __GXX_WEAK__ */
307 : :
308 : : #ifdef _LIBOBJC
309 : :
310 : : /* This is the config.h file in libobjc/ */
311 : : #include <config.h>
312 : :
313 : : #ifdef HAVE_SCHED_H
314 : : # include <sched.h>
315 : : #endif
316 : :
317 : : /* Key structure for maintaining thread specific storage */
318 : : static pthread_key_t _objc_thread_storage;
319 : : static pthread_attr_t _objc_thread_attribs;
320 : :
321 : : /* Thread local storage for a single thread */
322 : : static void *thread_local_storage = NULL;
323 : :
324 : : /* Backend initialization functions */
325 : :
326 : : /* Initialize the threads subsystem. */
327 : : static inline int
328 : : __gthread_objc_init_thread_system (void)
329 : : {
330 : : if (__gthread_active_p ())
331 : : {
332 : : /* Initialize the thread storage key. */
333 : : if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0)
334 : : {
335 : : /* The normal default detach state for threads is
336 : : * PTHREAD_CREATE_JOINABLE which causes threads to not die
337 : : * when you think they should. */
338 : : if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0
339 : : && __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs,
340 : : PTHREAD_CREATE_DETACHED) == 0)
341 : : return 0;
342 : : }
343 : : }
344 : :
345 : : return -1;
346 : : }
347 : :
348 : : /* Close the threads subsystem. */
349 : : static inline int
350 : : __gthread_objc_close_thread_system (void)
351 : : {
352 : : if (__gthread_active_p ()
353 : : && __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0
354 : : && __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0)
355 : : return 0;
356 : :
357 : : return -1;
358 : : }
359 : :
360 : : /* Backend thread functions */
361 : :
362 : : /* Create a new thread of execution. */
363 : : static inline objc_thread_t
364 : : __gthread_objc_thread_detach (void (*func)(void *), void *arg)
365 : : {
366 : : objc_thread_t thread_id;
367 : : pthread_t new_thread_handle;
368 : :
369 : : if (!__gthread_active_p ())
370 : : return NULL;
371 : :
372 : : if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs,
373 : : (void *) func, arg)))
374 : : thread_id = (objc_thread_t) new_thread_handle;
375 : : else
376 : : thread_id = NULL;
377 : :
378 : : return thread_id;
379 : : }
380 : :
381 : : /* Set the current thread's priority. */
382 : : static inline int
383 : : __gthread_objc_thread_set_priority (int priority)
384 : : {
385 : : if (!__gthread_active_p ())
386 : : return -1;
387 : : else
388 : : {
389 : : #ifdef _POSIX_PRIORITY_SCHEDULING
390 : : #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
391 : : pthread_t thread_id = __gthrw_(pthread_self) ();
392 : : int policy;
393 : : struct sched_param params;
394 : : int priority_min, priority_max;
395 : :
396 : : if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0)
397 : : {
398 : : if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1)
399 : : return -1;
400 : :
401 : : if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1)
402 : : return -1;
403 : :
404 : : if (priority > priority_max)
405 : : priority = priority_max;
406 : : else if (priority < priority_min)
407 : : priority = priority_min;
408 : : params.sched_priority = priority;
409 : :
410 : : /*
411 : : * The solaris 7 and several other man pages incorrectly state that
412 : : * this should be a pointer to policy but pthread.h is universally
413 : : * at odds with this.
414 : : */
415 : : if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0)
416 : : return 0;
417 : : }
418 : : #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
419 : : #endif /* _POSIX_PRIORITY_SCHEDULING */
420 : : return -1;
421 : : }
422 : : }
423 : :
424 : : /* Return the current thread's priority. */
425 : : static inline int
426 : : __gthread_objc_thread_get_priority (void)
427 : : {
428 : : #ifdef _POSIX_PRIORITY_SCHEDULING
429 : : #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
430 : : if (__gthread_active_p ())
431 : : {
432 : : int policy;
433 : : struct sched_param params;
434 : :
435 : : if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0)
436 : : return params.sched_priority;
437 : : else
438 : : return -1;
439 : : }
440 : : else
441 : : #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
442 : : #endif /* _POSIX_PRIORITY_SCHEDULING */
443 : : return OBJC_THREAD_INTERACTIVE_PRIORITY;
444 : : }
445 : :
446 : : /* Yield our process time to another thread. */
447 : : static inline void
448 : : __gthread_objc_thread_yield (void)
449 : : {
450 : : if (__gthread_active_p ())
451 : : __gthrw_(sched_yield) ();
452 : : }
453 : :
454 : : /* Terminate the current thread. */
455 : : static inline int
456 : : __gthread_objc_thread_exit (void)
457 : : {
458 : : if (__gthread_active_p ())
459 : : /* exit the thread */
460 : : __gthrw_(pthread_exit) (&__objc_thread_exit_status);
461 : :
462 : : /* Failed if we reached here */
463 : : return -1;
464 : : }
465 : :
466 : : /* Returns an integer value which uniquely describes a thread. */
467 : : static inline objc_thread_t
468 : : __gthread_objc_thread_id (void)
469 : : {
470 : : if (__gthread_active_p ())
471 : : return (objc_thread_t) __gthrw_(pthread_self) ();
472 : : else
473 : : return (objc_thread_t) 1;
474 : : }
475 : :
476 : : /* Sets the thread's local storage pointer. */
477 : : static inline int
478 : : __gthread_objc_thread_set_data (void *value)
479 : : {
480 : : if (__gthread_active_p ())
481 : : return __gthrw_(pthread_setspecific) (_objc_thread_storage, value);
482 : : else
483 : : {
484 : : thread_local_storage = value;
485 : : return 0;
486 : : }
487 : : }
488 : :
489 : : /* Returns the thread's local storage pointer. */
490 : : static inline void *
491 : : __gthread_objc_thread_get_data (void)
492 : : {
493 : : if (__gthread_active_p ())
494 : : return __gthrw_(pthread_getspecific) (_objc_thread_storage);
495 : : else
496 : : return thread_local_storage;
497 : : }
498 : :
499 : : /* Backend mutex functions */
500 : :
501 : : /* Allocate a mutex. */
502 : : static inline int
503 : : __gthread_objc_mutex_allocate (objc_mutex_t mutex)
504 : : {
505 : : if (__gthread_active_p ())
506 : : {
507 : : mutex->backend = objc_malloc (sizeof (pthread_mutex_t));
508 : :
509 : : if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL))
510 : : {
511 : : objc_free (mutex->backend);
512 : : mutex->backend = NULL;
513 : : return -1;
514 : : }
515 : : }
516 : :
517 : : return 0;
518 : : }
519 : :
520 : : /* Deallocate a mutex. */
521 : : static inline int
522 : : __gthread_objc_mutex_deallocate (objc_mutex_t mutex)
523 : : {
524 : : if (__gthread_active_p ())
525 : : {
526 : : int count;
527 : :
528 : : /*
529 : : * Posix Threads specifically require that the thread be unlocked
530 : : * for __gthrw_(pthread_mutex_destroy) to work.
531 : : */
532 : :
533 : : do
534 : : {
535 : : count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend);
536 : : if (count < 0)
537 : : return -1;
538 : : }
539 : : while (count);
540 : :
541 : : if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend))
542 : : return -1;
543 : :
544 : : objc_free (mutex->backend);
545 : : mutex->backend = NULL;
546 : : }
547 : : return 0;
548 : : }
549 : :
550 : : /* Grab a lock on a mutex. */
551 : : static inline int
552 : : __gthread_objc_mutex_lock (objc_mutex_t mutex)
553 : : {
554 : : if (__gthread_active_p ()
555 : : && __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0)
556 : : {
557 : : return -1;
558 : : }
559 : :
560 : : return 0;
561 : : }
562 : :
563 : : /* Try to grab a lock on a mutex. */
564 : : static inline int
565 : : __gthread_objc_mutex_trylock (objc_mutex_t mutex)
566 : : {
567 : : if (__gthread_active_p ()
568 : : && __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0)
569 : : {
570 : : return -1;
571 : : }
572 : :
573 : : return 0;
574 : : }
575 : :
576 : : /* Unlock the mutex */
577 : : static inline int
578 : : __gthread_objc_mutex_unlock (objc_mutex_t mutex)
579 : : {
580 : : if (__gthread_active_p ()
581 : : && __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0)
582 : : {
583 : : return -1;
584 : : }
585 : :
586 : : return 0;
587 : : }
588 : :
589 : : /* Backend condition mutex functions */
590 : :
591 : : /* Allocate a condition. */
592 : : static inline int
593 : : __gthread_objc_condition_allocate (objc_condition_t condition)
594 : : {
595 : : if (__gthread_active_p ())
596 : : {
597 : : condition->backend = objc_malloc (sizeof (pthread_cond_t));
598 : :
599 : : if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL))
600 : : {
601 : : objc_free (condition->backend);
602 : : condition->backend = NULL;
603 : : return -1;
604 : : }
605 : : }
606 : :
607 : : return 0;
608 : : }
609 : :
610 : : /* Deallocate a condition. */
611 : : static inline int
612 : : __gthread_objc_condition_deallocate (objc_condition_t condition)
613 : : {
614 : : if (__gthread_active_p ())
615 : : {
616 : : if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend))
617 : : return -1;
618 : :
619 : : objc_free (condition->backend);
620 : : condition->backend = NULL;
621 : : }
622 : : return 0;
623 : : }
624 : :
625 : : /* Wait on the condition */
626 : : static inline int
627 : : __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex)
628 : : {
629 : : if (__gthread_active_p ())
630 : : return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend,
631 : : (pthread_mutex_t *) mutex->backend);
632 : : else
633 : : return 0;
634 : : }
635 : :
636 : : /* Wake up all threads waiting on this condition. */
637 : : static inline int
638 : : __gthread_objc_condition_broadcast (objc_condition_t condition)
639 : : {
640 : : if (__gthread_active_p ())
641 : : return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend);
642 : : else
643 : : return 0;
644 : : }
645 : :
646 : : /* Wake up one thread waiting on this condition. */
647 : : static inline int
648 : : __gthread_objc_condition_signal (objc_condition_t condition)
649 : : {
650 : : if (__gthread_active_p ())
651 : : return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend);
652 : : else
653 : : return 0;
654 : : }
655 : :
656 : : #else /* _LIBOBJC */
657 : :
658 : : static inline int
659 : : __gthread_create (__gthread_t *__threadid, void *(*__func) (void*),
660 : : void *__args)
661 : : {
662 : : return __gthrw_(pthread_create) (__threadid, NULL, __func, __args);
663 : : }
664 : :
665 : : static inline int
666 : : __gthread_join (__gthread_t __threadid, void **__value_ptr)
667 : : {
668 : : return __gthrw_(pthread_join) (__threadid, __value_ptr);
669 : : }
670 : :
671 : : static inline int
672 : : __gthread_detach (__gthread_t __threadid)
673 : : {
674 : : return __gthrw_(pthread_detach) (__threadid);
675 : : }
676 : :
677 : : static inline int
678 : : __gthread_equal (__gthread_t __t1, __gthread_t __t2)
679 : : {
680 : : return __gthrw_(pthread_equal) (__t1, __t2);
681 : : }
682 : :
683 : : static inline __gthread_t
684 : : __gthread_self (void)
685 : : {
686 : : return __gthrw_(pthread_self) ();
687 : : }
688 : :
689 : : static inline int
690 : : __gthread_yield (void)
691 : : {
692 : : return __gthrw_(sched_yield) ();
693 : : }
694 : :
695 : : static inline int
696 : : __gthread_once (__gthread_once_t *__once, void (*__func) (void))
697 : : {
698 : : if (__gthread_active_p ())
699 : : return __gthrw_(pthread_once) (__once, __func);
700 : : else
701 : : return -1;
702 : : }
703 : :
704 : : static inline int
705 : : __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *))
706 : : {
707 : : return __gthrw_(pthread_key_create) (__key, __dtor);
708 : : }
709 : :
710 : : static inline int
711 : : __gthread_key_delete (__gthread_key_t __key)
712 : : {
713 : : return __gthrw_(pthread_key_delete) (__key);
714 : : }
715 : :
716 : : static inline void *
717 : : __gthread_getspecific (__gthread_key_t __key)
718 : : {
719 : : return __gthrw_(pthread_getspecific) (__key);
720 : : }
721 : :
722 : : static inline int
723 : : __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
724 : : {
725 : : return __gthrw_(pthread_setspecific) (__key, __ptr);
726 : : }
727 : :
728 : : static inline void
729 : : __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
730 : : {
731 : : if (__gthread_active_p ())
732 : : __gthrw_(pthread_mutex_init) (__mutex, NULL);
733 : : }
734 : :
735 : : static inline int
736 : : __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
737 : : {
738 : : if (__gthread_active_p ())
739 : : return __gthrw_(pthread_mutex_destroy) (__mutex);
740 : : else
741 : : return 0;
742 : : }
743 : :
744 : : static inline int
745 : : __gthread_mutex_lock (__gthread_mutex_t *__mutex)
746 : : {
747 : : if (__gthread_active_p ())
748 : : return __gthrw_(pthread_mutex_lock) (__mutex);
749 : : else
750 : : return 0;
751 : : }
752 : :
753 : : static inline int
754 : : __gthread_mutex_trylock (__gthread_mutex_t *__mutex)
755 : : {
756 : : if (__gthread_active_p ())
757 : : return __gthrw_(pthread_mutex_trylock) (__mutex);
758 : : else
759 : : return 0;
760 : : }
761 : :
762 : : #if _GTHREAD_USE_MUTEX_TIMEDLOCK
763 : : static inline int
764 : : __gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
765 : : const __gthread_time_t *__abs_timeout)
766 : : {
767 : : if (__gthread_active_p ())
768 : : return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout);
769 : : else
770 : : return 0;
771 : : }
772 : : #endif
773 : :
774 : : static inline int
775 : : __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
776 : : {
777 : : if (__gthread_active_p ())
778 : : return __gthrw_(pthread_mutex_unlock) (__mutex);
779 : : else
780 : : return 0;
781 : : }
782 : :
783 : : #if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \
784 : : || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC)
785 : : static inline int
786 : : __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
787 : : {
788 : : if (__gthread_active_p ())
789 : : {
790 : : pthread_mutexattr_t __attr;
791 : : int __r;
792 : :
793 : : __r = __gthrw_(pthread_mutexattr_init) (&__attr);
794 : : if (!__r)
795 : : __r = __gthrw_(pthread_mutexattr_settype) (&__attr,
796 : : PTHREAD_MUTEX_RECURSIVE);
797 : : if (!__r)
798 : : __r = __gthrw_(pthread_mutex_init) (__mutex, &__attr);
799 : : if (!__r)
800 : : __r = __gthrw_(pthread_mutexattr_destroy) (&__attr);
801 : : return __r;
802 : : }
803 : : return 0;
804 : : }
805 : : #endif
806 : :
807 : : static inline int
808 : : __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
809 : : {
810 : : return __gthread_mutex_lock (__mutex);
811 : : }
812 : :
813 : : static inline int
814 : : __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
815 : : {
816 : : return __gthread_mutex_trylock (__mutex);
817 : : }
818 : :
819 : : #if _GTHREAD_USE_MUTEX_TIMEDLOCK
820 : : static inline int
821 : : __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
822 : : const __gthread_time_t *__abs_timeout)
823 : : {
824 : : return __gthread_mutex_timedlock (__mutex, __abs_timeout);
825 : : }
826 : : #endif
827 : :
828 : : static inline int
829 : : __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
830 : : {
831 : : return __gthread_mutex_unlock (__mutex);
832 : : }
833 : :
834 : : static inline int
835 : : __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
836 : : {
837 : : return __gthread_mutex_destroy (__mutex);
838 : : }
839 : :
840 : : #ifdef _GTHREAD_USE_COND_INIT_FUNC
841 : : static inline void
842 : : __gthread_cond_init_function (__gthread_cond_t *__cond)
843 : : {
844 : : if (__gthread_active_p ())
845 : : __gthrw_(pthread_cond_init) (__cond, NULL);
846 : : }
847 : : #endif
848 : :
849 : : static inline int
850 : : __gthread_cond_broadcast (__gthread_cond_t *__cond)
851 : : {
852 : : return __gthrw_(pthread_cond_broadcast) (__cond);
853 : : }
854 : :
855 : : static inline int
856 : : __gthread_cond_signal (__gthread_cond_t *__cond)
857 : : {
858 : : return __gthrw_(pthread_cond_signal) (__cond);
859 : : }
860 : :
861 : : static inline int
862 : : __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
863 : : {
864 : : return __gthrw_(pthread_cond_wait) (__cond, __mutex);
865 : : }
866 : :
867 : : static inline int
868 : : __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
869 : : const __gthread_time_t *__abs_timeout)
870 : : {
871 : : return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout);
872 : : }
873 : :
874 : : static inline int
875 : : __gthread_cond_wait_recursive (__gthread_cond_t *__cond,
876 : : __gthread_recursive_mutex_t *__mutex)
877 : : {
878 : : return __gthread_cond_wait (__cond, __mutex);
879 : : }
880 : :
881 : : static inline int
882 : : __gthread_cond_destroy (__gthread_cond_t* __cond)
883 : : {
884 : : return __gthrw_(pthread_cond_destroy) (__cond);
885 : : }
886 : :
887 : : #endif /* _LIBOBJC */
888 : :
889 : : #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */
|