diff --git a/glibc-RHEL-119424-1.patch b/glibc-RHEL-119424-1.patch new file mode 100644 index 0000000..53a3d42 --- /dev/null +++ b/glibc-RHEL-119424-1.patch @@ -0,0 +1,349 @@ +commit e41aabcc93edd6c9a6acb15212b2783d8a7ec5a3 +Author: Siddhesh Poyarekar +Date: Mon Dec 16 08:14:09 2024 -0500 + + tests: Verify inheritance of cpu affinity + + Add a couple of tests to verify that CPU affinity set using + sched_setaffinity and pthread_setaffinity_np are inherited by a child + process and child thread. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Adhemerval Zanella + +diff --git a/nptl/Makefile b/nptl/Makefile +index 7139f76827b5ffe6..4d3271ba71f0bc65 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -312,6 +312,7 @@ tests = \ + tst-mutexpi11 \ + tst-mutexpi12 \ + tst-once5 \ ++ tst-pthread-affinity-inheritance \ + tst-pthread-attr-affinity \ + tst-pthread-attr-affinity-fail \ + tst-pthread-attr-sigmask \ +diff --git a/nptl/tst-pthread-affinity-inheritance.c b/nptl/tst-pthread-affinity-inheritance.c +new file mode 100644 +index 0000000000000000..c020530dd916dea1 +--- /dev/null ++++ b/nptl/tst-pthread-affinity-inheritance.c +@@ -0,0 +1,71 @@ ++/* CPU Affinity inheritance test - pthread_{gs}etaffinity_np. ++ Copyright The GNU Toolchain Authors. ++ 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 ++ . */ ++ ++/* See top level comment in nptl/tst-skeleton-affinity-inheritance.c for a ++ description of this test. */ ++#include ++#include ++#include ++#include ++#include ++ ++static void ++set_my_affinity (size_t size, const cpu_set_t *set) ++{ ++ int ret = pthread_setaffinity_np (pthread_self (), size, set); ++ ++ if (ret != 0) ++ FAIL ("pthread_setaffinity_np returned %d (%s)", ret, strerror (ret)); ++} ++ ++static void ++verify_my_affinity (int nproc, size_t size, const cpu_set_t *expected_set) ++{ ++ cpu_set_t *set = CPU_ALLOC (nproc); ++ cpu_set_t *xor_set = CPU_ALLOC (nproc); ++ ++ if (set == NULL || xor_set== NULL) ++ FAIL_EXIT1 ("verify_my_affinity: Failed to allocate cpuset: %m\n"); ++ ++ int ret = pthread_getaffinity_np (pthread_self (), size, set); ++ if (ret != 0) ++ FAIL ("pthread_getaffinity_np returned %d (%s)", ret, strerror (ret)); ++ ++ CPU_XOR_S (size, xor_set, expected_set, set); ++ ++ int cpucount = CPU_COUNT_S (size, xor_set); ++ ++ if (cpucount > 0) ++ { ++ FAIL ("Affinity mask not inherited, " ++ "following %d CPUs mismatched in the expected and actual sets: ", ++ cpucount); ++ for (int cur = 0; cur < nproc && cpucount >= 0; cur++) ++ if (CPU_ISSET_S (size, cur, xor_set)) ++ { ++ printf ("%d ", cur); ++ cpucount--; ++ } ++ printf ("\n"); ++ } ++ ++ CPU_FREE (set); ++ CPU_FREE (xor_set); ++} ++ ++#include "tst-skeleton-affinity-inheritance.c" +diff --git a/nptl/tst-skeleton-affinity-inheritance.c b/nptl/tst-skeleton-affinity-inheritance.c +new file mode 100644 +index 0000000000000000..6de6d9c9428a0c9d +--- /dev/null ++++ b/nptl/tst-skeleton-affinity-inheritance.c +@@ -0,0 +1,152 @@ ++/* CPU Affinity inheritance test - common infrastructure. ++ Copyright The GNU Toolchain Authors. ++ 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 ++ . */ ++ ++/* The general idea of this test is to verify that the set of CPUs assigned to ++ a task gets inherited by a child (thread or process) of that task. This is ++ a framework that is included by specific APIs for the test, e.g. ++ sched_getaffinity/sched_setaffinity and ++ pthread_setaffinity_np/pthread_getaffinity_np. This is a framework, actual ++ tests entry points are in nptl/tst-pthread-affinity-inheritance.c and ++ sysdeps/unix/sysv/linux/tst-sched-affinity-inheritance.c. ++ ++ There are two levels to the test with two different CPU masks. The first ++ level verifies that the affinity set on the main process is inherited by its ++ children subprocess or thread. The second level verifies that a subprocess ++ or subthread passes on its affinity to their respective subprocess or ++ subthread. We set a slightly different mask in both levels to ensure that ++ they're both inherited. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct test_param ++{ ++ int nproc; ++ cpu_set_t *set; ++ size_t size; ++ bool entry; ++}; ++ ++void __attribute__((noinline)) ++set_cpu_mask (struct test_param *param, bool entry) ++{ ++ int cpus = param->nproc; ++ ++ /* Less CPUS for the first level, if that's possible. */ ++ if (entry && cpus > 1) ++ cpus--; ++ ++ CPU_ZERO_S (param->size, param->set); ++ while (cpus > 0) ++ CPU_SET_S (--cpus, param->size, param->set); ++ ++ if (CPU_COUNT_S (param->size, param->set) == 0) ++ FAIL_EXIT1 ("Failed to add any CPUs to the affinity set\n"); ++} ++ ++static void * ++child_test (void *arg) ++{ ++ struct test_param *param = arg; ++ ++ printf ("%d:%d child\n", getpid (), gettid ()); ++ verify_my_affinity (param->nproc, param->size, param->set); ++ return NULL; ++} ++ ++void * ++do_one_test (void *arg) ++{ ++ void *(*child) (void *) = NULL; ++ struct test_param *param = arg; ++ bool entry = param->entry; ++ ++ if (entry) ++ { ++ printf ("%d:%d Start test run\n", getpid (), gettid ()); ++ /* First level: Reenter as a subprocess and then as a subthread. */ ++ child = do_one_test; ++ set_cpu_mask (param, true); ++ set_my_affinity (param->size, param->set); ++ param->entry = false; ++ } ++ else ++ { ++ /* Verification for the first level. */ ++ verify_my_affinity (param->nproc, param->size, param->set); ++ ++ /* Launch the second level test, launching CHILD_TEST as a subprocess and ++ then as a subthread. Use a different mask to see if it gets ++ inherited. */ ++ child = child_test; ++ set_cpu_mask (param, false); ++ set_my_affinity (param->size, param->set); ++ } ++ ++ /* Verify that a child of a thread/process inherits the affinity mask. */ ++ printf ("%d:%d%sdo_one_test: fork\n", getpid (), gettid (), ++ entry ? " " : " "); ++ int pid = xfork (); ++ ++ if (pid == 0) ++ { ++ child (param); ++ return NULL; ++ } ++ ++ xwaitpid (pid, NULL, 0); ++ ++ /* Verify that a subthread of a thread/process inherits the affinity ++ mask. */ ++ printf ("%d:%d%sdo_one_test: thread\n", getpid (), gettid (), ++ entry ? " " : " "); ++ pthread_t t = xpthread_create (NULL, child, param); ++ xpthread_join (t); ++ ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ int num_cpus = get_nprocs (); ++ ++ struct test_param param = ++ { ++ .nproc = num_cpus, ++ .set = CPU_ALLOC (num_cpus), ++ .size = CPU_ALLOC_SIZE (num_cpus), ++ .entry = true, ++ }; ++ ++ if (param.set == NULL) ++ FAIL_EXIT1 ("error: CPU_ALLOC (%d) failed\n", num_cpus); ++ ++ do_one_test (¶m); ++ ++ CPU_FREE (param.set); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index a4b692febb3e87d9..a28b15ea16bc5045 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -231,6 +231,7 @@ tests += \ + tst-process_mrelease \ + tst-quota \ + tst-rlimit-infinity \ ++ tst-sched-affinity-inheritance \ + tst-sched_setattr \ + tst-sched_setattr-thread \ + tst-scm_rights \ +diff --git a/sysdeps/unix/sysv/linux/tst-sched-affinity-inheritance.c b/sysdeps/unix/sysv/linux/tst-sched-affinity-inheritance.c +new file mode 100644 +index 0000000000000000..fe0297f743d55e2f +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-sched-affinity-inheritance.c +@@ -0,0 +1,71 @@ ++/* CPU Affinity inheritance test - sched_{gs}etaffinity. ++ Copyright The GNU Toolchain Authors. ++ 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 ++ . */ ++ ++/* See top level comment in nptl/tst-skeleton-affinity-inheritance.c for a ++ description of this test. */ ++ ++#include ++#include ++#include ++#include ++ ++static void ++set_my_affinity (size_t size, const cpu_set_t *set) ++{ ++ int ret = sched_setaffinity (0, size, set); ++ ++ if (ret != 0) ++ FAIL ("sched_setaffinity returned %d (%s)", ret, strerror (ret)); ++} ++ ++static void ++verify_my_affinity (int nproc, size_t size, const cpu_set_t *expected_set) ++{ ++ cpu_set_t *set = CPU_ALLOC (nproc); ++ cpu_set_t *xor_set = CPU_ALLOC (nproc); ++ ++ if (set == NULL || xor_set== NULL) ++ FAIL_EXIT1 ("verify_my_affinity: Failed to allocate cpuset: %m\n"); ++ ++ int ret = sched_getaffinity (0, size, set); ++ if (ret != 0) ++ FAIL ("sched_getaffinity returned %d (%s)", ret, strerror (ret)); ++ ++ CPU_XOR_S (size, xor_set, expected_set, set); ++ ++ int cpucount = CPU_COUNT_S (size, xor_set); ++ ++ if (cpucount > 0) ++ { ++ FAIL ("Affinity mask not inherited, " ++ "following %d CPUs mismatched in the expected and actual sets:\n", ++ cpucount); ++ for (int cur = 0; cur < nproc && cpucount >= 0; cur++) ++ if (CPU_ISSET_S (size, cur, xor_set)) ++ { ++ printf ("%d ", cur); ++ cpucount--; ++ } ++ printf ("\n"); ++ } ++ ++ CPU_FREE (set); ++ CPU_FREE (xor_set); ++} ++ ++#include diff --git a/glibc-RHEL-119424-2.patch b/glibc-RHEL-119424-2.patch new file mode 100644 index 0000000..be715f9 --- /dev/null +++ b/glibc-RHEL-119424-2.patch @@ -0,0 +1,103 @@ +commit 09ea1afec75ed0d41cb0da27a9df1b8c3dd56ddc +Author: Stefan Liebler +Date: Fri Jan 10 12:55:50 2025 -0500 + + affinity-inheritance: Overallocate CPU sets + + Some kernels on S390 appear to return a CPU affinity mask based on + configured processors rather than the ones online. Overallocate the CPU + set to match that, but operate only on the ones online. + + Signed-off-by: Siddhesh Poyarekar + Co-authored-by: Siddhesh Poyarekar + +diff --git a/nptl/tst-pthread-affinity-inheritance.c b/nptl/tst-pthread-affinity-inheritance.c +index c020530dd916dea1..153fc904dfe14c9d 100644 +--- a/nptl/tst-pthread-affinity-inheritance.c ++++ b/nptl/tst-pthread-affinity-inheritance.c +@@ -34,10 +34,11 @@ set_my_affinity (size_t size, const cpu_set_t *set) + } + + static void +-verify_my_affinity (int nproc, size_t size, const cpu_set_t *expected_set) ++verify_my_affinity (int nproc, int nproc_configured, size_t size, ++ const cpu_set_t *expected_set) + { +- cpu_set_t *set = CPU_ALLOC (nproc); +- cpu_set_t *xor_set = CPU_ALLOC (nproc); ++ cpu_set_t *set = CPU_ALLOC (nproc_configured); ++ cpu_set_t *xor_set = CPU_ALLOC (nproc_configured); + + if (set == NULL || xor_set== NULL) + FAIL_EXIT1 ("verify_my_affinity: Failed to allocate cpuset: %m\n"); +diff --git a/nptl/tst-skeleton-affinity-inheritance.c b/nptl/tst-skeleton-affinity-inheritance.c +index 6de6d9c9428a0c9d..926f49622990e9e4 100644 +--- a/nptl/tst-skeleton-affinity-inheritance.c ++++ b/nptl/tst-skeleton-affinity-inheritance.c +@@ -42,6 +42,7 @@ + struct test_param + { + int nproc; ++ int nproc_configured; + cpu_set_t *set; + size_t size; + bool entry; +@@ -70,7 +71,8 @@ child_test (void *arg) + struct test_param *param = arg; + + printf ("%d:%d child\n", getpid (), gettid ()); +- verify_my_affinity (param->nproc, param->size, param->set); ++ verify_my_affinity (param->nproc, param->nproc_configured, param->size, ++ param->set); + return NULL; + } + +@@ -93,7 +95,8 @@ do_one_test (void *arg) + else + { + /* Verification for the first level. */ +- verify_my_affinity (param->nproc, param->size, param->set); ++ verify_my_affinity (param->nproc, param->nproc_configured, param->size, ++ param->set); + + /* Launch the second level test, launching CHILD_TEST as a subprocess and + then as a subthread. Use a different mask to see if it gets +@@ -129,13 +132,17 @@ do_one_test (void *arg) + static int + do_test (void) + { ++ /* Large enough in case the kernel decides to return the larger mask. This ++ seems to happen on some kernels for S390x. */ ++ int num_configured_cpus = get_nprocs_conf (); + int num_cpus = get_nprocs (); + + struct test_param param = + { + .nproc = num_cpus, +- .set = CPU_ALLOC (num_cpus), +- .size = CPU_ALLOC_SIZE (num_cpus), ++ .nproc_configured = num_configured_cpus, ++ .set = CPU_ALLOC (num_configured_cpus), ++ .size = CPU_ALLOC_SIZE (num_configured_cpus), + .entry = true, + }; + +diff --git a/sysdeps/unix/sysv/linux/tst-sched-affinity-inheritance.c b/sysdeps/unix/sysv/linux/tst-sched-affinity-inheritance.c +index fe0297f743d55e2f..8a42d275fce35e84 100644 +--- a/sysdeps/unix/sysv/linux/tst-sched-affinity-inheritance.c ++++ b/sysdeps/unix/sysv/linux/tst-sched-affinity-inheritance.c +@@ -34,10 +34,11 @@ set_my_affinity (size_t size, const cpu_set_t *set) + } + + static void +-verify_my_affinity (int nproc, size_t size, const cpu_set_t *expected_set) ++verify_my_affinity (int nproc, int nproc_configured, size_t size, ++ const cpu_set_t *expected_set) + { +- cpu_set_t *set = CPU_ALLOC (nproc); +- cpu_set_t *xor_set = CPU_ALLOC (nproc); ++ cpu_set_t *set = CPU_ALLOC (nproc_configured); ++ cpu_set_t *xor_set = CPU_ALLOC (nproc_configured); + + if (set == NULL || xor_set== NULL) + FAIL_EXIT1 ("verify_my_affinity: Failed to allocate cpuset: %m\n"); diff --git a/glibc-RHEL-119424-3.patch b/glibc-RHEL-119424-3.patch new file mode 100644 index 0000000..d97c4c0 --- /dev/null +++ b/glibc-RHEL-119424-3.patch @@ -0,0 +1,20 @@ +commit 71b49e299dbe22853095119da5064303e1d6b9ff +Author: Florian Weimer +Date: Tue Jan 21 10:36:58 2025 +0100 + + nptl: Include in tst-skeleton-affinity-inheritance.c + + The file uses the identifiers bool, false, true. + +diff --git a/nptl/tst-skeleton-affinity-inheritance.c b/nptl/tst-skeleton-affinity-inheritance.c +index 926f49622990e9e4..e1f328ae265b2bfb 100644 +--- a/nptl/tst-skeleton-affinity-inheritance.c ++++ b/nptl/tst-skeleton-affinity-inheritance.c +@@ -32,6 +32,7 @@ + they're both inherited. */ + + #include ++#include + #include + #include + #include