diff --git a/posix/Makefile b/posix/Makefile
index a650abf598..c0e224236a 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -253,7 +253,8 @@ tests := \
tst-boost \
tst-chmod \
tst-cpucount \
- tst-cpuset \
+ tst-cpuset-dynamic \
+ tst-cpuset-static \
tst-dir \
tst-execl1 \
tst-execl2 \
diff --git a/posix/tst-cpuset-dynamic.c b/posix/tst-cpuset-dynamic.c
new file mode 100644
index 0000000000..6e0f06dfd8
--- /dev/null
+++ b/posix/tst-cpuset-dynamic.c
@@ -0,0 +1,63 @@
+/* Test that CPU_* macros comply with their specifications.
+
+ Copyright (C) 2024 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
+
+#define LOCAL_NUM_CPUS 2048
+#define LOCAL_CPU_SETSIZE LOCAL_NUM_CPUS / 8
+
+#define PREPARE_CPU_SET(X) \
+ X = CPU_ALLOC (LOCAL_NUM_CPUS);
+
+/* Create a mapping so that access to the page before the cpuset generates a
+ fault. The aim is to check the behavior for negative values since the
+ interface accepts signed int. */
+#define PREPARE_CPU_SET_TO_FAULT_BEFORE(X) \
+ size_t local_sz_##X = CPU_ALLOC_SIZE(LOCAL_NUM_CPUS); \
+ struct support_next_to_fault local_##X = support_next_to_fault_allocate_before(local_sz_##X); \
+ X = (cpu_set_t *) local_##X.buffer;
+
+/* Create a mapping so that access to the page after the cpuset generates a
+ fault. The aim is to check the behavior for values above CPU count since the
+ interface accepts signed int. */
+#define PREPARE_CPU_SET_TO_FAULT(X) \
+ size_t local_sz_##X = CPU_ALLOC_SIZE(LOCAL_NUM_CPUS); \
+ struct support_next_to_fault local_##X = support_next_to_fault_allocate(local_sz_##X); \
+ X = (cpu_set_t *) local_##X.buffer;
+
+#define GET_SIZE() (size_t) CPU_ALLOC_SIZE(LOCAL_NUM_CPUS)
+
+#define LOCAL_CPU_ZERO(sz, cpusetp) CPU_ZERO_S(sz, cpusetp)
+#define LOCAL_CPU_SET(cpu, sz, cpusetp) CPU_SET_S(cpu, sz, cpusetp)
+#define LOCAL_CPU_CLR(cpu, sz, cpusetp) CPU_CLR_S(cpu, sz, cpusetp)
+#define LOCAL_CPU_ISSET(cpu, sz, cpusetp) CPU_ISSET_S(cpu, sz, cpusetp)
+#define LOCAL_CPU_COUNT(sz, cpusetp) CPU_COUNT_S(sz, cpusetp)
+#define LOCAL_CPU_AND(sz, destsetp, srcsetp1, srcsetp2) \
+ CPU_AND_S(sz, destsetp, srcsetp1, srcsetp2)
+#define LOCAL_CPU_OR(sz, destsetp, srcsetp1, srcsetp2) \
+ CPU_OR_S(sz, destsetp, srcsetp1, srcsetp2)
+#define LOCAL_CPU_XOR(sz, destsetp, srcsetp1, srcsetp2) \
+ CPU_XOR_S(sz, destsetp, srcsetp1, srcsetp2)
+#define LOCAL_CPU_EQUAL(sz, setp1, setp2) CPU_EQUAL_S(sz, setp1, setp2)
+
+#define CLEAN_CPU_SET(cpusetp) CPU_FREE(cpusetp)
+#define CLEAN_CPU_SET_TO_FAULT_BEFORE(X) support_next_to_fault_free(&local_##X)
+#define CLEAN_CPU_SET_TO_FAULT(X) support_next_to_fault_free(&local_##X)
+
+#include "tst-cpuset-skeleton.c"
diff --git a/posix/tst-cpuset-skeleton.c b/posix/tst-cpuset-skeleton.c
new file mode 100644
index 0000000000..2c04989c0d
--- /dev/null
+++ b/posix/tst-cpuset-skeleton.c
@@ -0,0 +1,123 @@
+/* Test that CPU_* macros comply with their specifications.
+
+ Copyright (C) 2024 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
+#include
+#include
+
+#include
+#include
+
+static int
+do_test (void)
+{
+ cpu_set_t *cpusetp_A = NULL;
+ cpu_set_t *cpusetp_B = NULL;
+ cpu_set_t *cpusetp_C = NULL;
+
+ size_t setsz __attribute__ ((unused)) = GET_SIZE();
+
+ TEST_VERIFY (CPU_ALLOC_SIZE (-1) == 0);
+ TEST_VERIFY (CPU_ALLOC_SIZE (0) == 0);
+ TEST_VERIFY (CPU_ALLOC_SIZE (1) == sizeof (__cpu_mask));
+ TEST_VERIFY (CPU_ALLOC_SIZE (INT_MAX) > 0);
+
+ PREPARE_CPU_SET_TO_FAULT_BEFORE(cpusetp_A);
+ PREPARE_CPU_SET_TO_FAULT(cpusetp_B);
+ PREPARE_CPU_SET(cpusetp_C);
+
+ /* Bad actor access, negative CPU number */
+ LOCAL_CPU_SET (-1, setsz, cpusetp_A);
+ TEST_VERIFY (!LOCAL_CPU_ISSET (-1, setsz, cpusetp_A));
+
+ /* Bad actor access, above CPU number */
+ LOCAL_CPU_SET (LOCAL_NUM_CPUS, setsz, cpusetp_B);
+ TEST_VERIFY (!LOCAL_CPU_ISSET (LOCAL_NUM_CPUS, setsz, cpusetp_B));
+
+ LOCAL_CPU_ZERO (setsz, cpusetp_A);
+ LOCAL_CPU_ZERO (setsz, cpusetp_B);
+ LOCAL_CPU_ZERO (setsz, cpusetp_C);
+
+ for (int cpu = 0; cpu < LOCAL_NUM_CPUS; cpu += 2)
+ {
+ /* Set A = 0x55..55 */
+ LOCAL_CPU_SET (cpu, setsz, cpusetp_A);
+ TEST_VERIFY (LOCAL_CPU_ISSET (cpu, setsz, cpusetp_A));
+ }
+ for (int cpu = 1; cpu < LOCAL_NUM_CPUS; cpu += 2)
+ {
+ /* Set B = 0xAA..AA */
+ LOCAL_CPU_SET (cpu, setsz, cpusetp_B);
+ TEST_VERIFY (LOCAL_CPU_ISSET (cpu, setsz, cpusetp_B));
+ }
+
+ /* Ensure CPU_COUNT matches expected count */
+ TEST_VERIFY (LOCAL_CPU_COUNT (setsz, cpusetp_A) == LOCAL_CPU_COUNT (setsz, cpusetp_B));
+ TEST_VERIFY (LOCAL_CPU_COUNT (setsz, cpusetp_A) == LOCAL_NUM_CPUS / 2);
+
+ LOCAL_CPU_AND (setsz, cpusetp_C, cpusetp_A, cpusetp_B);
+ for (int cpu = 0; cpu < LOCAL_NUM_CPUS; cpu++)
+ {
+ /* A setsz, B == 0 */
+ TEST_VERIFY (!LOCAL_CPU_ISSET (cpu, setsz, cpusetp_C));
+ }
+
+ LOCAL_CPU_OR (setsz, cpusetp_C, cpusetp_A, cpusetp_B);
+ for (int cpu = 0; cpu < LOCAL_NUM_CPUS; cpu++)
+ {
+ /* A | B == 0xFF..FF */
+ TEST_VERIFY (LOCAL_CPU_ISSET (cpu, setsz, cpusetp_C));
+ }
+
+ /* Check that CPU_ZERO actually does something */
+ TEST_VERIFY (LOCAL_CPU_COUNT (setsz, cpusetp_C) == LOCAL_NUM_CPUS);
+ LOCAL_CPU_ZERO (setsz, cpusetp_C);
+ TEST_VERIFY (LOCAL_CPU_COUNT (setsz, cpusetp_C) == 0);
+
+ LOCAL_CPU_XOR (setsz, cpusetp_C, cpusetp_A, cpusetp_A);
+ for (int cpu = 0; cpu < LOCAL_NUM_CPUS; cpu++)
+ {
+ /* A ^ A == 0 */
+ TEST_VERIFY (!LOCAL_CPU_ISSET (cpu, setsz, cpusetp_C));
+ }
+
+ LOCAL_CPU_XOR (setsz, cpusetp_C, cpusetp_A, cpusetp_B);
+ for (int cpu = 0; cpu < LOCAL_NUM_CPUS; cpu++)
+ {
+ /* C = A ^ B == 0xFF..FF */
+ TEST_VERIFY (LOCAL_CPU_ISSET (cpu, setsz, cpusetp_C));
+ }
+
+ for (int cpu = 1; cpu < LOCAL_NUM_CPUS; cpu += 2)
+ {
+ /* C = 0x55..55 */
+ LOCAL_CPU_CLR (cpu, setsz, cpusetp_C);
+ TEST_VERIFY (!LOCAL_CPU_ISSET (cpu, setsz, cpusetp_C));
+ }
+
+ TEST_VERIFY (LOCAL_CPU_EQUAL (setsz, cpusetp_A, cpusetp_C));
+
+ CLEAN_CPU_SET(cpusetp_C);
+ CLEAN_CPU_SET_TO_FAULT(cpusetp_B);
+ CLEAN_CPU_SET_TO_FAULT_BEFORE(cpusetp_A);
+
+ return 0;
+}
+
+#include
diff --git a/posix/tst-cpuset-static.c b/posix/tst-cpuset-static.c
new file mode 100644
index 0000000000..ad4c40e422
--- /dev/null
+++ b/posix/tst-cpuset-static.c
@@ -0,0 +1,61 @@
+/* Test that CPU_* macros comply with their specifications.
+
+ Copyright (C) 2024 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
+
+#define LOCAL_NUM_CPUS CPU_SETSIZE
+
+/* Create a mapping so that access to the page before the cpuset generates a
+ fault. The aim is to check the behavior for negative values since the
+ interface accepts signed int. */
+#define PREPARE_CPU_SET_TO_FAULT_BEFORE(X) \
+ struct support_next_to_fault local_##X = support_next_to_fault_allocate_before(sizeof(*X)); \
+ X = (cpu_set_t *) local_##X.buffer;
+
+/* Create a mapping so that access to the page after the cpuset generates a
+ fault. The aim is to check the behavior for values above CPU count since the
+ interface accepts signed int. */
+#define PREPARE_CPU_SET_TO_FAULT(X) \
+ struct support_next_to_fault local_##X = support_next_to_fault_allocate(sizeof(*X)); \
+ X = (cpu_set_t *) local_##X.buffer;
+
+#define PREPARE_CPU_SET(X) \
+ cpu_set_t local_##X = {}; \
+ X = &local_##X;
+
+#define GET_SIZE() (size_t) sizeof (cpu_set_t)
+
+#define LOCAL_CPU_ZERO(sz, cpusetp) CPU_ZERO(cpusetp)
+#define LOCAL_CPU_SET(cpu, sz, cpusetp) CPU_SET(cpu, cpusetp)
+#define LOCAL_CPU_CLR(cpu, sz, cpusetp) CPU_CLR(cpu, cpusetp)
+#define LOCAL_CPU_ISSET(cpu, sz, cpusetp) CPU_ISSET(cpu, cpusetp)
+#define LOCAL_CPU_COUNT(sz, cpusetp) CPU_COUNT(cpusetp)
+#define LOCAL_CPU_AND(sz, destsetp, srcsetp1, srcsetp2) \
+ CPU_AND(destsetp, srcsetp1, srcsetp2)
+#define LOCAL_CPU_OR(sz, destsetp, srcsetp1, srcsetp2) \
+ CPU_OR(destsetp, srcsetp1, srcsetp2)
+#define LOCAL_CPU_XOR(sz, destsetp, srcsetp1, srcsetp2) \
+ CPU_XOR(destsetp, srcsetp1, srcsetp2)
+#define LOCAL_CPU_EQUAL(sz, setp1, setp2) CPU_EQUAL(setp1, setp2)
+
+#define CLEAN_CPU_SET(X)
+#define CLEAN_CPU_SET_TO_FAULT_BEFORE(X) support_next_to_fault_free(&local_##X)
+#define CLEAN_CPU_SET_TO_FAULT(X) support_next_to_fault_free(&local_##X)
+
+#include "tst-cpuset-skeleton.c"
diff --git a/posix/tst-cpuset.c b/posix/tst-cpuset.c
deleted file mode 100644
index d736793222..0000000000
--- a/posix/tst-cpuset.c
+++ /dev/null
@@ -1,82 +0,0 @@
-#include
-#include
-
-static int
-do_test (void)
-{
- int result = 0;
-
- cpu_set_t s1;
- cpu_set_t s2;
- cpu_set_t s3;
-
- CPU_ZERO (&s1);
- CPU_SET (0, &s1);
-
- CPU_ZERO (&s2);
- CPU_SET (0, &s2);
- CPU_SET (1, &s2);
-
- CPU_AND (&s3, &s1, &s2);
- if (! CPU_EQUAL (&s3, &s1))
- {
- puts ("result of CPU_AND wrong");
- result = 1;
- }
-
- CPU_OR (&s3, &s1, &s2);
- if (! CPU_EQUAL (&s3, &s2))
- {
- puts ("result of CPU_OR wrong");
- result = 1;
- }
-
- CPU_XOR (&s3, &s1, &s2);
- if (CPU_COUNT (&s3) != 1)
- {
- puts ("result of CPU_XOR wrong");
- result = 1;
- }
-
- cpu_set_t *vs1 = CPU_ALLOC (2048);
- cpu_set_t *vs2 = CPU_ALLOC (2048);
- cpu_set_t *vs3 = CPU_ALLOC (2048);
- size_t vssize = CPU_ALLOC_SIZE (2048);
-
- CPU_ZERO_S (vssize, vs1);
- CPU_SET_S (0, vssize, vs1);
-
- CPU_ZERO_S (vssize, vs2);
- CPU_SET_S (0, vssize, vs2);
- CPU_SET_S (2047, vssize, vs2);
-
- CPU_AND_S (vssize, vs3, vs1, vs2);
- if (! CPU_EQUAL_S (vssize, vs3, vs1))
- {
- puts ("result of CPU_AND_S wrong");
- result = 1;
- }
-
- CPU_OR_S (vssize, vs3, vs1, vs2);
- if (! CPU_EQUAL_S (vssize, vs3, vs2))
- {
- puts ("result of CPU_OR_S wrong");
- result = 1;
- }
-
- CPU_XOR_S (vssize, vs3, vs1, vs2);
- if (CPU_COUNT_S (vssize, vs3) != 1)
- {
- puts ("result of CPU_XOR_S wrong");
- result = 1;
- }
-
- CPU_FREE (vs1);
- CPU_FREE (vs2);
- CPU_FREE (vs3);
-
- return result;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"