1/* Private libc-internal interface for mutex locks. NPTL version.
2 Copyright (C) 1996-2022 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
17 not, see <https://www.gnu.org/licenses/>. */
18
19#ifndef _LIBC_LOCKP_H
20#define _LIBC_LOCKP_H 1
21
22#include <pthread.h>
23#define __need_NULL
24#include <stddef.h>
25
26
27/* Fortunately Linux now has a mean to do locking which is realtime
28 safe without the aid of the thread library. We also need no fancy
29 options like error checking mutexes etc. We only need simple
30 locks, maybe recursive. This can be easily and cheaply implemented
31 using futexes. We will use them everywhere except in ld.so since
32 ld.so might be used on old kernels with a different libc.so. */
33#include <lowlevellock.h>
34#include <tls.h>
35#include <libc-lock-arch.h>
36
37/* Mutex type. */
38typedef int __libc_lock_t __LIBC_LOCK_ALIGNMENT;
39typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t;
40typedef pthread_rwlock_t __libc_rwlock_t;
41
42/* Define a lock variable NAME with storage class CLASS. The lock must be
43 initialized with __libc_lock_init before it can be used (or define it
44 with __libc_lock_define_initialized, below). Use `extern' for CLASS to
45 declare a lock defined in another module. In public structure
46 definitions you must use a pointer to the lock structure (i.e., NAME
47 begins with a `*'), because its storage size will not be known outside
48 of libc. */
49#define __libc_lock_define(CLASS,NAME) \
50 CLASS __libc_lock_t NAME;
51#define __libc_rwlock_define(CLASS,NAME) \
52 CLASS __libc_rwlock_t NAME;
53#define __rtld_lock_define_recursive(CLASS,NAME) \
54 CLASS __rtld_lock_recursive_t NAME;
55
56/* Define an initialized lock variable NAME with storage class CLASS.
57
58 For the C library we take a deeper look at the initializer. For
59 this implementation all fields are initialized to zero. Therefore
60 we don't initialize the variable which allows putting it into the
61 BSS section. */
62
63_Static_assert (LLL_LOCK_INITIALIZER == 0, "LLL_LOCK_INITIALIZER != 0");
64#define _LIBC_LOCK_INITIALIZER LLL_LOCK_INITIALIZER
65#define __libc_lock_define_initialized(CLASS,NAME) \
66 CLASS __libc_lock_t NAME;
67
68#define __libc_rwlock_define_initialized(CLASS,NAME) \
69 CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER;
70
71#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
72 CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
73#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
74 {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
75
76#define __rtld_lock_initialize(NAME) \
77 (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER)
78
79/* If we check for a weakly referenced symbol and then perform a
80 normal jump to it te code generated for some platforms in case of
81 PIC is unnecessarily slow. What would happen is that the function
82 is first referenced as data and then it is called indirectly
83 through the PLT. We can make this a direct jump. */
84#ifdef __PIC__
85# define __libc_maybe_call(FUNC, ARGS, ELSE) \
86 (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
87 _fn != NULL ? (*_fn) ARGS : ELSE; }))
88#else
89# define __libc_maybe_call(FUNC, ARGS, ELSE) \
90 (FUNC != NULL ? FUNC ARGS : ELSE)
91#endif
92
93/* All previously forwarded functions are now called directly (either
94 via local call in libc, or through a __export), but __libc_ptf_call
95 is still used in generic code shared with Hurd. */
96#define PTFAVAIL(NAME) 1
97#define __libc_ptf_call(FUNC, ARGS, ELSE) FUNC ARGS
98#define __libc_ptf_call_always(FUNC, ARGS) FUNC ARGS
99
100/* Initialize the named lock variable, leaving it in a consistent, unlocked
101 state. */
102#define __libc_lock_init(NAME) ((void) ((NAME) = LLL_LOCK_INITIALIZER))
103#define __libc_rwlock_init(NAME) __pthread_rwlock_init (&(NAME), NULL)
104
105/* Finalize the named lock variable, which must be locked. It cannot be
106 used again until __libc_lock_init is called again on it. This must be
107 called on a lock variable before the containing storage is reused. */
108#define __libc_lock_fini(NAME) ((void) 0)
109#define __libc_rwlock_fini(NAME) ((void) 0)
110
111/* Lock the named lock variable. */
112#define __libc_lock_lock(NAME) ({ lll_lock (NAME, LLL_PRIVATE); 0; })
113#define __libc_rwlock_rdlock(NAME) __pthread_rwlock_rdlock (&(NAME))
114#define __libc_rwlock_wrlock(NAME) __pthread_rwlock_wrlock (&(NAME))
115
116/* Try to lock the named lock variable. */
117#define __libc_lock_trylock(NAME) lll_trylock (NAME)
118
119/* Unlock the named lock variable. */
120#define __libc_lock_unlock(NAME) lll_unlock (NAME, LLL_PRIVATE)
121#define __libc_rwlock_unlock(NAME) __pthread_rwlock_unlock (&(NAME))
122
123#if IS_IN (rtld)
124# define __rtld_lock_lock_recursive(NAME) \
125 ___rtld_mutex_lock (&(NAME).mutex)
126
127# define __rtld_lock_unlock_recursive(NAME) \
128 ___rtld_mutex_unlock (&(NAME).mutex)
129#else /* Not in the dynamic loader. */
130# define __rtld_lock_lock_recursive(NAME) \
131 __pthread_mutex_lock (&(NAME).mutex)
132
133# define __rtld_lock_unlock_recursive(NAME) \
134 __pthread_mutex_unlock (&(NAME).mutex)
135#endif
136
137/* Define once control variable. */
138#if PTHREAD_ONCE_INIT == 0
139/* Special case for static variables where we can avoid the initialization
140 if it is zero. */
141# define __libc_once_define(CLASS, NAME) \
142 CLASS pthread_once_t NAME
143#else
144# define __libc_once_define(CLASS, NAME) \
145 CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT
146#endif
147
148/* Call handler iff the first call. Use a local call in libc, but the
149 global pthread_once symbol elsewhere. */
150#if IS_IN (libc)
151# define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
152 __pthread_once (&(ONCE_CONTROL), INIT_FUNCTION)
153#else
154# define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \
155 pthread_once (&(ONCE_CONTROL), INIT_FUNCTION)
156#endif
157
158/* Get once control variable. */
159#define __libc_once_get(ONCE_CONTROL) ((ONCE_CONTROL) != PTHREAD_ONCE_INIT)
160
161/* __libc_cleanup_push and __libc_cleanup_pop depend on exception
162 handling and stack unwinding. */
163#ifdef __EXCEPTIONS
164
165/* Normal cleanup handling, based on C cleanup attribute. */
166static __always_inline void
167__libc_cleanup_routine (struct __pthread_cleanup_frame *f)
168{
169 if (f->__do_it)
170 f->__cancel_routine (f->__cancel_arg);
171}
172
173# define __libc_cleanup_push(fct, arg) \
174 do { \
175 struct __pthread_cleanup_frame __clframe \
176 __attribute__ ((__cleanup__ (__libc_cleanup_routine))) \
177 = { .__cancel_routine = (fct), .__cancel_arg = (arg), \
178 .__do_it = 1 };
179
180# define __libc_cleanup_pop(execute) \
181 __clframe.__do_it = (execute); \
182 } while (0)
183#endif /* __EXCEPTIONS */
184
185/* Register handlers to execute before and after `fork'. Note that the
186 last parameter is NULL. The handlers registered by the libc are
187 never removed so this is OK. */
188extern int __register_atfork (void (*__prepare) (void),
189 void (*__parent) (void),
190 void (*__child) (void),
191 void *__dso_handle);
192
193/* Functions that are used by this file and are internal to the GNU C
194 library. */
195
196extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
197 const pthread_mutexattr_t *__mutex_attr);
198libc_hidden_proto (__pthread_mutex_init)
199extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
200libc_hidden_proto (__pthread_mutex_destroy)
201extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex);
202
203extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
204libc_hidden_proto (__pthread_mutex_lock)
205extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
206libc_hidden_proto (__pthread_mutex_unlock)
207
208extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr);
209
210extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock,
211 const pthread_rwlockattr_t *__attr);
212libc_hidden_proto (__pthread_rwlock_init)
213
214extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
215
216extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
217libc_hidden_proto (__pthread_rwlock_rdlock)
218
219extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
220libc_hidden_proto (__pthread_rwlock_wrlock)
221
222extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
223libc_hidden_proto (__pthread_rwlock_unlock)
224extern int __pthread_once (pthread_once_t *__once_control,
225 void (*__init_routine) (void));
226libc_hidden_proto (__pthread_once)
227
228extern int __pthread_atfork (void (*__prepare) (void),
229 void (*__parent) (void),
230 void (*__child) (void));
231
232extern int __pthread_setcancelstate (int state, int *oldstate);
233libc_hidden_proto (__pthread_setcancelstate)
234
235/* Make the pthread functions weak so that we can elide them from
236 single-threaded processes. */
237#ifndef __NO_WEAK_PTHREAD_ALIASES
238# ifdef weak_extern
239weak_extern (__pthread_mutex_trylock)
240weak_extern (__pthread_mutexattr_destroy)
241weak_extern (__pthread_initialize)
242weak_extern (__pthread_atfork)
243# else
244# pragma weak __pthread_mutex_trylock
245# pragma weak __pthread_mutexattr_destroy
246# pragma weak __pthread_initialize
247# pragma weak __pthread_atfork
248# endif
249#endif
250
251#endif /* libc-lockP.h */
252

source code of glibc/sysdeps/nptl/libc-lockP.h