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