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.
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.
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.
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. */
20 #ifndef _BITS_LIBC_LOCK_H
21 #define _BITS_LIBC_LOCK_H 1
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. */
35 # include <lowlevellock.h>
37 # include <pthread-functions.h>
38 # include <errno.h> /* For EBUSY. */
39 # include <gnu/option-groups.h> /* For __OPTION_EGLIBC_BIG_MACROS. */
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;
48 typedef int __libc_lock_t;
49 typedef struct { int lock; int cnt; void *owner; } __libc_lock_recursive_t;
51 typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t;
53 typedef pthread_rwlock_t __libc_rwlock_t;
55 typedef struct __libc_rwlock_opaque__ __libc_rwlock_t;
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;
63 /* Type for key to thread-specific data. */
64 typedef pthread_key_t __libc_key_t;
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
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;
82 /* Define an initialized lock variable NAME with storage class CLASS.
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.) */
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;
96 # define __libc_lock_define_initialized(CLASS,NAME) \
97 CLASS __libc_lock_t NAME = LLL_LOCK_INITIALIZER;
100 # if __LT_SPINLOCK_INIT == 0
101 # define __libc_lock_define_initialized(CLASS,NAME) \
102 CLASS __libc_lock_t NAME;
104 # define __libc_lock_define_initialized(CLASS,NAME) \
105 CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER;
109 #define __libc_rwlock_define_initialized(CLASS,NAME) \
110 CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
112 /* Define an initialized recursive lock variable NAME with storage
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;
119 # define __libc_lock_define_initialized_recursive(CLASS,NAME) \
120 CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER;
122 # define _LIBC_LOCK_RECURSIVE_INITIALIZER \
123 { LLL_LOCK_INITIALIZER, 0, NULL }
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}
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}
136 #define __rtld_lock_initialize(NAME) \
137 (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER)
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. */
145 # define __libc_maybe_call(FUNC, ARGS, ELSE) \
146 (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
147 _fn != NULL ? (*_fn) ARGS : ELSE; }))
149 # define __libc_maybe_call(FUNC, ARGS, ELSE) \
150 (FUNC != NULL ? FUNC ARGS : ELSE)
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)
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) \
169 /* Initialize the named lock variable, leaving it in a consistent, unlocked
171 #if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread)
172 # define __libc_lock_init(NAME) ((NAME) = LLL_LOCK_INITIALIZER, 0)
174 # define __libc_lock_init(NAME) \
175 __libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0)
177 #if defined SHARED && !defined NOT_IN_libc
178 /* ((NAME) = (__libc_rwlock_t) PTHREAD_RWLOCK_INITIALIZER, 0) is
180 # define __libc_rwlock_init(NAME) \
181 (__builtin_memset (&(NAME), '\0', sizeof (NAME)), 0)
183 # define __libc_rwlock_init(NAME) \
184 __libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)
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)
192 # define __libc_lock_init_recursive(NAME) \
194 if (__pthread_mutex_init != NULL) \
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); \
205 #define __rtld_lock_init_recursive(NAME) \
207 if (__pthread_mutex_init != NULL) \
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); \
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)
223 # define __libc_lock_fini(NAME) \
224 __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0)
226 #if defined SHARED && !defined NOT_IN_libc
227 # define __libc_rwlock_fini(NAME) ((void) 0)
229 # define __libc_rwlock_fini(NAME) \
230 __libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)
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)
237 # define __libc_lock_fini_recursive(NAME) \
238 __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0)
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; })
254 # define __libc_lock_lock(NAME) \
255 __libc_lock_lock_fn (&(NAME))
256 # endif /* __OPTION_EGLIBC_BIG_MACROS */
258 # define __libc_lock_lock(NAME) \
259 __libc_maybe_call (__pthread_mutex_lock, (&(NAME)), 0)
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)
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) \
278 void *self = THREAD_SELF; \
279 if ((NAME).owner != self) \
281 lll_lock ((NAME).lock, LLL_PRIVATE); \
282 (NAME).owner = self; \
287 # define __libc_lock_lock_recursive(NAME) \
288 __libc_lock_lock_recursive_fn (&(NAME))
289 # endif /* __OPTION_EGLIBC_BIG_MACROS */
291 # define __libc_lock_lock_recursive(NAME) \
292 __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0)
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) \
308 # define __libc_lock_trylock(NAME) \
309 __libc_lock_trylock_fn (&(NAME))
310 # endif /* __OPTION_EGLIBC_BIG_MACROS */
312 # define __libc_lock_trylock(NAME) \
313 __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0)
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)
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) \
333 void *self = THREAD_SELF; \
334 if ((NAME).owner != self) \
336 if (lll_trylock ((NAME).lock) == 0) \
338 (NAME).owner = self; \
349 # define __libc_lock_trylock_recursive(NAME) \
350 __libc_lock_trylock_recursive_fn (&(NAME))
351 # endif /* __OPTION_EGLIBC_BIG_MACROS */
353 # define __libc_lock_trylock_recursive(NAME) \
354 __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0)
357 #define __rtld_lock_trylock_recursive(NAME) \
358 __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0)
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)
373 # define __libc_lock_unlock(NAME) \
374 __libc_lock_unlock_fn (&(NAME))
375 # endif /* __OPTION_EGLIBC_BIG_MACROS */
377 # define __libc_lock_unlock(NAME) \
378 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0)
380 #define __libc_rwlock_unlock(NAME) \
381 __libc_ptf_call (__pthread_rwlock_unlock, (&(NAME)), 0)
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) \
396 if (--(NAME).cnt == 0) \
398 (NAME).owner = NULL; \
399 lll_unlock ((NAME).lock, LLL_PRIVATE); \
403 # define __libc_lock_unlock_recursive(NAME) \
404 __libc_lock_unlock_recursive_fn (&(NAME))
405 # endif /* __OPTION_EGLIBC_BIG_MACROS */
407 # define __libc_lock_unlock_recursive(NAME) \
408 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0)
411 #if defined _LIBC && defined SHARED
412 # define __rtld_lock_default_lock_recursive(lock) \
413 ++((pthread_mutex_t *)(lock))->__data.__count;
415 # define __rtld_lock_default_unlock_recursive(lock) \
416 --((pthread_mutex_t *)(lock))->__data.__count;
418 # define __rtld_lock_lock_recursive(NAME) \
419 GL(dl_rtld_lock_recursive) (&(NAME).mutex)
421 # define __rtld_lock_unlock_recursive(NAME) \
422 GL(dl_rtld_unlock_recursive) (&(NAME).mutex)
424 # define __rtld_lock_lock_recursive(NAME) \
425 __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0)
427 # define __rtld_lock_unlock_recursive(NAME) \
428 __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0)
431 /* Define once control variable. */
432 #if PTHREAD_ONCE_INIT == 0
433 /* Special case for static variables where we can avoid the initialization
435 # define __libc_once_define(CLASS, NAME) \
436 CLASS pthread_once_t NAME
438 # define __libc_once_define(CLASS, NAME) \
439 CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
442 /* Call handler iff the first call. */
443 #define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
445 if (PTFAVAIL (__pthread_once)) \
446 __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL), \
448 else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \
450 (ONCE_CONTROL) |= 2; \
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,
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,
468 /* Start critical region with cleanup. */
469 #define __libc_cleanup_region_start(DOIT, FCT, ARG) \
470 { struct _pthread_cleanup_buffer _buffer; \
473 _avail = PTFAVAIL (_pthread_cleanup_push_defer); \
475 __libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT, \
478 _buffer.__routine = (FCT); \
479 _buffer.__arg = (ARG); \
485 /* End critical region with cleanup. */
486 #define __libc_cleanup_region_end(DOIT) \
488 __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\
490 _buffer.__routine (_buffer.__arg); \
493 /* Sometimes we have to exit the block in the middle. */
494 #define __libc_cleanup_end(DOIT) \
496 __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\
498 _buffer.__routine (_buffer.__arg)
501 /* Normal cleanup handling, based on C cleanup attribute. */
503 __libc_cleanup_routine (struct __pthread_cleanup_frame *f)
506 f->__cancel_routine (f->__cancel_arg);
509 #define __libc_cleanup_push(fct, arg) \
511 struct __pthread_cleanup_frame __clframe \
512 __attribute__ ((__cleanup__ (__libc_cleanup_routine))) \
513 = { .__cancel_routine = (fct), .__cancel_arg = (arg), \
516 #define __libc_cleanup_pop(execute) \
517 __clframe.__do_it = (execute); \
521 /* Create thread-specific key. */
522 #define __libc_key_create(KEY, DESTRUCTOR) \
523 __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)
525 /* Get thread-specific data. */
526 #define __libc_getspecific(KEY) \
527 __libc_ptf_call (__pthread_getspecific, (KEY), NULL)
529 /* Set thread-specific data. */
530 #define __libc_setspecific(KEY, VALUE) \
531 __libc_ptf_call (__pthread_setspecific, (KEY, VALUE), 0)
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),
544 /* Functions that are used by this file and are internal to the GNU C
547 extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
548 __const pthread_mutexattr_t *__mutex_attr);
550 extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
552 extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
554 extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
556 extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
558 extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr);
560 extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
562 extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
566 extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
567 __const pthread_rwlockattr_t *__attr);
569 extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
571 extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
573 extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
575 extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
577 extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
579 extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
582 extern int __pthread_key_create (pthread_key_t *__key,
583 void (*__destr_function) (void *));
585 extern int __pthread_setspecific (pthread_key_t __key,
586 __const void *__pointer);
588 extern void *__pthread_getspecific (pthread_key_t __key);
590 extern int __pthread_once (pthread_once_t *__once_control,
591 void (*__init_routine) (void));
593 extern int __pthread_atfork (void (*__prepare) (void),
594 void (*__parent) (void),
595 void (*__child) (void));
599 /* Make the pthread functions weak so that we can elide them from
600 single-threaded processes. */
601 #ifndef __NO_WEAK_PTHREAD_ALIASES
606 # define BP_SYM(sym) sym
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))
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
659 #endif /* bits/libc-lock.h */