tests: allow tests to append tunables

Message ID 20260324141438.3094802-1-yury.khrustalev@arm.com (mailing list archive)
State Under Review
Delegated to: Adhemerval Zanella Netto
Headers
Series tests: allow tests to append tunables |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

Commit Message

Yury Khrustalev March 24, 2026, 2:14 p.m. UTC
  Many tests use Glibc tunables. The tunable values are provided via
the GLIBC_TUNABLES env variable. Tests set it in makefiles using

  tst-foo-ENV = GLIBC_TUNABLES=tunable=value

This overwrites environment for this test, so if another env var is
set elsewhere, one of these changes would be lost. The correct way
should be to append to test's environment:

  tst-foo-ENV += GLIBC_TUNABLES=tunable=value

However, if two or more tunables need to be set for the same test,
the 'tunable=value' part should be appended to previously defined
GLIBC_TUNABLES env variable.

This commit adds 'tunable-add' that can be used to correctly append
another tunable to a test's environment. We also change tests in the
malloc and misc folder.

---
base-commit: 9f5f18aab4
passes regression on aarch64 and x86-64

---
 Makeconfig                               |  12 +++
 Rules                                    |  12 +--
 malloc/Makefile                          |  53 +++++-----
 sysdeps/unix/sysv/linux/aarch64/Makefile | 117 +++++++++++------------
 4 files changed, 99 insertions(+), 95 deletions(-)
  

Comments

Yury Khrustalev April 10, 2026, 10:27 a.m. UTC | #1
On Tue, Mar 24, 2026 at 02:14:38PM +0000, Yury Khrustalev wrote:
> Many tests use Glibc tunables. The tunable values are provided via
> the GLIBC_TUNABLES env variable. Tests set it in makefiles using
> 
>   tst-foo-ENV = GLIBC_TUNABLES=tunable=value
> 
> This overwrites environment for this test, so if another env var is
> set elsewhere, one of these changes would be lost. The correct way
> should be to append to test's environment:
> 
>   tst-foo-ENV += GLIBC_TUNABLES=tunable=value
> 
> However, if two or more tunables need to be set for the same test,
> the 'tunable=value' part should be appended to previously defined
> GLIBC_TUNABLES env variable.
> 
> This commit adds 'tunable-add' that can be used to correctly append
> another tunable to a test's environment. We also change tests in the
> malloc and misc folder.
> 
> ---
> base-commit: 9f5f18aab4
> passes regression on aarch64 and x86-64

Polite ping :)
  

Patch

diff --git a/Makeconfig b/Makeconfig
index 8fe7217dd7..9e01489ff9 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -1479,6 +1479,18 @@  evaluate-test = $(..)scripts/evaluate-test.sh $(test-name) $$? \
 
 endif # Makeconfig not yet included
 
+# Correctly modify Glibc tunable environment variable for the test
+# appending new param=value to the environment variable if it is
+# already defined for this test:
+# $(1) is test name and $(2) is param=value part that needs to be
+# appended to the value of the GLIBC_TUNABLES variable.
+define tunable-add
+$(1)-ENV = $(if \
+$(findstring GLIBC_TUNABLES,$($(1)-ENV)),\
+$(patsubst GLIBC_TUNABLES=%,GLIBC_TUNABLES=%:$(2),$($(1)-ENV)),\
+$($(1)-ENV) GLIBC_TUNABLES=$(2))
+endef
+
 # Local Variables:
 # mode: makefile
 # End:
diff --git a/Rules b/Rules
index 9d8587a148..427a7535a4 100644
--- a/Rules
+++ b/Rules
@@ -343,32 +343,32 @@  endif
 
 # All malloc-check tests will be run with MALLOC_CHECK_=3
 define malloc-check-ENVS
-$(1)-malloc-check-ENV = MALLOC_CHECK_=3 \
-			LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+$(1)-malloc-check-ENV += MALLOC_CHECK_=3 \
+			LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
 endef
 $(foreach t,$(tests-malloc-check),$(eval $(call malloc-check-ENVS,$(t))))
 
 # All malloc-hugetlb1 tests will be run with GLIBC_TUNABLES=glibc.malloc.hugetlb=1
 define malloc-hugetlb1-ENVS
