@@ -4,5 +4,8 @@
RSEQ_SIZE_SIZE sizeof (unsigned int)
RSEQ_SIZE_ALIGN __alignof (unsigned int)
+RSEQ_FEATURE_SIZE_SIZE sizeof (unsigned int)
+RSEQ_FEATURE_SIZE_ALIGN __alignof (unsigned int)
+
RSEQ_OFFSET_SIZE sizeof (ptrdiff_t)
RSEQ_OFFSET_ALIGN __alignof (ptrdiff_t)
@@ -38,6 +38,23 @@ __rseq_size:
_rseq_size:
.zero RSEQ_SIZE_SIZE
+/* Define 2 symbols, __rseq_feature_size is public const and
+ _rseq_feature_size, which is an alias of __rseq_feature_size, but hidden and
+ writable for internal use. */
+
+ .globl __rseq_feature_size
+ .type __rseq_feature_size, %object
+ .size __rseq_feature_size, RSEQ_FEATURE_SIZE_SIZE
+ .hidden _rseq_feature_size
+ .globl _rseq_feature_size
+ .type _rseq_feature_size, %object
+ .size _rseq_feature_size, RSEQ_FEATURE_SIZE_SIZE
+ .section .data.rel.ro
+ .balign RSEQ_FEATURE_SIZE_ALIGN
+__rseq_feature_size:
+_rseq_feature_size:
+ .zero RSEQ_FEATURE_SIZE_SIZE
+
/* Define 2 symbols, __rseq_offset is public const and _rseq_offset, which is an
alias of __rseq_offset, but hidden and writable for internal use. */
@@ -1011,6 +1011,15 @@ registration is successful, @code{__rseq_size} is at least 32 (the
initial size of @code{struct rseq}).
@end deftypevar
+@deftypevar {unsigned int} __rseq_feature_size
+@standards{Linux, sys/rseq.h}
+This variable is either zero (if restartable sequence registration
+failed or has been disabled) or the size of the restartable sequence
+features supported by the running kernel. If registration is
+successful, @code{__rseq_feature_size} is at least 20 (the feature size
+of @code{struct rseq} in the initial rseq kernel implementation).
+@end deftypevar
+
@deftypevar {unsigned int} __rseq_flags
@standards{Linux, sys/rseq.h}
The flags used during restartable sequence registration with the kernel.
@@ -48,6 +48,7 @@ const unsigned int __rseq_flags;
/* The variables are in .data.relro but are not yet write-protected. */
extern unsigned int _rseq_size;
+extern unsigned int _rseq_feature_size;
extern ptrdiff_t _rseq_offset;
void
@@ -108,6 +109,7 @@ __tls_init_tp (void)
if (rseq_register_current_thread (pd, do_rseq))
{
_rseq_size = GLRO (dl_tls_rseq_alloc_size);
+ _rseq_feature_size = GLRO (dl_tls_rseq_feature_size);
}
/* If the registration fails or is disabled by tunable, the public rseq
@@ -356,6 +356,9 @@ ld {
__rseq_offset;
__rseq_size;
}
+ GLIBC_2.40 {
+ __rseq_feature_size;
+ }
GLIBC_PRIVATE {
__nptl_change_stack_perm;
}
@@ -7,3 +7,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x8
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.4 __stack_chk_guard D 0x4
GLIBC_2.4 __tls_get_addr F
GLIBC_2.4 _dl_mcount F
GLIBC_2.4 _r_debug D 0x14
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.4 __stack_chk_guard D 0x4
GLIBC_2.4 __tls_get_addr F
GLIBC_2.4 _dl_mcount F
GLIBC_2.4 _r_debug D 0x14
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -6,3 +6,4 @@ GLIBC_2.36 __stack_chk_guard D 0x8
GLIBC_2.36 __tls_get_addr F
GLIBC_2.36 _dl_mcount F
GLIBC_2.36 _r_debug D 0x28
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.4 __stack_chk_guard D 0x4
GLIBC_2.4 __tls_get_addr F
GLIBC_2.4 _dl_mcount F
GLIBC_2.4 _r_debug D 0x14
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x8
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -6,3 +6,4 @@ GLIBC_2.35 __stack_chk_guard D 0x4
GLIBC_2.35 __tls_get_addr F
GLIBC_2.35 _dl_mcount F
GLIBC_2.35 _r_debug D 0x14
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -9,3 +9,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.39 __parse_hwcap_3_4_and_convert_at_platform F
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -9,3 +9,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.39 __parse_hwcap_3_4_and_convert_at_platform F
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -9,3 +9,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.39 __parse_hwcap_3_4_and_convert_at_platform F
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -6,3 +6,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -6,3 +6,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -7,3 +7,4 @@ GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -6,3 +6,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -6,3 +6,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -163,6 +163,10 @@ extern const ptrdiff_t __rseq_offset;
unsuccessful. */
extern const unsigned int __rseq_size;
+/* Size of the registered rseq features. 0 if the registration was
+ unsuccessful. */
+extern const unsigned int __rseq_feature_size;
+
/* Flags used during rseq registration. */
extern const unsigned int __rseq_flags;
@@ -39,6 +39,7 @@ check_rseq_disabled (void)
TEST_COMPARE (__rseq_flags, 0);
TEST_COMPARE (__rseq_size, 0);
+ TEST_COMPARE (__rseq_feature_size, 0);
TEST_COMPARE ((int) rseq_area->cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
int ret = syscall (__NR_rseq, &local_rseq, RSEQ_TEST_MIN_SIZE, 0, RSEQ_SIG);
@@ -38,12 +38,14 @@ static void
do_rseq_main_test (void)
{
size_t rseq_align = MAX (getauxval (AT_RSEQ_ALIGN), RSEQ_TEST_MIN_ALIGN);
- size_t rseq_size = roundup (MAX (getauxval (AT_RSEQ_FEATURE_SIZE), RSEQ_TEST_MIN_SIZE), rseq_align);
+ size_t rseq_feature_size = MAX (getauxval (AT_RSEQ_FEATURE_SIZE), RSEQ_TEST_MIN_FEATURE_SIZE);
+ size_t rseq_size = roundup (MAX (rseq_feature_size, RSEQ_TEST_MIN_SIZE), rseq_align);
struct rseq *rseq = __thread_pointer () + __rseq_offset;
TEST_VERIFY_EXIT (rseq_thread_registered ());
TEST_COMPARE (__rseq_flags, 0);
TEST_COMPARE (__rseq_size, rseq_size);
+ TEST_COMPARE (__rseq_feature_size, rseq_feature_size);
/* The size of the rseq area must be a multiple of the alignment. */
TEST_VERIFY ((__rseq_size % rseq_align) == 0);
/* The rseq area address must be aligned. */
@@ -6,3 +6,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
@@ -6,3 +6,4 @@ GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
GLIBC_2.35 __rseq_offset D 0x4
GLIBC_2.35 __rseq_size D 0x4
+GLIBC_2.40 __rseq_feature_size D 0x4
Exposing this symbol allows applications wishing to use rseq features which are part of the extensible rseq ABI like 'node_id' and 'mm_cid' to test the two following conditions in a single load / conditional branch: - rseq is registered - the specific rseq feature is available This is useful as rseq is expected to be used in hot paths. This variable is either zero (if restartable sequence registration failed or has been disabled) or the size of the available restartable sequence features. Signed-off-by: Michael Jeanson <mjeanson@efficios.com> --- Changes since v7: - Fix sorting of symbols in abilist files Changes since v8: - Remove superfluous attributes on externs - Clarify where the magic '20' initial feature size comes from --- csu/rseq-sizes.sym | 3 +++ elf/dl-rseq-symbols.S | 17 +++++++++++++++++ manual/threads.texi | 9 +++++++++ sysdeps/nptl/dl-tls_init_tp.c | 2 ++ sysdeps/unix/sysv/linux/Versions | 3 +++ sysdeps/unix/sysv/linux/aarch64/ld.abilist | 1 + sysdeps/unix/sysv/linux/alpha/ld.abilist | 1 + sysdeps/unix/sysv/linux/arc/ld.abilist | 1 + sysdeps/unix/sysv/linux/arm/be/ld.abilist | 1 + sysdeps/unix/sysv/linux/arm/le/ld.abilist | 1 + sysdeps/unix/sysv/linux/csky/ld.abilist | 1 + sysdeps/unix/sysv/linux/hppa/ld.abilist | 1 + sysdeps/unix/sysv/linux/i386/ld.abilist | 1 + .../unix/sysv/linux/loongarch/lp64/ld.abilist | 1 + .../unix/sysv/linux/m68k/coldfire/ld.abilist | 1 + sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist | 1 + sysdeps/unix/sysv/linux/microblaze/ld.abilist | 1 + sysdeps/unix/sysv/linux/mips/mips32/ld.abilist | 1 + .../unix/sysv/linux/mips/mips64/n32/ld.abilist | 1 + .../unix/sysv/linux/mips/mips64/n64/ld.abilist | 1 + sysdeps/unix/sysv/linux/nios2/ld.abilist | 1 + sysdeps/unix/sysv/linux/or1k/ld.abilist | 1 + .../sysv/linux/powerpc/powerpc32/ld.abilist | 1 + .../sysv/linux/powerpc/powerpc64/be/ld.abilist | 1 + .../sysv/linux/powerpc/powerpc64/le/ld.abilist | 1 + sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist | 1 + sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist | 1 + sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist | 1 + sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist | 1 + sysdeps/unix/sysv/linux/sh/be/ld.abilist | 1 + sysdeps/unix/sysv/linux/sh/le/ld.abilist | 1 + .../unix/sysv/linux/sparc/sparc32/ld.abilist | 1 + .../unix/sysv/linux/sparc/sparc64/ld.abilist | 1 + sysdeps/unix/sysv/linux/sys/rseq.h | 4 ++++ sysdeps/unix/sysv/linux/tst-rseq-disable.c | 1 + sysdeps/unix/sysv/linux/tst-rseq.c | 4 +++- sysdeps/unix/sysv/linux/x86_64/64/ld.abilist | 1 + sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist | 1 + 38 files changed, 72 insertions(+), 1 deletion(-)