1 /* libc-internal interface for mutex locks. NPTL version. 2 Copyright (C) 1996-2003, 2005, 2007 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public License as 7 published by the Free Software Foundation; either version 2.1 of the 8 License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; see the file COPYING.LIB. If not, 17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18 Boston, MA 02111-1307, USA. */ 19 20 #ifndef _BITS_LIBC_LOCK_H 21 #define _BITS_LIBC_LOCK_H 1 22 23 #include <pthread.h> 24 #define __need_NULL 25 #include <stddef.h> 26 27 28 /* Fortunately Linux now has a mean to do locking which is realtime 29 safe without the aid of the thread library. We also need no fancy 30 options like error checking mutexes etc. We only need simple 31 locks, maybe recursive. This can be easily and cheaply implemented 32 using futexes. We will use them everywhere except in ld.so since 33 ld.so might be used on old kernels with a different libc.so. */ 34 #ifdef _LIBC 35 # include <lowlevellock.h> 36 # include <tls.h> 37 # include <pthread-functions.h> 38 #endif 39 40 /* Mutex type. */ 41 #if defined _LIBC || defined _IO_MTSAFE_IO 42 # if (defined NOT_IN_libc && !defined IS_IN_libpthread) || !defined _LIBC 43 typedef pthread_mutex_t __libc_lock_t; 44 typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; 45 # else 46 typedef int __libc_lock_t; 47 typedef struct { int lock; int cnt; void *owner; } __libc_lock_recursive_t; 48 # endif 49 typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t; 50 # ifdef __USE_UNIX98 51 typedef pthread_rwlock_t __libc_rwlock_t; 52 # else 53 typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; 54 # endif 55 #else 56 typedef struct __libc_lock_opaque__ __libc_lock_t; 57 typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; 58 typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; 59 #endif 60 61 /* Type for key to thread-specific data. */ 62 typedef pthread_key_t __libc_key_t; 63 64 /* Define a lock variable NAME with storage class CLASS. The lock must be 65 initialized with __libc_lock_init before it can be used (or define it 66 with __libc_lock_define_initialized, below). Use `extern' for CLASS to 67 declare a lock defined in another module. In public structure 68 definitions you must use a pointer to the lock structure (i.e., NAME 69 begins with a `*'), because its storage size will not be known outside 70 of libc. */ 71 #define __libc_lock_define(CLASS,NAME) \ 72 CLASS __libc_lock_t NAME; 73 #define __libc_rwlock_define(CLASS,NAME) \ 74 CLASS __libc_rwlock_t NAME; 75 #define __libc_lock_define_recursive(CLASS,NAME) \ 76 CLASS __libc_lock_recursive_t NAME; 77 #define __rtld_lock_define_recursive(CLASS,NAME) \ 78 CLASS __rtld_lock_recursive_t NAME; 79 80 /* Define an initialized lock variable NAME with storage class CLASS. 81 82 For the C library we take a deeper look at the initializer. For 83 this implementation all fields are initialized to zero. Therefore 84 we don't initialize the variable which allows putting it into the 85 BSS section. (Except on PA-RISC and other odd architectures, where 86 initialized locks must be set to one due to the lack of normal 87 atomic operations.) */ 88 89 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 90 # if LLL_LOCK_INITIALIZER == 0 91 # define __libc_lock_define_initialized(CLASS,NAME) \ 92 CLASS __libc_lock_t NAME; 93 # else 94 # define __libc_lock_define_initialized(CLASS,NAME) \ 95 CLASS __libc_lock_t NAME = LLL_LOCK_INITIALIZER; 96 # endif 97 #else 98 # if __LT_SPINLOCK_INIT == 0 99 # define __libc_lock_define_initialized(CLASS,NAME) \ 100 CLASS __libc_lock_t NAME; 101 # else 102 # define __libc_lock_define_initialized(CLASS,NAME) \ 103 CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; 104 # endif 105 #endif 106 107 #define __libc_rwlock_define_initialized(CLASS,NAME) \ 108 CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; 109 110 /* Define an initialized recursive lock variable NAME with storage 111 class CLASS. */ 112 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 113 # if LLL_LOCK_INITIALIZER == 0 114 # define __libc_lock_define_initialized_recursive(CLASS,NAME) \ 115 CLASS __libc_lock_recursive_t NAME; 116 # else 117 # define __libc_lock_define_initialized_recursive(CLASS,NAME) \ 118 CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; 119 # endif 120 # define _LIBC_LOCK_RECURSIVE_INITIALIZER \ 121 { LLL_LOCK_INITIALIZER, 0, NULL } 122 #else 123 # define __libc_lock_define_initialized_recursive(CLASS,NAME) \ 124 CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; 125 # define _LIBC_LOCK_RECURSIVE_INITIALIZER \ 126 {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} 127 #endif 128 129 #define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ 130 CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; 131 #define _RTLD_LOCK_RECURSIVE_INITIALIZER \ 132 {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} 133 134 #define __rtld_lock_initialize(NAME) \ 135 (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER) 136 137 /* If we check for a weakly referenced symbol and then perform a 138 normal jump to it te code generated for some platforms in case of 139 PIC is unnecessarily slow. What would happen is that the function 140 is first referenced as data and then it is called indirectly 141 through the PLT. We can make this a direct jump. */ 142 #ifdef __PIC__ 143 # define __libc_maybe_call(FUNC, ARGS, ELSE) \ 144 (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ 145 _fn != NULL ? (*_fn) ARGS : ELSE; })) 146 #else 147 # define __libc_maybe_call(FUNC, ARGS, ELSE) \ 148 (FUNC != NULL ? FUNC ARGS : ELSE) 149 #endif 150 151 /* Call thread functions through the function pointer table. */ 152 #if defined SHARED && !defined NOT_IN_libc 153 # define PTFAVAIL(NAME) __libc_pthread_functions_init 154 # define __libc_ptf_call(FUNC, ARGS, ELSE) \ 155 (__libc_pthread_functions_init ? PTHFCT_CALL (ptr_##FUNC, ARGS) : ELSE) 156 # define __libc_ptf_call_always(FUNC, ARGS) \ 157 PTHFCT_CALL (ptr_##FUNC, ARGS) 158 #else 159 # define PTFAVAIL(NAME) (NAME != NULL) 160 # define __libc_ptf_call(FUNC, ARGS, ELSE) \ 161 __libc_maybe_call (FUNC, ARGS, ELSE) 162 # define __libc_ptf_call_always(FUNC, ARGS) \ 163 FUNC ARGS 164 #endif 165 166 167 /* Initialize the named lock variable, leaving it in a consistent, unlocked 168 state. */ 169 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 170 # define __libc_lock_init(NAME) ((NAME) = LLL_LOCK_INITIALIZER, 0) 171 #else 172 # define __libc_lock_init(NAME) \ 173 __libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0) 174 #endif 175 #if defined SHARED && !defined NOT_IN_libc 176 /* ((NAME) = (__libc_rwlock_t) PTHREAD_RWLOCK_INITIALIZER, 0) is 177 inefficient. */ 178 # define __libc_rwlock_init(NAME) \ 179 (__builtin_memset (&(NAME), '\0', sizeof (NAME)), 0) 180 #else 181 # define __libc_rwlock_init(NAME) \ 182 __libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0) 183 #endif 184 185 /* Same as last but this time we initialize a recursive mutex. */ 186 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 187 # define __libc_lock_init_recursive(NAME) \ 188 ((NAME) = (__libc_lock_recursive_t) _LIBC_LOCK_RECURSIVE_INITIALIZER, 0) 189 #else 190 # define __libc_lock_init_recursive(NAME) \ 191 do { \ 192 if (__pthread_mutex_init != NULL) \ 193 { \ 194 pthread_mutexattr_t __attr; \ 195 __pthread_mutexattr_init (&__attr); \ 196 __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ 197 __pthread_mutex_init (&(NAME).mutex, &__attr); \ 198 __pthread_mutexattr_destroy (&__attr); \ 199 } \ 200 } while (0) 201 #endif 202 203 #define __rtld_lock_init_recursive(NAME) \ 204 do { \ 205 if (__pthread_mutex_init != NULL) \ 206 { \ 207 pthread_mutexattr_t __attr; \ 208 __pthread_mutexattr_init (&__attr); \ 209 __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ 210 __pthread_mutex_init (&(NAME).mutex, &__attr); \ 211 __pthread_mutexattr_destroy (&__attr); \ 212 } \ 213 } while (0) 214 215 /* Finalize the named lock variable, which must be locked. It cannot be 216 used again until __libc_lock_init is called again on it. This must be 217 called on a lock variable before the containing storage is reused. */ 218 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 219 # define __libc_lock_fini(NAME) ((void) 0) 220 #else 221 # define __libc_lock_fini(NAME) \ 222 __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0) 223 #endif 224 #if defined SHARED && !defined NOT_IN_libc 225 # define __libc_rwlock_fini(NAME) ((void) 0) 226 #else 227 # define __libc_rwlock_fini(NAME) \ 228 __libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0) 229 #endif 230 231 /* Finalize recursive named lock. */ 232 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 233 # define __libc_lock_fini_recursive(NAME) ((void) 0) 234 #else 235 # define __libc_lock_fini_recursive(NAME) \ 236 __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0) 237 #endif 238 239 /* Lock the named lock variable. */ 240 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 241 # define __libc_lock_lock(NAME) \ 242 ({ lll_lock (NAME, LLL_PRIVATE); 0; }) 243 #else 244 # define __libc_lock_lock(NAME) \ 245 __libc_maybe_call (__pthread_mutex_lock, (&(NAME)), 0) 246 #endif 247 #define __libc_rwlock_rdlock(NAME) \ 248 __libc_ptf_call (__pthread_rwlock_rdlock, (&(NAME)), 0) 249 #define __libc_rwlock_wrlock(NAME) \ 250 __libc_ptf_call (__pthread_rwlock_wrlock, (&(NAME)), 0) 251 252 /* Lock the recursive named lock variable. */ 253 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 254 # define __libc_lock_lock_recursive(NAME) \ 255 do { \ 256 void *self = THREAD_SELF; \ 257 if ((NAME).owner != self) \ 258 { \ 259 lll_lock ((NAME).lock, LLL_PRIVATE); \ 260 (NAME).owner = self; \ 261 } \ 262 ++(NAME).cnt; \ 263 } while (0) 264 #else 265 # define __libc_lock_lock_recursive(NAME) \ 266 __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) 267 #endif 268 269 /* Try to lock the named lock variable. */ 270 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 271 # define __libc_lock_trylock(NAME) \ 272 lll_trylock (NAME) 273 #else 274 # define __libc_lock_trylock(NAME) \ 275 __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0) 276 #endif 277 #define __libc_rwlock_tryrdlock(NAME) \ 278 __libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0) 279 #define __libc_rwlock_trywrlock(NAME) \ 280 __libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0) 281 282 /* Try to lock the recursive named lock variable. */ 283 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 284 # define __libc_lock_trylock_recursive(NAME) \ 285 ({ \ 286 int result = 0; \ 287 void *self = THREAD_SELF; \ 288 if ((NAME).owner != self) \ 289 { \ 290 if (lll_trylock ((NAME).lock) == 0) \ 291 { \ 292 (NAME).owner = self; \ 293 (NAME).cnt = 1; \ 294 } \ 295 else \ 296 result = EBUSY; \ 297 } \ 298 else \ 299 ++(NAME).cnt; \ 300 result; \ 301 }) 302 #else 303 # define __libc_lock_trylock_recursive(NAME) \ 304 __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0) 305 #endif 306 307 #define __rtld_lock_trylock_recursive(NAME) \ 308 __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0) 309 310 /* Unlock the named lock variable. */ 311 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 312 # define __libc_lock_unlock(NAME) \ 313 lll_unlock (NAME, LLL_PRIVATE) 314 #else 315 # define __libc_lock_unlock(NAME) \ 316 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) 317 #endif 318 #define __libc_rwlock_unlock(NAME) \ 319 __libc_ptf_call (__pthread_rwlock_unlock, (&(NAME)), 0) 320 321 /* Unlock the recursive named lock variable. */ 322 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) 323 /* We do no error checking here. */ 324 # define __libc_lock_unlock_recursive(NAME) \ 325 do { \ 326 if (--(NAME).cnt == 0) \ 327 { \ 328 (NAME).owner = NULL; \ 329 lll_unlock ((NAME).lock, LLL_PRIVATE); \ 330 } \ 331 } while (0) 332 #else 333 # define __libc_lock_unlock_recursive(NAME) \ 334 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) 335 #endif 336 337 #if defined _LIBC && defined SHARED 338 # define __rtld_lock_default_lock_recursive(lock) \ 339 ++((pthread_mutex_t *)(lock))->__data.__count; 340 341 # define __rtld_lock_default_unlock_recursive(lock) \ 342 --((pthread_mutex_t *)(lock))->__data.__count; 343 344 # define __rtld_lock_lock_recursive(NAME) \ 345 GL(dl_rtld_lock_recursive) (&(NAME).mutex) 346 347 # define __rtld_lock_unlock_recursive(NAME) \ 348 GL(dl_rtld_unlock_recursive) (&(NAME).mutex) 349 #else 350 # define __rtld_lock_lock_recursive(NAME) \ 351 __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) 352 353 # define __rtld_lock_unlock_recursive(NAME) \ 354 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) 355 #endif 356 357 /* Define once control variable. */ 358 #if PTHREAD_ONCE_INIT == 0 359 /* Special case for static variables where we can avoid the initialization 360 if it is zero. */ 361 # define __libc_once_define(CLASS, NAME) \ 362 CLASS pthread_once_t NAME 363 #else 364 # define __libc_once_define(CLASS, NAME) \ 365 CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT 366 #endif 367 368 /* Call handler iff the first call. */ 369 #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ 370 do { \ 371 if (PTFAVAIL (__pthread_once)) \ 372 __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL), \ 373 INIT_FUNCTION)); \ 374 else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ 375 INIT_FUNCTION (); \ 376 (ONCE_CONTROL) |= 2; \ 377 } \ 378 } while (0) 379 380 381 /* Note that for I/O cleanup handling we are using the old-style 382 cancel handling. It does not have to be integrated with C++ snce 383 no C++ code is called in the middle. The old-style handling is 384 faster and the support is not going away. */ 385 extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, 386 void (*routine) (void *), void *arg); 387 extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, 388 int execute); 389 extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, 390 void (*routine) (void *), void *arg); 391 extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, 392 int execute); 393 394 /* Start critical region with cleanup. */ 395 #define __libc_cleanup_region_start(DOIT, FCT, ARG) \ 396 { struct _pthread_cleanup_buffer _buffer; \ 397 int _avail; \ 398 if (DOIT) { \ 399 _avail = PTFAVAIL (_pthread_cleanup_push_defer); \ 400 if (_avail) { \ 401 __libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT, \ 402 ARG)); \ 403 } else { \ 404 _buffer.__routine = (FCT); \ 405 _buffer.__arg = (ARG); \ 406 } \ 407 } else { \ 408 _avail = 0; \ 409 } 410 411 /* End critical region with cleanup. */ 412 #define __libc_cleanup_region_end(DOIT) \ 413 if (_avail) { \ 414 __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ 415 } else if (DOIT) \ 416 _buffer.__routine (_buffer.__arg); \ 417 } 418 419 /* Sometimes we have to exit the block in the middle. */ 420 #define __libc_cleanup_end(DOIT) \ 421 if (_avail) { \ 422 __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ 423 } else if (DOIT) \ 424 _buffer.__routine (_buffer.__arg) 425 426 427 /* Normal cleanup handling, based on C cleanup attribute. */ 428 __extern_inline void 429 __libc_cleanup_routine (struct __pthread_cleanup_frame *f) 430 { 431 if (f->__do_it) 432 f->__cancel_routine (f->__cancel_arg); 433 } 434 435 #define __libc_cleanup_push(fct, arg) \ 436 do { \ 437 struct __pthread_cleanup_frame __clframe \ 438 __attribute__ ((__cleanup__ (__libc_cleanup_routine))) \ 439 = { .__cancel_routine = (fct), .__cancel_arg = (arg), \ 440 .__do_it = 1 }; 441 442 #define __libc_cleanup_pop(execute) \ 443 __clframe.__do_it = (execute); \ 444 } while (0) 445 446 447 /* Create thread-specific key. */ 448 #define __libc_key_create(KEY, DESTRUCTOR) \ 449 __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1) 450 451 /* Get thread-specific data. */ 452 #define __libc_getspecific(KEY) \ 453 __libc_ptf_call (__pthread_getspecific, (KEY), NULL) 454 455 /* Set thread-specific data. */ 456 #define __libc_setspecific(KEY, VALUE) \ 457 __libc_ptf_call (__pthread_setspecific, (KEY, VALUE), 0) 458 459 460 /* Register handlers to execute before and after `fork'. Note that the 461 last parameter is NULL. The handlers registered by the libc are 462 never removed so this is OK. */ 463 #define __libc_atfork(PREPARE, PARENT, CHILD) \ 464 __register_atfork (PREPARE, PARENT, CHILD, NULL) 465 extern int __register_atfork (void (*__prepare) (void), 466 void (*__parent) (void), 467 void (*__child) (void), 468 void *__dso_handle); 469 470 /* Functions that are used by this file and are internal to the GNU C 471 library. */ 472 473 extern int __pthread_mutex_init (pthread_mutex_t *__mutex, 474 __const pthread_mutexattr_t *__mutex_attr); 475 476 extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); 477 478 extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); 479 480 extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); 481 482 extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); 483 484 extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); 485 486 extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); 487 488 extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, 489 int __kind); 490 491 #ifdef __USE_UNIX98 492 extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, 493 __const pthread_rwlockattr_t *__attr); 494 495 extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); 496 497 extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); 498 499 extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); 500 501 extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); 502 503 extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); 504 505 extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); 506 #endif 507 508 extern int __pthread_key_create (pthread_key_t *__key, 509 void (*__destr_function) (void *)); 510 511 extern int __pthread_setspecific (pthread_key_t __key, 512 __const void *__pointer); 513 514 extern void *__pthread_getspecific (pthread_key_t __key); 515 516 extern int __pthread_once (pthread_once_t *__once_control, 517 void (*__init_routine) (void)); 518 519 extern int __pthread_atfork (void (*__prepare) (void), 520 void (*__parent) (void), 521 void (*__child) (void)); 522 523 524 525 /* Make the pthread functions weak so that we can elide them from 526 single-threaded processes. */ 527 #ifndef __NO_WEAK_PTHREAD_ALIASES 528 # ifdef weak_extern 529 # if _LIBC 530 # include <bp-sym.h> 531 # else 532 # define BP_SYM (sym) sym 533 # endif 534 weak_extern (BP_SYM (__pthread_mutex_init)) 535 weak_extern (BP_SYM (__pthread_mutex_destroy)) 536 weak_extern (BP_SYM (__pthread_mutex_lock)) 537 weak_extern (BP_SYM (__pthread_mutex_trylock)) 538 weak_extern (BP_SYM (__pthread_mutex_unlock)) 539 weak_extern (BP_SYM (__pthread_mutexattr_init)) 540 weak_extern (BP_SYM (__pthread_mutexattr_destroy)) 541 weak_extern (BP_SYM (__pthread_mutexattr_settype)) 542 weak_extern (BP_SYM (__pthread_rwlock_init)) 543 weak_extern (BP_SYM (__pthread_rwlock_destroy)) 544 weak_extern (BP_SYM (__pthread_rwlock_rdlock)) 545 weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) 546 weak_extern (BP_SYM (__pthread_rwlock_wrlock)) 547 weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) 548 weak_extern (BP_SYM (__pthread_rwlock_unlock)) 549 weak_extern (BP_SYM (__pthread_key_create)) 550 weak_extern (BP_SYM (__pthread_setspecific)) 551 weak_extern (BP_SYM (__pthread_getspecific)) 552 weak_extern (BP_SYM (__pthread_once)) 553 weak_extern (__pthread_initialize) 554 weak_extern (__pthread_atfork) 555 weak_extern (BP_SYM (_pthread_cleanup_push_defer)) 556 weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) 557 weak_extern (BP_SYM (pthread_setcancelstate)) 558 # else 559 # pragma weak __pthread_mutex_init 560 # pragma weak __pthread_mutex_destroy 561 # pragma weak __pthread_mutex_lock 562 # pragma weak __pthread_mutex_trylock 563 # pragma weak __pthread_mutex_unlock 564 # pragma weak __pthread_mutexattr_init 565 # pragma weak __pthread_mutexattr_destroy 566 # pragma weak __pthread_mutexattr_settype 567 # pragma weak __pthread_rwlock_destroy 568 # pragma weak __pthread_rwlock_rdlock 569 # pragma weak __pthread_rwlock_tryrdlock 570 # pragma weak __pthread_rwlock_wrlock 571 # pragma weak __pthread_rwlock_trywrlock 572 # pragma weak __pthread_rwlock_unlock 573 # pragma weak __pthread_key_create 574 # pragma weak __pthread_setspecific 575 # pragma weak __pthread_getspecific 576 # pragma weak __pthread_once 577 # pragma weak __pthread_initialize 578 # pragma weak __pthread_atfork 579 # pragma weak _pthread_cleanup_push_defer 580 # pragma weak _pthread_cleanup_pop_restore 581 # pragma weak pthread_setcancelstate 582 # endif 583 #endif 584 585 #endif /* bits/libc-lock.h */ 586