-$(1)-malloc-hugetlb1-ENV += GLIBC_TUNABLES=glibc.malloc.hugetlb=1
+$(call tunable-add,$(1)-malloc-hugetlb1,glibc.malloc.hugetlb=1)
 endef
 $(foreach t,$(tests-malloc-hugetlb1),$(eval $(call malloc-hugetlb1-ENVS,$(t))))
 
 # All malloc-hugetlb2 tests will be run with GLIBC_TUNABLE=glibc.malloc.hugetlb=2
 define malloc-hugetlb2-ENVS
-$(1)-malloc-hugetlb2-ENV += GLIBC_TUNABLES=glibc.malloc.hugetlb=2
+$(call tunable-add,$(1)-malloc-hugetlb2,glibc.malloc.hugetlb=2)
 endef
 $(foreach t,$(tests-malloc-hugetlb2),$(eval $(call malloc-hugetlb2-ENVS,$(t))))
 
 # All malloc-largetcache tests will be run with GLIBC_TUNABLE=glibc.malloc.tcache_max=1048576
 define malloc-largetcache-ENVS
-$(1)-malloc-largetcache-ENV += GLIBC_TUNABLES=glibc.malloc.tcache_max=1048576
+$(call tunable-add,$(1)-malloc-largetcache,glibc.malloc.tcache_max=1048576)
 endef
 $(foreach t,$(tests-malloc-largetcache),$(eval $(call malloc-largetcache-ENVS,$(t))))
 
 # mcheck tests need the debug DSO to support -lmcheck.
 define mcheck-ENVS
-$(1)-mcheck-ENV = LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+$(1)-mcheck-ENV += LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
 endef
 $(foreach t,$(tests-mcheck),$(eval $(call mcheck-ENVS,$(t))))
 
diff --git a/malloc/Makefile b/malloc/Makefile
index fef5021298..ba540016f3 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -437,18 +437,18 @@  endif
 malloc-check-env = \
   MALLOC_CHECK_=3 \
   LD_PRELOAD=$(objpfx)/libc_malloc_debug.so
-
-malloc-check-tunables-env = \
-  GLIBC_TUNABLES=glibc.malloc.check=3 \
-  LD_PRELOAD=$(objpfx)/libc_malloc_debug.so
-
-tst-malloc-check-ENV = $(malloc-check-env)
-tst-malloc-usable-ENV = $(malloc-check-env)
-tst-malloc-usable-threaded-main-ENV = $(malloc-check-env)
-tst-malloc-usable-threaded-worker-ENV = $(malloc-check-env)
-tst-malloc-usable-tunables-ENV = $(malloc-check-tunables-env)
-tst-malloc-usable-tunables-threaded-main-ENV = $(malloc-check-tunables-env)
-tst-malloc-usable-tunables-threaded-worker-ENV = $(malloc-check-tunables-env)
+tst-malloc-check-ENV += $(malloc-check-env)
+tst-malloc-usable-ENV += $(malloc-check-env)
+tst-malloc-usable-threaded-main-ENV += $(malloc-check-env)
+tst-malloc-usable-threaded-worker-ENV += $(malloc-check-env)
+
+malloc-check-tunables-env = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-malloc-usable-tunables-ENV += $(malloc-check-tunables-env)
+tst-malloc-usable-tunables-threaded-main-ENV += $(malloc-check-tunables-env)
+tst-malloc-usable-tunables-threaded-worker-ENV += $(malloc-check-tunables-env)
+$(eval $(call tunable-add,tst-malloc-usable-tunables,glibc.malloc.check=3))
+$(eval $(call tunable-add,tst-malloc-usable-tunables-threaded-main,glibc.malloc.check=3))
+$(eval $(call tunable-add,tst-malloc-usable-tunables-threaded-worker,glibc.malloc.check=3))
 
 CPPFLAGS-malloc-debug.c += -DUSE_TCACHE=0
 CPPFLAGS-malloc.c += -DUSE_TCACHE=1
