]>
Commit | Line | Data |
---|---|---|
6319d58e | 1 | /* Threads compatibility routines for libgcc2 and libobjc. */ |
58febf9e | 2 | /* Compile this one with gcc. */ |
0ba508e4 | 3 | /* Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004 |
ecd34a08 | 4 | Free Software Foundation, Inc. |
58febf9e | 5 | |
f12b58b3 | 6 | This file is part of GCC. |
58febf9e | 7 | |
f12b58b3 | 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 2, or (at your option) any later | |
11 | version. | |
58febf9e | 12 | |
f12b58b3 | 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. | |
58febf9e | 17 | |
18 | You should have received a copy of the GNU General Public License | |
f12b58b3 | 19 | along with GCC; see the file COPYING. If not, write to the Free |
20 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA | |
21 | 02111-1307, USA. */ | |
58febf9e | 22 | |
23 | /* As a special exception, if you link this library with other files, | |
24 | some of which are compiled with GCC, to produce an executable, | |
25 | this library does not by itself cause the resulting executable | |
26 | to be covered by the GNU General Public License. | |
27 | This exception does not however invalidate any other reasons why | |
28 | the executable file might be covered by the GNU General Public License. */ | |
29 | ||
2a281353 | 30 | #ifndef GCC_GTHR_POSIX_H |
31 | #define GCC_GTHR_POSIX_H | |
58febf9e | 32 | |
33 | /* POSIX threads specific definitions. | |
5a54c45e | 34 | Easy, since the interface is just one-to-one mapping. */ |
58febf9e | 35 | |
36 | #define __GTHREADS 1 | |
37 | ||
ecd34a08 | 38 | /* Some implementations of <pthread.h> require this to be defined. */ |
39 | #ifndef _REENTRANT | |
40 | #define _REENTRANT 1 | |
41 | #endif | |
42 | ||
58febf9e | 43 | #include <pthread.h> |
f9f6f55a | 44 | #include <unistd.h> |
58febf9e | 45 | |
46 | typedef pthread_key_t __gthread_key_t; | |
47 | typedef pthread_once_t __gthread_once_t; | |
48 | typedef pthread_mutex_t __gthread_mutex_t; | |
4813f5af | 49 | typedef pthread_mutex_t __gthread_recursive_mutex_t; |
58febf9e | 50 | |
51 | #define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER | |
52 | #define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT | |
4813f5af | 53 | #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER) |
54 | #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER | |
55 | #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) | |
56 | #define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP | |
ff00b6c5 | 57 | #elif defined(PTHREAD_MUTEX_RECURSIVE) |
4813f5af | 58 | #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function |
ff00b6c5 | 59 | #else |
60 | #define __GTHREAD_RECURSIVE_MUTEX_INIT RECURSIVE_ERRORCHECKMUTEX | |
4813f5af | 61 | #endif |
58febf9e | 62 | |
63 | #if SUPPORTS_WEAK && GTHREAD_USE_WEAK | |
64 | ||
6319d58e | 65 | #pragma weak pthread_once |
66 | #pragma weak pthread_key_create | |
67 | #pragma weak pthread_key_delete | |
68 | #pragma weak pthread_getspecific | |
69 | #pragma weak pthread_setspecific | |
70 | #pragma weak pthread_create | |
2f5d30d9 | 71 | |
3cfec666 | 72 | #pragma weak pthread_mutex_lock |
73 | #pragma weak pthread_mutex_trylock | |
74 | #pragma weak pthread_mutex_unlock | |
fcbbb04c | 75 | #pragma weak pthread_mutexattr_init |
76 | #pragma weak pthread_mutexattr_settype | |
77 | #pragma weak pthread_mutexattr_destroy | |
78 | ||
79 | #pragma weak pthread_mutex_init | |
6319d58e | 80 | |
ecd34a08 | 81 | #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) |
7fd957fe | 82 | /* Objective-C. */ |
6319d58e | 83 | #pragma weak pthread_cond_broadcast |
84 | #pragma weak pthread_cond_destroy | |
85 | #pragma weak pthread_cond_init | |
86 | #pragma weak pthread_cond_signal | |
87 | #pragma weak pthread_cond_wait | |
88 | #pragma weak pthread_exit | |
6319d58e | 89 | #pragma weak pthread_mutex_destroy |
90 | #pragma weak pthread_self | |
a55f666d | 91 | #ifdef _POSIX_PRIORITY_SCHEDULING |
f9f6f55a | 92 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
23ab4af6 | 93 | #pragma weak sched_get_priority_max |
94 | #pragma weak sched_get_priority_min | |
f9f6f55a | 95 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
a55f666d | 96 | #endif /* _POSIX_PRIORITY_SCHEDULING */ |
6319d58e | 97 | #pragma weak sched_yield |
92f25da5 | 98 | #pragma weak pthread_attr_destroy |
99 | #pragma weak pthread_attr_init | |
100 | #pragma weak pthread_attr_setdetachstate | |
f9f6f55a | 101 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
92f25da5 | 102 | #pragma weak pthread_getschedparam |
103 | #pragma weak pthread_setschedparam | |
f9f6f55a | 104 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
ecd34a08 | 105 | #endif /* _LIBOBJC || _LIBOBJC_WEAK */ |
58febf9e | 106 | |
58febf9e | 107 | static inline int |
205b5771 | 108 | __gthread_active_p (void) |
58febf9e | 109 | { |
c3e6a7ce | 110 | static void *const __gthread_active_ptr |
111 | = __extension__ (void *) &pthread_create; | |
58febf9e | 112 | return __gthread_active_ptr != 0; |
113 | } | |
114 | ||
115 | #else /* not SUPPORTS_WEAK */ | |
116 | ||
117 | static inline int | |
205b5771 | 118 | __gthread_active_p (void) |
58febf9e | 119 | { |
120 | return 1; | |
121 | } | |
122 | ||
123 | #endif /* SUPPORTS_WEAK */ | |
124 | ||
6319d58e | 125 | #ifdef _LIBOBJC |
126 | ||
53f5af15 | 127 | /* This is the config.h file in libobjc/ */ |
128 | #include <config.h> | |
129 | ||
130 | #ifdef HAVE_SCHED_H | |
131 | # include <sched.h> | |
132 | #endif | |
133 | ||
6319d58e | 134 | /* Key structure for maintaining thread specific storage */ |
135 | static pthread_key_t _objc_thread_storage; | |
eb7dae3a | 136 | static pthread_attr_t _objc_thread_attribs; |
6319d58e | 137 | |
138 | /* Thread local storage for a single thread */ | |
139 | static void *thread_local_storage = NULL; | |
140 | ||
141 | /* Backend initialization functions */ | |
142 | ||
5a54c45e | 143 | /* Initialize the threads subsystem. */ |
6319d58e | 144 | static inline int |
b6546344 | 145 | __gthread_objc_init_thread_system (void) |
6319d58e | 146 | { |
147 | if (__gthread_active_p ()) | |
eb7dae3a | 148 | { |
778ac06a | 149 | /* Initialize the thread storage key. */ |
b6546344 | 150 | if (pthread_key_create (&_objc_thread_storage, NULL) == 0) |
3cfec666 | 151 | { |
152 | /* The normal default detach state for threads is | |
153 | * PTHREAD_CREATE_JOINABLE which causes threads to not die | |
154 | * when you think they should. */ | |
b6546344 | 155 | if (pthread_attr_init (&_objc_thread_attribs) == 0 |
156 | && pthread_attr_setdetachstate (&_objc_thread_attribs, | |
157 | PTHREAD_CREATE_DETACHED) == 0) | |
3cfec666 | 158 | return 0; |
159 | } | |
eb7dae3a | 160 | } |
02cb9619 | 161 | |
162 | return -1; | |
6319d58e | 163 | } |
164 | ||
5a54c45e | 165 | /* Close the threads subsystem. */ |
6319d58e | 166 | static inline int |
b6546344 | 167 | __gthread_objc_close_thread_system (void) |
6319d58e | 168 | { |
eb7dae3a | 169 | if (__gthread_active_p () |
b6546344 | 170 | && pthread_key_delete (_objc_thread_storage) == 0 |
171 | && pthread_attr_destroy (&_objc_thread_attribs) == 0) | |
6319d58e | 172 | return 0; |
eb7dae3a | 173 | |
174 | return -1; | |
6319d58e | 175 | } |
176 | ||
177 | /* Backend thread functions */ | |
178 | ||
5a54c45e | 179 | /* Create a new thread of execution. */ |
6319d58e | 180 | static inline objc_thread_t |
b6546344 | 181 | __gthread_objc_thread_detach (void (*func)(void *), void *arg) |
6319d58e | 182 | { |
183 | objc_thread_t thread_id; | |
184 | pthread_t new_thread_handle; | |
185 | ||
186 | if (!__gthread_active_p ()) | |
187 | return NULL; | |
3cfec666 | 188 | |
b6546344 | 189 | if (!(pthread_create (&new_thread_handle, NULL, (void *) func, arg))) |
05036d9f | 190 | thread_id = (objc_thread_t) new_thread_handle; |
6319d58e | 191 | else |
192 | thread_id = NULL; | |
3cfec666 | 193 | |
6319d58e | 194 | return thread_id; |
195 | } | |
196 | ||
5a54c45e | 197 | /* Set the current thread's priority. */ |
6319d58e | 198 | static inline int |
b6546344 | 199 | __gthread_objc_thread_set_priority (int priority) |
6319d58e | 200 | { |
b6546344 | 201 | if (!__gthread_active_p ()) |
eb7dae3a | 202 | return -1; |
b6546344 | 203 | else |
204 | { | |
a55f666d | 205 | #ifdef _POSIX_PRIORITY_SCHEDULING |
f9f6f55a | 206 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
b6546344 | 207 | pthread_t thread_id = pthread_self (); |
208 | int policy; | |
209 | struct sched_param params; | |
210 | int priority_min, priority_max; | |
3cfec666 | 211 | |
b6546344 | 212 | if (pthread_getschedparam (thread_id, &policy, ¶ms) == 0) |
213 | { | |
214 | if ((priority_max = sched_get_priority_max (policy)) == -1) | |
215 | return -1; | |
216 | ||
217 | if ((priority_min = sched_get_priority_min (policy)) == -1) | |
218 | return -1; | |
3cfec666 | 219 | |
b6546344 | 220 | if (priority > priority_max) |
221 | priority = priority_max; | |
222 | else if (priority < priority_min) | |
223 | priority = priority_min; | |
224 | params.sched_priority = priority; | |
225 | ||
226 | /* | |
227 | * The solaris 7 and several other man pages incorrectly state that | |
228 | * this should be a pointer to policy but pthread.h is universally | |
229 | * at odds with this. | |
230 | */ | |
231 | if (pthread_setschedparam (thread_id, policy, ¶ms) == 0) | |
232 | return 0; | |
233 | } | |
f9f6f55a | 234 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
a55f666d | 235 | #endif /* _POSIX_PRIORITY_SCHEDULING */ |
b6546344 | 236 | return -1; |
237 | } | |
6319d58e | 238 | } |
239 | ||
5a54c45e | 240 | /* Return the current thread's priority. */ |
6319d58e | 241 | static inline int |
b6546344 | 242 | __gthread_objc_thread_get_priority (void) |
6319d58e | 243 | { |
a55f666d | 244 | #ifdef _POSIX_PRIORITY_SCHEDULING |
f9f6f55a | 245 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
6319d58e | 246 | if (__gthread_active_p ()) |
eb7dae3a | 247 | { |
248 | int policy; | |
249 | struct sched_param params; | |
250 | ||
b6546344 | 251 | if (pthread_getschedparam (pthread_self (), &policy, ¶ms) == 0) |
3cfec666 | 252 | return params.sched_priority; |
eb7dae3a | 253 | else |
3cfec666 | 254 | return -1; |
eb7dae3a | 255 | } |
6319d58e | 256 | else |
f9f6f55a | 257 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
a55f666d | 258 | #endif /* _POSIX_PRIORITY_SCHEDULING */ |
6319d58e | 259 | return OBJC_THREAD_INTERACTIVE_PRIORITY; |
260 | } | |
261 | ||
5a54c45e | 262 | /* Yield our process time to another thread. */ |
6319d58e | 263 | static inline void |
b6546344 | 264 | __gthread_objc_thread_yield (void) |
6319d58e | 265 | { |
266 | if (__gthread_active_p ()) | |
b6546344 | 267 | sched_yield (); |
6319d58e | 268 | } |
269 | ||
5a54c45e | 270 | /* Terminate the current thread. */ |
6319d58e | 271 | static inline int |
b6546344 | 272 | __gthread_objc_thread_exit (void) |
6319d58e | 273 | { |
274 | if (__gthread_active_p ()) | |
275 | /* exit the thread */ | |
b6546344 | 276 | pthread_exit (&__objc_thread_exit_status); |
6319d58e | 277 | |
278 | /* Failed if we reached here */ | |
279 | return -1; | |
280 | } | |
281 | ||
5a54c45e | 282 | /* Returns an integer value which uniquely describes a thread. */ |
6319d58e | 283 | static inline objc_thread_t |
b6546344 | 284 | __gthread_objc_thread_id (void) |
6319d58e | 285 | { |
286 | if (__gthread_active_p ()) | |
b6546344 | 287 | return (objc_thread_t) pthread_self (); |
6319d58e | 288 | else |
05036d9f | 289 | return (objc_thread_t) 1; |
6319d58e | 290 | } |
291 | ||
5a54c45e | 292 | /* Sets the thread's local storage pointer. */ |
6319d58e | 293 | static inline int |
b6546344 | 294 | __gthread_objc_thread_set_data (void *value) |
6319d58e | 295 | { |
296 | if (__gthread_active_p ()) | |
b6546344 | 297 | return pthread_setspecific (_objc_thread_storage, value); |
6319d58e | 298 | else |
299 | { | |
300 | thread_local_storage = value; | |
301 | return 0; | |
302 | } | |
303 | } | |
304 | ||
5a54c45e | 305 | /* Returns the thread's local storage pointer. */ |
6319d58e | 306 | static inline void * |
b6546344 | 307 | __gthread_objc_thread_get_data (void) |
6319d58e | 308 | { |
309 | if (__gthread_active_p ()) | |
b6546344 | 310 | return pthread_getspecific (_objc_thread_storage); |
6319d58e | 311 | else |
312 | return thread_local_storage; | |
313 | } | |
314 | ||
315 | /* Backend mutex functions */ | |
316 | ||
5a54c45e | 317 | /* Allocate a mutex. */ |
6319d58e | 318 | static inline int |
b6546344 | 319 | __gthread_objc_mutex_allocate (objc_mutex_t mutex) |
6319d58e | 320 | { |
321 | if (__gthread_active_p ()) | |
322 | { | |
b6546344 | 323 | mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); |
6319d58e | 324 | |
b6546344 | 325 | if (pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL)) |
6319d58e | 326 | { |
b6546344 | 327 | objc_free (mutex->backend); |
6319d58e | 328 | mutex->backend = NULL; |
329 | return -1; | |
330 | } | |
331 | } | |
332 | ||
333 | return 0; | |
334 | } | |
335 | ||
5a54c45e | 336 | /* Deallocate a mutex. */ |
6319d58e | 337 | static inline int |
b6546344 | 338 | __gthread_objc_mutex_deallocate (objc_mutex_t mutex) |
6319d58e | 339 | { |
340 | if (__gthread_active_p ()) | |
341 | { | |
342 | int count; | |
343 | ||
344 | /* | |
345 | * Posix Threads specifically require that the thread be unlocked | |
346 | * for pthread_mutex_destroy to work. | |
347 | */ | |
348 | ||
349 | do | |
350 | { | |
b6546344 | 351 | count = pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend); |
6319d58e | 352 | if (count < 0) |
353 | return -1; | |
354 | } | |
355 | while (count); | |
356 | ||
b6546344 | 357 | if (pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend)) |
6319d58e | 358 | return -1; |
359 | ||
b6546344 | 360 | objc_free (mutex->backend); |
6319d58e | 361 | mutex->backend = NULL; |
362 | } | |
363 | return 0; | |
364 | } | |
365 | ||
5a54c45e | 366 | /* Grab a lock on a mutex. */ |
6319d58e | 367 | static inline int |
b6546344 | 368 | __gthread_objc_mutex_lock (objc_mutex_t mutex) |
6319d58e | 369 | { |
3cfec666 | 370 | if (__gthread_active_p () |
b6546344 | 371 | && pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0) |
273f030c | 372 | { |
373 | return -1; | |
374 | } | |
375 | ||
376 | return 0; | |
6319d58e | 377 | } |
378 | ||
5a54c45e | 379 | /* Try to grab a lock on a mutex. */ |
6319d58e | 380 | static inline int |
b6546344 | 381 | __gthread_objc_mutex_trylock (objc_mutex_t mutex) |
6319d58e | 382 | { |
3cfec666 | 383 | if (__gthread_active_p () |
b6546344 | 384 | && pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0) |
273f030c | 385 | { |
386 | return -1; | |
387 | } | |
388 | ||
389 | return 0; | |
6319d58e | 390 | } |
391 | ||
392 | /* Unlock the mutex */ | |
393 | static inline int | |
b6546344 | 394 | __gthread_objc_mutex_unlock (objc_mutex_t mutex) |
6319d58e | 395 | { |
3cfec666 | 396 | if (__gthread_active_p () |
b6546344 | 397 | && pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0) |
273f030c | 398 | { |
399 | return -1; | |
400 | } | |
401 | ||
402 | return 0; | |
6319d58e | 403 | } |
404 | ||
405 | /* Backend condition mutex functions */ | |
406 | ||
5a54c45e | 407 | /* Allocate a condition. */ |
6319d58e | 408 | static inline int |
b6546344 | 409 | __gthread_objc_condition_allocate (objc_condition_t condition) |
6319d58e | 410 | { |
411 | if (__gthread_active_p ()) | |
412 | { | |
b6546344 | 413 | condition->backend = objc_malloc (sizeof (pthread_cond_t)); |
6319d58e | 414 | |
b6546344 | 415 | if (pthread_cond_init ((pthread_cond_t *) condition->backend, NULL)) |
6319d58e | 416 | { |
b6546344 | 417 | objc_free (condition->backend); |
6319d58e | 418 | condition->backend = NULL; |
419 | return -1; | |
420 | } | |
421 | } | |
422 | ||
423 | return 0; | |
424 | } | |
425 | ||
5a54c45e | 426 | /* Deallocate a condition. */ |
6319d58e | 427 | static inline int |
b6546344 | 428 | __gthread_objc_condition_deallocate (objc_condition_t condition) |
6319d58e | 429 | { |
430 | if (__gthread_active_p ()) | |
431 | { | |
b6546344 | 432 | if (pthread_cond_destroy ((pthread_cond_t *) condition->backend)) |
6319d58e | 433 | return -1; |
434 | ||
b6546344 | 435 | objc_free (condition->backend); |
6319d58e | 436 | condition->backend = NULL; |
437 | } | |
438 | return 0; | |
439 | } | |
440 | ||
441 | /* Wait on the condition */ | |
442 | static inline int | |
b6546344 | 443 | __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) |
6319d58e | 444 | { |
445 | if (__gthread_active_p ()) | |
b6546344 | 446 | return pthread_cond_wait ((pthread_cond_t *) condition->backend, |
447 | (pthread_mutex_t *) mutex->backend); | |
6319d58e | 448 | else |
449 | return 0; | |
450 | } | |
451 | ||
5a54c45e | 452 | /* Wake up all threads waiting on this condition. */ |
6319d58e | 453 | static inline int |
b6546344 | 454 | __gthread_objc_condition_broadcast (objc_condition_t condition) |
6319d58e | 455 | { |
456 | if (__gthread_active_p ()) | |
b6546344 | 457 | return pthread_cond_broadcast ((pthread_cond_t *) condition->backend); |
6319d58e | 458 | else |
459 | return 0; | |
460 | } | |
461 | ||
5a54c45e | 462 | /* Wake up one thread waiting on this condition. */ |
6319d58e | 463 | static inline int |
b6546344 | 464 | __gthread_objc_condition_signal (objc_condition_t condition) |
6319d58e | 465 | { |
466 | if (__gthread_active_p ()) | |
b6546344 | 467 | return pthread_cond_signal ((pthread_cond_t *) condition->backend); |
6319d58e | 468 | else |
469 | return 0; | |
470 | } | |
471 | ||
472 | #else /* _LIBOBJC */ | |
473 | ||
58febf9e | 474 | static inline int |
205b5771 | 475 | __gthread_once (__gthread_once_t *once, void (*func) (void)) |
58febf9e | 476 | { |
477 | if (__gthread_active_p ()) | |
478 | return pthread_once (once, func); | |
479 | else | |
480 | return -1; | |
481 | } | |
482 | ||
483 | static inline int | |
484 | __gthread_key_create (__gthread_key_t *key, void (*dtor) (void *)) | |
485 | { | |
486 | return pthread_key_create (key, dtor); | |
487 | } | |
488 | ||
58febf9e | 489 | static inline int |
490 | __gthread_key_delete (__gthread_key_t key) | |
491 | { | |
492 | return pthread_key_delete (key); | |
493 | } | |
494 | ||
495 | static inline void * | |
496 | __gthread_getspecific (__gthread_key_t key) | |
497 | { | |
498 | return pthread_getspecific (key); | |
499 | } | |
500 | ||
501 | static inline int | |
502 | __gthread_setspecific (__gthread_key_t key, const void *ptr) | |
503 | { | |
504 | return pthread_setspecific (key, ptr); | |
505 | } | |
506 | ||
507 | static inline int | |
508 | __gthread_mutex_lock (__gthread_mutex_t *mutex) | |
509 | { | |
510 | if (__gthread_active_p ()) | |
511 | return pthread_mutex_lock (mutex); | |
512 | else | |
513 | return 0; | |
514 | } | |
515 | ||
516 | static inline int | |
517 | __gthread_mutex_trylock (__gthread_mutex_t *mutex) | |
518 | { | |
519 | if (__gthread_active_p ()) | |
520 | return pthread_mutex_trylock (mutex); | |
521 | else | |
522 | return 0; | |
523 | } | |
524 | ||
525 | static inline int | |
526 | __gthread_mutex_unlock (__gthread_mutex_t *mutex) | |
527 | { | |
528 | if (__gthread_active_p ()) | |
529 | return pthread_mutex_unlock (mutex); | |
530 | else | |
531 | return 0; | |
532 | } | |
533 | ||
ff00b6c5 | 534 | #if !defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_MUTEX_RECURSIVE) |
4813f5af | 535 | static inline int |
536 | __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) | |
537 | { | |
538 | if (__gthread_active_p ()) | |
539 | { | |
540 | pthread_mutexattr_t attr; | |
541 | int r; | |
542 | ||
543 | r = pthread_mutexattr_init (&attr); | |
544 | if (!r) | |
545 | r = pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); | |
546 | if (!r) | |
547 | r = pthread_mutex_init (mutex, &attr); | |
548 | if (!r) | |
549 | r = pthread_mutexattr_destroy (&attr); | |
550 | return r; | |
551 | } | |
552 | } | |
553 | #endif | |
554 | ||
555 | static inline int | |
556 | __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) | |
557 | { | |
558 | return __gthread_mutex_lock (mutex); | |
559 | } | |
560 | ||
561 | static inline int | |
562 | __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) | |
563 | { | |
564 | return __gthread_mutex_trylock (mutex); | |
565 | } | |
566 | ||
567 | static inline int | |
568 | __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) | |
569 | { | |
570 | return __gthread_mutex_unlock (mutex); | |
571 | } | |
572 | ||
6319d58e | 573 | #endif /* _LIBOBJC */ |
574 | ||
2a281353 | 575 | #endif /* ! GCC_GTHR_POSIX_H */ |