The test runs one hog thread per CPU in each of three cgroups weighted
1:2:3 and expects their CPU time in the same ratio. That holds when
each CPU runs one hog of every cgroup. On a NUMA machine the load
balancer leaves them less evenly spread, and the heaviest cgroup can
fall short of the tolerance.

Pin the hogs of each cgroup one per CPU: the test checks the weights,
not the load balancer.

Fixes: 6376b22cd0a3 ("cgroup: Add test_cpucg_weight_overprovisioned() testcase")

https://virtuozzo.atlassian.net/browse/VSTOR-152674
Feature: fix selftests

Signed-off-by: Eva Kurchatova <[email protected]>
---
 tools/testing/selftests/cgroup/test_cpu.c | 31 +++++++++++++++++++----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/tools/testing/selftests/cgroup/test_cpu.c 
b/tools/testing/selftests/cgroup/test_cpu.c
index a2b50af8e9ee..3385e75eed81 100644
--- a/tools/testing/selftests/cgroup/test_cpu.c
+++ b/tools/testing/selftests/cgroup/test_cpu.c
@@ -6,6 +6,7 @@
 #include <sys/wait.h>
 #include <errno.h>
 #include <pthread.h>
+#include <sched.h>
 #include <stdio.h>
 #include <time.h>
 #include <unistd.h>
@@ -30,6 +31,7 @@ struct cpu_hog_func_param {
        int nprocs;
        struct timespec ts;
        enum hog_clock_type clock_type;
+       bool pin;
 };
 
 /*
@@ -136,7 +138,13 @@ static int hog_cpus_timed(const char *cgroup, void *arg)
        struct timespec ts_run = param->ts;
        struct timespec ts_remaining = ts_run;
        struct timespec ts_start;
-       int i, ret;
+       pthread_attr_t attr;
+       cpu_set_t cpus, one;
+       int i, ret, cpu = -1;
+       /* Unpinned, as before, where the mask does not fit in a cpu_set_t */
+       bool pin = param->pin && !sched_getaffinity(0, sizeof(cpus), &cpus);
+
+       pthread_attr_init(&attr);
 
        ret = clock_gettime(CLOCK_MONOTONIC, &ts_start);
        if (ret != 0)
@@ -145,7 +153,18 @@ static int hog_cpus_timed(const char *cgroup, void *arg)
        for (i = 0; i < param->nprocs; i++) {
                pthread_t tid;
 
-               ret = pthread_create(&tid, NULL, &hog_cpu_thread_func, NULL);
+               /* One hog per allowed CPU, in turn */
+               if (pin) {
+                       do {
+                               cpu = (cpu + 1) % CPU_SETSIZE;
+                       } while (!CPU_ISSET(cpu, &cpus));
+                       CPU_ZERO(&one);
+                       CPU_SET(cpu, &one);
+                       ret = pthread_attr_setaffinity_np(&attr, sizeof(one), 
&one);
+                       if (ret != 0)
+                               return ret;
+               }
+               ret = pthread_create(&tid, &attr, &hog_cpu_thread_func, NULL);
                if (ret != 0)
                        return ret;
        }
@@ -372,7 +391,8 @@ run_cpucg_weight_test(
        return ret;
 }
 
-static pid_t weight_hog_ncpus(const struct cpu_hogger *child, int ncpus)
+static pid_t weight_hog_ncpus(const struct cpu_hogger *child, int ncpus,
+                             bool pin)
 {
        long usage_seconds = 10;
        struct cpu_hog_func_param param = {
@@ -382,13 +402,14 @@ static pid_t weight_hog_ncpus(const struct cpu_hogger 
*child, int ncpus)
                        .tv_nsec = 0,
                },
                .clock_type = CPU_HOG_CLOCK_WALL,
+               .pin = pin,
        };
        return cg_run_nowait(child->cgroup, hog_cpus_timed, (void *)&param);
 }
 
 static pid_t weight_hog_all_cpus(const struct cpu_hogger *child)
 {
-       return weight_hog_ncpus(child, get_nprocs());
+       return weight_hog_ncpus(child, get_nprocs(), true);
 }
 
 static int
@@ -434,7 +455,7 @@ static int test_cpucg_weight_overprovisioned(const char 
*root)
 
 static pid_t weight_hog_one_cpu(const struct cpu_hogger *child)
 {
-       return weight_hog_ncpus(child, 1);
+       return weight_hog_ncpus(child, 1, false);
 }
 
 static int
-- 
2.56.0

_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to