@@ -489,32 +489,31 @@  $(objpfx)tst-interpose-static-nothread: $(objpfx)tst-interpose-aux-nothread.o
 $(objpfx)tst-interpose-static-thread: \
   $(objpfx)tst-interpose-aux-thread.o $(static-thread-library)
 
-tst-dynarray-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray.mtrace \
+tst-dynarray-ENV += MALLOC_TRACE=$(objpfx)tst-dynarray.mtrace \
 		   LD_PRELOAD=$(objpfx)libc_malloc_debug.so
 $(objpfx)tst-dynarray-mem.out: $(objpfx)tst-dynarray.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray.mtrace > $@; \
 	$(evaluate-test)
 
-tst-dynarray-fail-ENV = MALLOC_TRACE=$(objpfx)tst-dynarray-fail.mtrace \
+tst-dynarray-fail-ENV += MALLOC_TRACE=$(objpfx)tst-dynarray-fail.mtrace \
 			LD_PRELOAD=$(objpfx)libc_malloc_debug.so
 $(objpfx)tst-dynarray-fail-mem.out: $(objpfx)tst-dynarray-fail.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-dynarray-fail.mtrace > $@; \
 	$(evaluate-test)
 
-tst-compathooks-on-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
-tst-compathooks-on-mcheck-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
-tst-compathooks-on-malloc-check-ENV = \
+tst-compathooks-on-ENV += LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-compathooks-on-mcheck-ENV += LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-compathooks-on-malloc-check-ENV += \
 	LD_PRELOAD=$(objpfx)libc_malloc_debug.so
-tst-mallocstate-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
-tst-mallocstate-malloc-check-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-mallocstate-ENV += LD_PRELOAD=$(objpfx)libc_malloc_debug.so
 
 # The test needs malloc_get_state/malloc_set_state which is in
 # libc_malloc_debug.so.
 $(objpfx)tst-mallocstate: $(objpfx)libc_malloc_debug.so
 $(objpfx)tst-mallocstate-malloc-check: $(objpfx)libc_malloc_debug.so
-tst-mallocstate-threaded-main-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-mallocstate-threaded-main-ENV += LD_PRELOAD=$(objpfx)libc_malloc_debug.so
 $(objpfx)tst-mallocstate-threaded-main: $(objpfx)libc_malloc_debug.so
-tst-mallocstate-threaded-worker-ENV = LD_PRELOAD=$(objpfx)libc_malloc_debug.so
+tst-mallocstate-threaded-worker-ENV += LD_PRELOAD=$(objpfx)libc_malloc_debug.so
 $(objpfx)tst-mallocstate-threaded-worker: $(objpfx)libc_malloc_debug.so
 
 $(objpfx)tst-aligned-alloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
@@ -522,18 +521,18 @@  $(objpfx)tst-aligned-alloc-random-thread.out: $(objpfx)tst-aligned_alloc-lib.so
 $(objpfx)tst-aligned-alloc-random-thread-cross.out: $(objpfx)tst-aligned_alloc-lib.so
 $(objpfx)tst-malloc-random.out: $(objpfx)tst-aligned_alloc-lib.so
 
-tst-aligned-alloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
-tst-aligned-alloc-random-thread-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
-tst-aligned-alloc-random-thread-cross-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
-tst-malloc-random-ENV = LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+tst-aligned-alloc-random-ENV += LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+tst-aligned-alloc-random-thread-ENV += LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+tst-aligned-alloc-random-thread-cross-ENV += LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
+tst-malloc-random-ENV += LD_PRELOAD=$(objpfx)tst-aligned_alloc-lib.so
 
-tst-free-aligned-sized-trace-ENV = MALLOC_TRACE=$(objpfx)tst-free-aligned-sized-mem.mtrace \
+tst-free-aligned-sized-trace-ENV += MALLOC_TRACE=$(objpfx)tst-free-aligned-sized-mem.mtrace \
 	LD_PRELOAD=$(objpfx)libc_malloc_debug.so
 $(objpfx)tst-free-aligned-sized-mtrace.out: $(objpfx)tst-free-aligned-sized-trace.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-free-aligned-sized-mem.mtrace > $@; \
 	$(evaluate-test)
 
