[PATCH RESEND 2/3] sysdeps: add rtld_rwlock_recursive
Caleb Sander Mateos
csander@purestorage.com
Tue Sep 23 19:27:03 GMT 2025
A subsequent commit will want to use a reader-writer lock in the runtime
dynamic loader. Currently, only a full mutual exclusion lock is defined
for rtld, rtld_lock_recursive. Add rtld_rwlock_*_recursive macros
providing an similar interface except with "lock" split into "rdlock"
and "wrlock":
- __rtld_rwlock_define_recursive() to declare a rwlock
- __rtld_rwlock_define_initialized_recursive() to define and initialize
a rwlock
- __rtld_rwlock_rdlock_recursive() to lock a rwlock for reading (shared)
- __rtld_rwlock_wrlock_recursive() to lock a rwlock for writing
(exclusive)
- __rtld_rwlock_unlock_recursive() to unlock a rwlock locked for either
reading or writing
In sysdeps/nptl/libc-lockP.h and sysdeps/nptl/dl-mutex.c, map the rdlock,
wrlock, and unlock macros to the corresponding pthread_rwlock functions.
Initialize the pthread_rwlock with the PTHREAD_RWLOCK_PREFER_READER_NP
lock kind in the define_initialized macro to allow the rwlock to be
locked recursively for reading.
Define the rtld_rwlock macros as aliases for the corresponding rtld_lock
macros in sysdeps/mach/libc-lock.h, analogous to the libc_rwlock macros.
Signed-off-by: Caleb Sander Mateos <csander@purestorage.com>
---
sysdeps/generic/ldsodefs.h | 3 +++
sysdeps/generic/libc-lock.h | 5 +++++
sysdeps/mach/libc-lock.h | 7 +++++++
sysdeps/nptl/dl-mutex.c | 24 ++++++++++++++++++++++++
sysdeps/nptl/dl-tls_init_tp.c | 9 +++++++++
sysdeps/nptl/libc-lockP.h | 26 ++++++++++++++++++++++++++
6 files changed, 74 insertions(+)
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 31e9a6b600..f36e64ddba 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1457,10 +1457,13 @@ _dl_audit_objclose (struct link_map *l)
no-op dummy implementation early. Similar
to GL (dl_rtld_lock_recursive) and GL (dl_rtld_unlock_recursive)
in !PTHREAD_IN_LIBC builds. */
extern int (*___rtld_mutex_lock) (pthread_mutex_t *) attribute_hidden;
extern int (*___rtld_mutex_unlock) (pthread_mutex_t *lock) attribute_hidden;
+extern int (*___rtld_rwlock_rdlock) (pthread_rwlock_t *) attribute_hidden;
+extern int (*___rtld_rwlock_wrlock) (pthread_rwlock_t *) attribute_hidden;
+extern int (*___rtld_rwlock_unlock) (pthread_rwlock_t *) attribute_hidden;
/* Called after libc has been loaded, but before RELRO is activated.
Used to initialize the function pointers to the actual
implementations. */
void __rtld_mutex_init (void) attribute_hidden;
diff --git a/sysdeps/generic/libc-lock.h b/sysdeps/generic/libc-lock.h
index fafaf8c932..a7b0ee6c88 100644
--- a/sysdeps/generic/libc-lock.h
+++ b/sysdeps/generic/libc-lock.h
@@ -28,20 +28,22 @@
begins with a `*'), because its storage size will not be known outside
of libc. */
#define __libc_lock_define(CLASS,NAME)
#define __libc_lock_define_recursive(CLASS,NAME)
#define __rtld_lock_define_recursive(CLASS,NAME)
+#define __rtld_rwlock_define_recursive(CLASS,NAME)
#define __libc_rwlock_define(CLASS,NAME)
/* Define an initialized lock variable NAME with storage class CLASS. */
#define __libc_lock_define_initialized(CLASS,NAME)
#define __libc_rwlock_define_initialized(CLASS,NAME)
/* Define an initialized recursive lock variable NAME with storage
class CLASS. */
#define __libc_lock_define_initialized_recursive(CLASS,NAME)
#define __rtld_lock_define_initialized_recursive(CLASS,NAME)
+#define __rtld_rwlock_define_initialized_recursive(CLASS,NAME)
/* Initialize the named lock variable, leaving it in a consistent, unlocked
state. */
#define __libc_lock_init(NAME)
#define __rtld_lock_initialize(NAME)
@@ -65,10 +67,12 @@
#define __libc_rwlock_wrlock(NAME)
/* Lock the recursive named lock variable. */
#define __libc_lock_lock_recursive(NAME)
#define __rtld_lock_lock_recursive(NAME)
+#define __rtld_rwlock_rdlock_recursive(NAME)
+#define __rtld_rwlock_wrlock_recursive(NAME)
/* Try to lock the named lock variable. */
#define __libc_lock_trylock(NAME) 0
#define __libc_rwlock_tryrdlock(NAME) 0
#define __libc_rwlock_trywrlock(NAME) 0
@@ -81,10 +85,11 @@
#define __libc_rwlock_unlock(NAME)
/* Unlock the recursive named lock variable. */
#define __libc_lock_unlock_recursive(NAME)
#define __rtld_lock_unlock_recursive(NAME)
+#define __rtld_rwlock_unlock_recursive(NAME)
/* Define once control variable. */
#define __libc_once_define(CLASS, NAME) CLASS int NAME = 0
diff --git a/sysdeps/mach/libc-lock.h b/sysdeps/mach/libc-lock.h
index fd590f1551..d02269039b 100644
--- a/sysdeps/mach/libc-lock.h
+++ b/sysdeps/mach/libc-lock.h
@@ -150,10 +150,17 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
#define __libc_rwlock_rdlock __libc_lock_lock
#define __libc_rwlock_wrlock __libc_lock_lock
#define __libc_rwlock_tryrdlock __libc_lock_trylock
#define __libc_rwlock_trywrlock __libc_lock_trylock
#define __libc_rwlock_unlock __libc_lock_unlock
+#define __rtld_rwlock_define_recursive __rtld_lock_define_recursive
+#define _RTLD_RWLOCK_RECURSIVE_INITIALIZER _RTLD_LOCK_RECURSIVE_INITIALIZER
+#define __rtld_rwlock_define_initialized_recursive \
+ __rtld_lock_define_initialized_recursive
+#define __rtld_rwlock_rdlock_recursive __rtld_lock_lock_recursive
+#define __rtld_rwlock_wrlock_recursive __rtld_lock_lock_recursive
+#define __rtld_rwlock_unlock_recursive __rtld_lock_unlock_recursive
struct __libc_cleanup_frame
{
void (*__fct) (void *);
void *__argp;
diff --git a/sysdeps/nptl/dl-mutex.c b/sysdeps/nptl/dl-mutex.c
index 1e324e19bb..f5371326b2 100644
--- a/sysdeps/nptl/dl-mutex.c
+++ b/sysdeps/nptl/dl-mutex.c
@@ -22,10 +22,13 @@
#include <first-versions.h>
#include <ldsodefs.h>
__typeof (pthread_mutex_lock) *___rtld_mutex_lock attribute_relro;
__typeof (pthread_mutex_unlock) *___rtld_mutex_unlock attribute_relro;
+__typeof (pthread_rwlock_rdlock) *___rtld_rwlock_rdlock attribute_relro;
+__typeof (pthread_rwlock_wrlock) *___rtld_rwlock_wrlock attribute_relro;
+__typeof (pthread_rwlock_unlock) *___rtld_rwlock_unlock attribute_relro;
void
__rtld_mutex_init (void)
{
/* There is an implicit assumption here that the lock counters are
@@ -48,6 +51,27 @@ __rtld_mutex_init (void)
0x7dd7aaaa, /* dl_new_hash output. */
FIRST_VERSION_libc_pthread_mutex_unlock_STRING,
FIRST_VERSION_libc_pthread_mutex_unlock_HASH);
assert (sym != NULL);
___rtld_mutex_unlock = DL_SYMBOL_ADDRESS (libc_map, sym);
+
+ sym = _dl_lookup_direct (libc_map, "pthread_rwlock_rdlock",
+ 0x1534d41c, /* dl_new_hash output. */
+ FIRST_VERSION_libc_pthread_rwlock_rdlock_STRING,
+ FIRST_VERSION_libc_pthread_rwlock_rdlock_HASH);
+ assert (sym != NULL);
+ ___rtld_rwlock_rdlock = DL_SYMBOL_ADDRESS (libc_map, sym);
+
+ sym = _dl_lookup_direct (libc_map, "pthread_rwlock_wrlock",
+ 0x21dbf64f, /* dl_new_hash output. */
+ FIRST_VERSION_libc_pthread_rwlock_wrlock_STRING,
+ FIRST_VERSION_libc_pthread_rwlock_wrlock_HASH);
+ assert (sym != NULL);
+ ___rtld_rwlock_wrlock = DL_SYMBOL_ADDRESS (libc_map, sym);
+
+ sym = _dl_lookup_direct (libc_map, "pthread_rwlock_unlock",
+ 0x1ce94309, /* dl_new_hash output. */
+ FIRST_VERSION_libc_pthread_rwlock_unlock_STRING,
+ FIRST_VERSION_libc_pthread_rwlock_unlock_HASH);
+ assert (sym != NULL);
+ ___rtld_rwlock_unlock = DL_SYMBOL_ADDRESS (libc_map, sym);
}
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
index 47566dce4f..5c97983302 100644
--- a/sysdeps/nptl/dl-tls_init_tp.c
+++ b/sysdeps/nptl/dl-tls_init_tp.c
@@ -41,10 +41,16 @@ rtld_hidden_def (__nptl_initial_report_events)
static int
rtld_mutex_dummy (pthread_mutex_t *lock)
{
return 0;
}
+
+static int
+rtld_rwlock_dummy (pthread_rwlock_t *lock)
+{
+ return 0;
+}
#endif
const unsigned int __rseq_flags;
size_t _rseq_align attribute_hidden;
@@ -59,10 +65,13 @@ __tls_pre_init_tp (void)
INIT_LIST_HEAD (&GL (dl_stack_cache));
#ifdef SHARED
___rtld_mutex_lock = rtld_mutex_dummy;
___rtld_mutex_unlock = rtld_mutex_dummy;
+ ___rtld_rwlock_rdlock = rtld_rwlock_dummy;
+ ___rtld_rwlock_wrlock = rtld_rwlock_dummy;
+ ___rtld_rwlock_unlock = rtld_rwlock_dummy;
#endif
}
void
__tls_init_tp (void)
diff --git a/sysdeps/nptl/libc-lockP.h b/sysdeps/nptl/libc-lockP.h
index 1be3dd1ec1..904482be83 100644
--- a/sysdeps/nptl/libc-lockP.h
+++ b/sysdeps/nptl/libc-lockP.h
@@ -36,10 +36,11 @@
/* Mutex type. */
typedef int __libc_lock_t __LIBC_LOCK_ALIGNMENT;
typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t;
typedef pthread_rwlock_t __libc_rwlock_t;
+typedef struct { pthread_rwlock_t rwlock; } __rtld_rwlock_recursive_t;
/* Define a lock variable NAME with storage class CLASS. The lock must be
initialized with __libc_lock_init before it can be used (or define it
with __libc_lock_define_initialized, below). Use `extern' for CLASS to
declare a lock defined in another module. In public structure
@@ -50,10 +51,12 @@ typedef pthread_rwlock_t __libc_rwlock_t;
CLASS __libc_lock_t NAME;
#define __libc_rwlock_define(CLASS,NAME) \
CLASS __libc_rwlock_t NAME;
#define __rtld_lock_define_recursive(CLASS,NAME) \
CLASS __rtld_lock_recursive_t NAME;
+#define __rtld_rwlock_define_recursive(CLASS,NAME) \
+ CLASS __rtld_rwlock_recursive_t NAME;
/* Define an initialized lock variable NAME with storage class CLASS.
For the C library we take a deeper look at the initializer. For
this implementation all fields are initialized to zero. Therefore
@@ -71,10 +74,15 @@ _Static_assert (LLL_LOCK_INITIALIZER == 0, "LLL_LOCK_INITIALIZER != 0");
#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \
CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER;
#define _RTLD_LOCK_RECURSIVE_INITIALIZER \
{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP}
+#define __rtld_rwlock_define_initialized_recursive(CLASS,NAME) \
+ CLASS __rtld_rwlock_recursive_t NAME = _RTLD_RWLOCK_RECURSIVE_INITIALIZER;
+#define _RTLD_RWLOCK_RECURSIVE_INITIALIZER \
+ {PTHREAD_RWLOCK_INITIALIZER}
+
#define __rtld_lock_initialize(NAME) \
(void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER)
/* If we check for a weakly referenced symbol and then perform a
normal jump to it te code generated for some platforms in case of
@@ -124,16 +132,34 @@ _Static_assert (LLL_LOCK_INITIALIZER == 0, "LLL_LOCK_INITIALIZER != 0");
# define __rtld_lock_lock_recursive(NAME) \
___rtld_mutex_lock (&(NAME).mutex)
# define __rtld_lock_unlock_recursive(NAME) \
___rtld_mutex_unlock (&(NAME).mutex)
+
+# define __rtld_rwlock_rdlock_recursive(NAME) \
+ ___rtld_rwlock_rdlock (&(NAME).rwlock)
+
+# define __rtld_rwlock_wrlock_recursive(NAME) \
+ ___rtld_rwlock_wrlock (&(NAME).rwlock)
+
+# define __rtld_rwlock_unlock_recursive(NAME) \
+ ___rtld_rwlock_unlock (&(NAME).rwlock)
#else /* Not in the dynamic loader. */
# define __rtld_lock_lock_recursive(NAME) \
__pthread_mutex_lock (&(NAME).mutex)
# define __rtld_lock_unlock_recursive(NAME) \
__pthread_mutex_unlock (&(NAME).mutex)
+
+# define __rtld_rwlock_rdlock_recursive(NAME) \
+ __pthread_rwlock_rdlock (&(NAME).rwlock)
+
+# define __rtld_rwlock_wrlock_recursive(NAME) \
+ __pthread_rwlock_wrlock (&(NAME).rwlock)
+
+# define __rtld_rwlock_unlock_recursive(NAME) \
+ __pthread_rwlock_unlock (&(NAME).rwlock)
#endif
/* Define once control variable. */
#if PTHREAD_ONCE_INIT == 0
/* Special case for static variables where we can avoid the initialization
--
2.43.0
More information about the Libc-alpha
mailing list