master
  1/* Private libc-internal interface for mutex locks.  NPTL version.
  2   Copyright (C) 1996-2025 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 */