-tst-free-sized-trace-ENV = MALLOC_TRACE=$(objpfx)tst-free-sized-mem.mtrace \
+tst-free-sized-trace-ENV += MALLOC_TRACE=$(objpfx)tst-free-sized-mem.mtrace \
 	LD_PRELOAD=$(objpfx)libc_malloc_debug.so
 $(objpfx)tst-free-sized-mtrace.out: $(objpfx)tst-free-sized-trace.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-free-sized-mem.mtrace > $@; \
diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile
index 57461fded7..2270027286 100644
--- a/sysdeps/unix/sysv/linux/aarch64/Makefile
+++ b/sysdeps/unix/sysv/linux/aarch64/Makefile
@@ -70,21 +70,18 @@  $(objpfx)tst-bti-ld-debug-dlopen.out: $(objpfx)tst-bti-mod-unprot.so
 $(objpfx)tst-bti-permissive-dlopen.out: $(objpfx)tst-bti-mod-unprot.so
 
 $(objpfx)tst-bti-abort-unprot-preload.out: $(objpfx)tst-bti-mod-unprot-preload.so
-tst-bti-abort-unprot-preload-ENV = \
-  GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1 \
-  LD_PRELOAD=$(objpfx)tst-bti-mod-unprot-preload.so
+$(eval $(call tunable-add,tst-bti-abort-unprot-preload,glibc.cpu.aarch64_bti=1))
+tst-bti-abort-unprot-preload-ENV += LD_PRELOAD=$(objpfx)tst-bti-mod-unprot-preload.so
 
 $(objpfx)tst-bti-dep-prot-preload.out: $(objpfx)tst-bti-mod-prot-preload.so
 # The 'fun' function will be provided by the preload library
 LDFLAGS-tst-bti-dep-prot-preload = -Wl,--unresolved-symbols=ignore-all
-tst-bti-dep-prot-preload-ENV = \
-  GLIBC_TUNABLES=glibc.cpu.aarch64_bti=0 \
-  LD_PRELOAD=$(objpfx)tst-bti-mod-prot-preload.so
+$(eval $(call tunable-add,tst-bti-dep-prot-preload,glibc.cpu.aarch64_bti=0))
+tst-bti-dep-prot-preload-ENV += LD_PRELOAD=$(objpfx)tst-bti-mod-prot-preload.so
 
 $(objpfx)tst-bti-permissive-preload.out: $(objpfx)tst-bti-mod-unprot-preload.so
-tst-bti-permissive-preload-ENV = \
-  GLIBC_TUNABLES=glibc.cpu.aarch64_bti=0 \
-  LD_PRELOAD=$(objpfx)tst-bti-mod-unprot-preload.so
+$(eval $(call tunable-add,tst-bti-permissive-preload,glibc.cpu.aarch64_bti=0))
+tst-bti-permissive-preload-ENV += LD_PRELOAD=$(objpfx)tst-bti-mod-unprot-preload.so
 
 CFLAGS-tst-bti-abort-unprot.o += -mbranch-protection=none
 CFLAGS-tst-bti-ld-debug-exe.o += -mbranch-protection=none
@@ -93,17 +90,17 @@  CFLAGS-tst-bti-mod-unprot.os += -mbranch-protection=none
 CFLAGS-tst-bti-mod-unprot-preload.os += -mbranch-protection=none
 CFLAGS-tst-bti-mod-unprot-audit.os += -mbranch-protection=none
 
