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