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