-tst-bti-abort-imm-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
-tst-bti-abort-transitive-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
-tst-bti-abort-unprot-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
-tst-bti-dep-prot-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
-tst-bti-dlopen-imm-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
-tst-bti-dlopen-prot-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
-tst-bti-dlopen-transitive-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
+$(eval $(call tunable-add,tst-bti-abort-imm,glibc.cpu.aarch64_bti=1))
+$(eval $(call tunable-add,tst-bti-abort-transitive,glibc.cpu.aarch64_bti=1))
+$(eval $(call tunable-add,tst-bti-abort-unprot,glibc.cpu.aarch64_bti=1))
+$(eval $(call tunable-add,tst-bti-dep-prot,glibc.cpu.aarch64_bti=1))
+$(eval $(call tunable-add,tst-bti-dlopen-imm,glibc.cpu.aarch64_bti=1))
+$(eval $(call tunable-add,tst-bti-dlopen-prot,glibc.cpu.aarch64_bti=1))
+$(eval $(call tunable-add,tst-bti-dlopen-transitive,glibc.cpu.aarch64_bti=1))
 
-tst-bti-permissive-imm-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=0
-tst-bti-permissive-transitive-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=0
-tst-bti-permissive-dlopen-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=0
+$(eval $(call tunable-add,tst-bti-permissive-imm,glibc.cpu.aarch64_bti=0))
+$(eval $(call tunable-add,tst-bti-permissive-transitive,glibc.cpu.aarch64_bti=0))
+$(eval $(call tunable-add,tst-bti-permissive-dlopen,glibc.cpu.aarch64_bti=0))
 
 $(objpfx)tst-bti-unprot-audit.out: $(objpfx)tst-bti-mod-unprot-audit.so
 tst-bti-unprot-audit-ARGS = -- $(host-test-program-cmd)
@@ -112,7 +109,7 @@  $(objpfx)tst-bti-prot-audit.out: $(objpfx)tst-bti-mod-prot-audit.so
 $(objpfx)tst-bti-prot-audit: $(objpfx)tst-bti-mod-prot.so
 tst-bti-prot-audit-ARGS = -- $(host-test-program-cmd)
 
-tst-bti-permissive-audit-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=0
+$(eval $(call tunable-add,tst-bti-permissive-audit,glibc.cpu.aarch64_bti=0))
 $(objpfx)tst-bti-permissive-audit.out: $(objpfx)tst-bti-mod-unprot-audit.so
 $(objpfx)tst-bti-permissive-audit: $(objpfx)tst-bti-mod.so
 tst-bti-permissive-audit-ARGS = -- $(host-test-program-cmd)
@@ -131,7 +128,7 @@  tests-static += \
   tst-bti-abort-static \
   # tests-static
 
-tst-bti-abort-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_bti=1
+$(eval $(call tunable-add,tst-bti-abort-static,glibc.cpu.aarch64_bti=1))
 CFLAGS-tst-bti-abort-static.o += -mbranch-protection=none
 
 $(objpfx)tst-bti-ld-debug-%.out: $(..)elf/tst-dl-debug-protect.sh $(objpfx)tst-bti-ld-debug-%
@@ -224,37 +221,37 @@  LDFLAGS-tst-gcs-optional-static-on += -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-optional-static-off += -Wl,-z,gcs=never
 LDFLAGS-tst-gcs-override-static += -Wl,-z,gcs=never
 
-tst-gcs-disabled-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
-tst-gcs-enforced-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
-tst-gcs-enforced-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
-tst-gcs-optional-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
-tst-gcs-optional-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
-tst-gcs-override-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3
+$(eval $(call tunable-add,tst-gcs-disabled,glibc.cpu.aarch64_gcs=0))
+$(eval $(call tunable-add,tst-gcs-enforced,glibc.cpu.aarch64_gcs=1))
+$(eval $(call tunable-add,tst-gcs-enforced-abort,glibc.cpu.aarch64_gcs=1))
+$(eval $(call tunable-add,tst-gcs-optional-on,glibc.cpu.aarch64_gcs=2))
+$(eval $(call tunable-add,tst-gcs-optional-off,glibc.cpu.aarch64_gcs=2))
+$(eval $(call tunable-add,tst-gcs-override,glibc.cpu.aarch64_gcs=3))
 
