diff --git a/sysdeps/i386/nptl/rseq-access.h b/sysdeps/i386/nptl/rseq-access.h
new file mode 100644
index 0000000000..5e7e09d494
--- /dev/null
+++ b/sysdeps/i386/nptl/rseq-access.h
@@ -0,0 +1,98 @@
+/* RSEQ_* accessors. i386 version.
+ Copyright (C) 2002-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ . */
+
+#define __RSEQ_GETMEM(member) \
+ ({ __typeof (RSEQ_SELF()->member) __value; \
+ if (sizeof (__value) == 1) \
+ asm volatile ("movb %%gs:%P2(%3),%b0" \
+ : "=q" (__value) \
+ : "0" (0), "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ else if (sizeof (__value) == 4) \
+ asm volatile ("movl %%gs:%P1(%2),%0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ else /* 8 */ \
+ { \
+ asm volatile ("movl %%gs:%P1(%2),%%eax\n\t" \
+ "movl %%gs:4+%P1(%2),%%edx" \
+ : "=&A" (__value) \
+ : "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ } \
+ __value; })
+
+/* Read member of the RSEQ area directly. */
+#define RSEQ_GETMEM(member) \
+ ({ \
+ _Static_assert (sizeof (RSEQ_SELF()->member) == 1 \
+ || sizeof (RSEQ_SELF()->member) == 4 \
+ || sizeof (RSEQ_SELF()->member) == 8, \
+ "size of rseq data"); \
+ __RSEQ_GETMEM(member); })
+
+/* Read member of the RSEQ area directly, with single-copy atomicity semantics.
+ Static assert for types >= 64 bits since they can't be loaded atomically on
+ x86-32. */
+#define RSEQ_GETMEM_ONCE(member) \
+ ({ \
+ _Static_assert (sizeof (RSEQ_SELF()->member) == 1 \
+ || sizeof (RSEQ_SELF()->member) == 4, \
+ "size of rseq data"); \
+ __RSEQ_GETMEM(member); })
+
+#define __RSEQ_SETMEM(member, value) \
+ ({ \
+ if (sizeof (RSEQ_SELF()->member) == 1) \
+ asm volatile ("movb %b0,%%gs:%P1(%2)" : \
+ : "iq" (value), \
+ "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ else if (sizeof (RSEQ_SELF()->member) == 4) \
+ asm volatile ("movl %0,%%gs:%P1(%2)" : \
+ : "ir" (value), \
+ "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ else /* 8 */ \
+ { \
+ asm volatile ("movl %%eax,%%gs:%P1(%2)\n\t" \
+ "movl %%edx,%%gs:4+%P1(%2)" : \
+ : "A" ((uint64_t) cast_to_integer (value)), \
+ "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ }})
+
+/* Set member of the RSEQ area directly. */
+#define RSEQ_SETMEM(member, value) \
+ ({ \
+ _Static_assert (sizeof (RSEQ_SELF()->member) == 1 \
+ || sizeof (RSEQ_SELF()->member) == 4 \
+ || sizeof (RSEQ_SELF()->member) == 8, \
+ "size of rseq data"); \
+ __RSEQ_SETMEM(member, value); })
+
+/* Set member of the RSEQ area directly, with single-copy atomicity semantics.
+ Static assert for types >= 64 bits since they can't be stored atomically on
+ x86-32. */
+#define RSEQ_SETMEM_ONCE(member, value) \
+ ({ \
+ _Static_assert (sizeof (RSEQ_SELF()->member) == 1 \
+ || sizeof (RSEQ_SELF()->member) == 4, \
+ "size of rseq data"); \
+ __RSEQ_SETMEM(member, value); })
diff --git a/sysdeps/nptl/rseq-access.h b/sysdeps/nptl/rseq-access.h
new file mode 100644
index 0000000000..450f2dcca3
--- /dev/null
+++ b/sysdeps/nptl/rseq-access.h
@@ -0,0 +1,56 @@
+/* RSEQ_* accessors. Generic version.
+ Copyright (C) 2002-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ . */
+
+#include
+
+/* Read member of the RSEQ area directly. */
+#define RSEQ_GETMEM(member) \
+ RSEQ_SELF()->member
+
+/* Set member of the RSEQ area directly. */
+#define RSEQ_SETMEM(member, value) \
+ RSEQ_SELF()->member = (value)
+
+/* Static assert for types that can't be loaded/stored atomically on the
+ current architecture. */
+#if __HAVE_64B_ATOMICS
+#define __RSEQ_ASSERT_ATOMIC(member) \
+ _Static_assert (sizeof (RSEQ_SELF()->member) == 1 \
+ || sizeof (RSEQ_SELF()->member) == 4 \
+ || sizeof (RSEQ_SELF()->member) == 8, \
+ "size of rseq data")
+#else
+#define __RSEQ_ASSERT_ATOMIC(member) \
+ _Static_assert (sizeof (RSEQ_SELF()->member) == 1 \
+ || sizeof (RSEQ_SELF()->member) == 4, \
+ "size of rseq data")
+#endif
+
+/* Read member of the RSEQ area directly, with single-copy atomicity semantics. */
+#define RSEQ_GETMEM_ONCE(member) \
+ ({ \
+ __RSEQ_ASSERT_ATOMIC(member); \
+ (*(volatile __typeof (RSEQ_SELF()->member) *)&RSEQ_SELF()->member); \
+ })
+
+/* Set member of the RSEQ area directly, with single-copy atomicity semantics. */
+#define RSEQ_SETMEM_ONCE(member, value) \
+ ({ \
+ __RSEQ_ASSERT_ATOMIC(member); \
+ (*(volatile __typeof (RSEQ_SELF()->member) *)&RSEQ_SELF()->member = (value)); \
+ })
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
index 3993431707..00be15cfc8 100644
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
/* Minimum size of the rseq area allocation required by the syscall. The
actually used rseq feature size may be less (20 bytes initially). */
@@ -59,6 +60,13 @@ extern ptrdiff_t _rseq_offset attribute_hidden;
rtld_hidden_proto (__rseq_size)
rtld_hidden_proto (__rseq_offset)
+/* Returns a pointer to the current thread rseq area. */
+static inline struct rseq_area *
+RSEQ_SELF (void)
+{
+ return (struct rseq_area *) ((char *) __thread_pointer () + __rseq_offset);
+}
+
#ifdef RSEQ_SIG
static inline bool
rseq_register_current_thread (struct pthread *self, bool do_rseq)
diff --git a/sysdeps/x86_64/nptl/rseq-access.h b/sysdeps/x86_64/nptl/rseq-access.h
new file mode 100644
index 0000000000..535e36281f
--- /dev/null
+++ b/sysdeps/x86_64/nptl/rseq-access.h
@@ -0,0 +1,77 @@
+/* RSEQ_* accessors. x86_64 version.
+ Copyright (C) 2002-2025 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ . */
+
+/* Read member of the RSEQ area directly, with single-copy atomicity semantics. */
+#define RSEQ_GETMEM_ONCE(member) \
+ ({ __typeof (RSEQ_SELF()->member) __value; \
+ _Static_assert (sizeof (__value) == 1 \
+ || sizeof (__value) == 4 \
+ || sizeof (__value) == 8, \
+ "size of rseq data"); \
+ if (sizeof (__value) == 1) \
+ asm volatile ("movb %%fs:%P2(%q3),%b0" \
+ : "=q" (__value) \
+ : "0" (0), "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ else if (sizeof (__value) == 4) \
+ asm volatile ("movl %%fs:%P1(%q2),%0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ else /* 8 */ \
+ { \
+ asm volatile ("movq %%fs:%P1(%q2),%q0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ } \
+ __value; })
+
+/* Read member of the RSEQ area directly. */
+#define RSEQ_GETMEM(member) RSEQ_GETMEM_ONCE(member)
+
+/* Set member of the RSEQ area directly, with single-copy atomicity semantics. */
+#define RSEQ_SETMEM_ONCE(member, value) \
+ ({ \
+ _Static_assert (sizeof (RSEQ_SELF()->member) == 1 \
+ || sizeof (RSEQ_SELF()->member) == 4 \
+ || sizeof (RSEQ_SELF()->member) == 8, \
+ "size of rseq data"); \
+ if (sizeof (RSEQ_SELF()->member) == 1) \
+ asm volatile ("movb %b0,%%fs:%P1(%q2)" : \
+ : "iq" (value), \
+ "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ else if (sizeof (RSEQ_SELF()->member) == 4) \
+ asm volatile ("movl %0,%%fs:%P1(%q2)" : \
+ : IMM_MODE (value), \
+ "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ else /* 8 */ \
+ { \
+ /* Since movq takes a signed 32-bit immediate or a register source \
+ operand, use "er" constraint for 32-bit signed integer constant \
+ or register. */ \
+ asm volatile ("movq %q0,%%fs:%P1(%q2)" : \
+ : "er" ((uint64_t) cast_to_integer (value)), \
+ "i" (offsetof (struct rseq_area, member)), \
+ "r" (__rseq_offset)); \
+ }})
+
+/* Set member of the RSEQ area directly. */
+#define RSEQ_SETMEM(member, value) RSEQ_SETMEM_ONCE(member, value)