-tst-gcs-disabled-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
-tst-gcs-enforced-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
-tst-gcs-enforced-static-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
-tst-gcs-optional-static-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
-tst-gcs-optional-static-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
-tst-gcs-override-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3
+$(eval $(call tunable-add,tst-gcs-disabled-static,glibc.cpu.aarch64_gcs=0))
+$(eval $(call tunable-add,tst-gcs-enforced-static,glibc.cpu.aarch64_gcs=1))
+$(eval $(call tunable-add,tst-gcs-enforced-static-abort,glibc.cpu.aarch64_gcs=1))
+$(eval $(call tunable-add,tst-gcs-optional-static-on,glibc.cpu.aarch64_gcs=2))
+$(eval $(call tunable-add,tst-gcs-optional-static-off,glibc.cpu.aarch64_gcs=2))
+$(eval $(call tunable-add,tst-gcs-override-static,glibc.cpu.aarch64_gcs=3))
 
 LDFLAGS-tst-gcs-execv += -Wl,-z,gcs=always
-tst-gcs-execv-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
+$(eval $(call tunable-add,tst-gcs-execv,glibc.cpu.aarch64_gcs=1))
 tst-gcs-execv-ARGS = -- $(host-test-program-cmd)
 LDFLAGS-tst-gcs-fork += -Wl,-z,gcs=always
-tst-gcs-fork-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
+$(eval $(call tunable-add,tst-gcs-fork,glibc.cpu.aarch64_gcs=2))
 
 LDFLAGS-tst-gcs-lock += -Wl,-z,gcs=always
-tst-gcs-lock-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
+$(eval $(call tunable-add,tst-gcs-lock,glibc.cpu.aarch64_gcs=1))
 LDFLAGS-tst-gcs-lock-ptrace += -Wl,-z,gcs=always
-tst-gcs-lock-ptrace-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
+$(eval $(call tunable-add,tst-gcs-lock-ptrace,glibc.cpu.aarch64_gcs=1))
 tst-gcs-lock-ptrace-ARGS = -- $(host-test-program-cmd)
 LDFLAGS-tst-gcs-lock-static += -Wl,-z,gcs=always
-tst-gcs-lock-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
+$(eval $(call tunable-add,tst-gcs-lock-static,glibc.cpu.aarch64_gcs=1))
 LDFLAGS-tst-gcs-unlock += -Wl,-z,gcs=always
-tst-gcs-unlock-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
+$(eval $(call tunable-add,tst-gcs-unlock,glibc.cpu.aarch64_gcs=2))
 LDFLAGS-tst-gcs-unlock-static += -Wl,-z,gcs=always
-tst-gcs-unlock-static-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
+$(eval $(call tunable-add,tst-gcs-unlock-static,glibc.cpu.aarch64_gcs=2))
 
 # force one of the dependencies to be unmarked
 LDFLAGS-tst-gcs-mod2.so += -Wl,-z,gcs=never
@@ -283,10 +280,10 @@  $(objpfx)tst-gcs-mod1.so: $(objpfx)tst-gcs-mod2.so
 $(objpfx)tst-gcs-ld-debug-both: $(objpfx)tst-gcs-mod2.so
 $(objpfx)tst-gcs-ld-debug-shared: $(objpfx)tst-gcs-mod1.so $(objpfx)tst-gcs-mod3.so
 
-tst-gcs-shared-disabled-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
-tst-gcs-shared-enforced-abort-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
-tst-gcs-shared-optional-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
-tst-gcs-shared-override-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3
+$(eval $(call tunable-add,tst-gcs-shared-disabled,glibc.cpu.aarch64_gcs=0))
+$(eval $(call tunable-add,tst-gcs-shared-enforced-abort,glibc.cpu.aarch64_gcs=1))
+$(eval $(call tunable-add,tst-gcs-shared-optional,glibc.cpu.aarch64_gcs=2))
+$(eval $(call tunable-add,tst-gcs-shared-override,glibc.cpu.aarch64_gcs=3))
 
 LDFLAGS-tst-gcs-dlopen-disabled = -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-dlopen-enforced = -Wl,-z,gcs=always
@@ -296,11 +293,11 @@  LDFLAGS-tst-gcs-dlopen-override = -Wl,-z,gcs=always
 LDFLAGS-tst-gcs-ld-debug-exe = -Wl,-z,gcs=never
 LDFLAGS-tst-gcs-ld-debug-both = -Wl,-z,gcs=never
 
-tst-gcs-dlopen-disabled-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
-tst-gcs-dlopen-enforced-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1
-tst-gcs-dlopen-optional-on-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
-tst-gcs-dlopen-optional-off-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2
-tst-gcs-dlopen-override-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3
+$(eval $(call tunable-add,tst-gcs-dlopen-disabled,glibc.cpu.aarch64_gcs=0))
+$(eval $(call tunable-add,tst-gcs-dlopen-enforced,glibc.cpu.aarch64_gcs=1))
+$(eval $(call tunable-add,tst-gcs-dlopen-optional-on,glibc.cpu.aarch64_gcs=2))
+$(eval $(call tunable-add,tst-gcs-dlopen-optional-off,glibc.cpu.aarch64_gcs=2))
+$(eval $(call tunable-add,tst-gcs-dlopen-override,glibc.cpu.aarch64_gcs=3))
 
 $(objpfx)tst-gcs-dlopen-disabled.out: $(objpfx)tst-gcs-mod2.so
 $(objpfx)tst-gcs-dlopen-enforced.out: $(objpfx)tst-gcs-mod2.so
@@ -311,7 +308,7 @@  $(objpfx)tst-gcs-ld-debug-dlopen.out: $(objpfx)tst-gcs-mod2.so
 
 LDFLAGS-tst-gcs-noreturn = -Wl,-z,gcs=always
 
-tst-gcs-noreturn-ENV = GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0
+$(eval $(call tunable-add,tst-gcs-noreturn,glibc.cpu.aarch64_gcs=0))
 
 $(objpfx)tst-gcs-ld-debug-%.out: $(..)elf/tst-dl-debug-protect.sh $(objpfx)tst-gcs-ld-debug-%
 	$(SHELL) $< $(objpfx) '$(test-wrapper-env)' '$(rtld-prefix)' \
@@ -329,18 +326,14 @@  $(objpfx)tst-gcs-preload-enforced-abort: $(objpfx)tst-gcs-mod1.so
 $(objpfx)tst-gcs-preload-optional: $(objpfx)tst-gcs-mod1.so
 $(objpfx)tst-gcs-preload-override: $(objpfx)tst-gcs-mod1.so
 
-tst-gcs-preload-disabled-ENV = \
-  GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=0 \
-  LD_PRELOAD=$(objpfx)tst-gcs-mod1.so
-tst-gcs-preload-enforced-abort-ENV = \
-  GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=1 \
-  LD_PRELOAD=$(objpfx)tst-gcs-mod1.so
-tst-gcs-preload-optional-ENV = \
-  GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=2 \
-  LD_PRELOAD=$(objpfx)tst-gcs-mod1.so
-tst-gcs-preload-override-ENV = \
-  GLIBC_TUNABLES=glibc.cpu.aarch64_gcs=3 \
-  LD_PRELOAD=$(objpfx)tst-gcs-mod1.so
+$(eval $(call tunable-add,tst-gcs-preload-disabled,glibc.cpu.aarch64_gcs=0))
+tst-gcs-preload-disabled-ENV += LD_PRELOAD=$(objpfx)tst-gcs-mod1.so
+$(eval $(call tunable-add,tst-gcs-preload-enforced-abort,glibc.cpu.aarch64_gcs=1))
+tst-gcs-preload-enforced-abort-ENV += LD_PRELOAD=$(objpfx)tst-gcs-mod1.so
+$(eval $(call tunable-add,tst-gcs-preload-optional,glibc.cpu.aarch64_gcs=2))
+tst-gcs-preload-optional-ENV += LD_PRELOAD=$(objpfx)tst-gcs-mod1.so
+$(eval $(call tunable-add,tst-gcs-preload-override,glibc.cpu.aarch64_gcs=3))
+tst-gcs-preload-override-ENV += LD_PRELOAD=$(objpfx)tst-gcs-mod1.so
 
 LDFLAGS-tst-gcs-audit1.so += -Wl,-z,gcs=never