Received: by 2002:a05:6a10:6d10:0:0:0:0 with SMTP id gq16csp976221pxb; Fri, 22 Apr 2022 15:46:01 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwDRQhEM0lUfBFC9YNceRJzx4Oe7301T2NiHG1Mfe6J3YyVxT2NU0n7ETV36diU1f7MXUGl X-Received: by 2002:a5d:8754:0:b0:64c:fc47:ab2d with SMTP id k20-20020a5d8754000000b0064cfc47ab2dmr3055064iol.137.1650667561473; Fri, 22 Apr 2022 15:46:01 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1650667561; cv=none; d=google.com; s=arc-20160816; b=AnEn4djs0BykZbWj3gwb+WVUiFqJlMxNt/KjH0YXloSuCWSDSXJayQt88Jvgb7PJuc hBiJhMDmggosCevsBaoIPBfqtyj9jvTLEsOLYs1GvmSY1gxjTYfytT0R+wmHu8wAeceN vg2FzU98APxjTfuMbTr9wzjEPXVMPUU1NCius9mVia8emh0gYhgIzqG5qYCvn0Gl+M1F 9yGEBk9Qh9pM6HxDbTJiCmpbK6kjw7yckzUPmPUP3d2n2A+ikVqJURCxbgr+QvPybGOb JHDKULNlgiVbuQf2U+Q7kM0gvRftpd1q7GsfwRZkGwgJF2MLUIIV8njN2SX+StTEoVxF DXKg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=mXE/v8JHTyVxf9dgekZsoHje3QpqCFbIJjMNc4DKNeY=; b=YA7ygFvJsBwKiaLglHDbtTWTRQzrmABebIH082Ir8IR5XW1c2jt5gaahoegrJ5Ux2u FHY5wxqYciZO/sxosNGKl5p2J5wpySP3UpG1l8cGCgB68Qkc6Ob0HYgcyaWWzBo/rPqY wSPgWtqhm0WBuW0N8G6eX7MOGJ3y6GJIn8kgAmWGgqTmBTRfwP9eg6EstgyevBtAU6ib nEZ98DMekB7dSQ9sWxAM+UloOub5JJnXbkgaHTcvHOLd3Oe3/4jJr4xcUeyBHVMWzATz ftxbqDoZ1biEqUrIUaa8jcKEs8XR0x8uNYEIfAAWNhmUh77o/gWv7a1U4EAll5ZWz0HB 5Gdg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id t20-20020a026414000000b0032853482c13si2983378jac.4.2022.04.22.15.46.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 15:46:01 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2081A3ECE8B; Fri, 22 Apr 2022 13:34:30 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233723AbiDVRja (ORCPT + 99 others); Fri, 22 Apr 2022 13:39:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233918AbiDVRjV (ORCPT ); Fri, 22 Apr 2022 13:39:21 -0400 Received: from mail-qt1-f175.google.com (mail-qt1-f175.google.com [209.85.160.175]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B92CD64FA; Fri, 22 Apr 2022 10:36:17 -0700 (PDT) Received: by mail-qt1-f175.google.com with SMTP id x24so5993037qtq.11; Fri, 22 Apr 2022 10:36:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=mXE/v8JHTyVxf9dgekZsoHje3QpqCFbIJjMNc4DKNeY=; b=koBlbJoht58beorrsGvuuphDI0lniCciWuEnL+dMo+Zu6QF1Q2qbIDXYkqdJup/Btg atVIzFvRvNdYhC+Je6UATIMNm8B5gD0dQ4IZf4A3NlNCFGtBbmXrOiNL8MmAUTQLtske 1sxsKX806nghIVHFloKpjKeC+x5TD/627jSVn4Z/tuonR7SCsX5rS+F5ScVGo9YXLIiD UeEh/te3DaBqtCy66l4a/Ln48h42A3I0Yd8Uvlpgq5W8GRJYP9Wx7PPS65zpaXrXvdyZ FXHmWCrj+DyYFFMw83aXRv2NFmUvinoz95sPKjuhWmoXpSe63lkgunyYIqmPvnnLdBMD WY0g== X-Gm-Message-State: AOAM5329bzGLVzvsCD5q8nA0IqOjAI8LmP1kWKjsakpqckTSHCn9rtvT SejdJo5ly1Exk+N4e/xvvJM= X-Received: by 2002:ac8:6998:0:b0:2f1:ea20:96ae with SMTP id o24-20020ac86998000000b002f1ea2096aemr4090123qtq.89.1650648872334; Fri, 22 Apr 2022 10:34:32 -0700 (PDT) Received: from localhost (fwdproxy-ash-119.fbsv.net. [2a03:2880:20ff:77::face:b00c]) by smtp.gmail.com with ESMTPSA id c4-20020a37b304000000b0069ec13803adsm1173538qkf.7.2022.04.22.10.34.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 10:34:32 -0700 (PDT) From: David Vernet To: tj@kernel.org, lizefan.x@bytedance.com, hannes@cmpxchg.org Cc: cgroups@vger.kernel.org, peterz@infradead.org, mingo@redhat.com, linux-kernel@vger.kernel.org, kernel-team@fb.com Subject: [PATCH v2 4/4] cgroup: Add test_cpucg_weight_underprovisioned() testcase Date: Fri, 22 Apr 2022 10:33:53 -0700 Message-Id: <20220422173349.3394844-5-void@manifault.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220422173349.3394844-1-void@manifault.com> References: <20220422173349.3394844-1-void@manifault.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RDNS_NONE, SPF_HELO_NONE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org test_cpu.c includes testcases that validate the cgroup cpu controller. This patch adds a new testcase called test_cpucg_weight_underprovisioned() that verifies that processes with different cpu.weight that are all running on an underprovisioned system, still get roughly the same amount of cpu time. Because test_cpucg_weight_underprovisioned() is very similar to test_cpucg_weight_overprovisioned(), this patch also pulls the common logic into a separate helper function that is invoked from both testcases, and which uses function pointers to invoke the unique portions of the testcases. Signed-off-by: David Vernet --- tools/testing/selftests/cgroup/test_cpu.c | 155 ++++++++++++++++------ 1 file changed, 117 insertions(+), 38 deletions(-) diff --git a/tools/testing/selftests/cgroup/test_cpu.c b/tools/testing/selftests/cgroup/test_cpu.c index 8d901c06c79d..64f9ce91c992 100644 --- a/tools/testing/selftests/cgroup/test_cpu.c +++ b/tools/testing/selftests/cgroup/test_cpu.c @@ -19,6 +19,12 @@ enum hog_clock_type { CPU_HOG_CLOCK_WALL, }; +struct cpu_hogger { + char *cgroup; + pid_t pid; + long usage; +}; + struct cpu_hog_func_param { int nprocs; struct timespec ts; @@ -223,31 +229,15 @@ static int test_cpucg_stats(const char *root) return ret; } -/* - * First, this test creates the following hierarchy: - * A - * A/B cpu.weight = 50 - * A/C cpu.weight = 100 - * A/D cpu.weight = 150 - * - * A separate process is then created for each child cgroup which spawns as - * many threads as there are cores, and hogs each CPU as much as possible - * for some time interval. - * - * Once all of the children have exited, we verify that each child cgroup - * was given proportional runtime as informed by their cpu.weight. - */ -static int test_cpucg_weight_overprovisioned(const char *root) +static int +run_cpucg_weight_test( + const char *root, + pid_t (*spawn_child)(const struct cpu_hogger *child), + int (*validate)(const struct cpu_hogger *children, int num_children)) { - struct child { - char *cgroup; - pid_t pid; - long usage; - }; int ret = KSFT_FAIL, i; char *parent = NULL; - struct child children[3] = {NULL}; - long usage_seconds = 10; + struct cpu_hogger children[3] = {NULL}; parent = cg_name(root, "cpucg_test_0"); if (!parent) @@ -273,16 +263,7 @@ static int test_cpucg_weight_overprovisioned(const char *root) } for (i = 0; i < ARRAY_SIZE(children); i++) { - struct cpu_hog_func_param param = { - .nprocs = get_nprocs(), - .ts = { - .tv_sec = usage_seconds, - .tv_nsec = 0, - }, - .clock_type = CPU_HOG_CLOCK_WALL, - }; - pid_t pid = cg_run_nowait(children[i].cgroup, hog_cpus_timed, - (void *)¶m); + pid_t pid = spawn_child(&children[i]); if (pid <= 0) goto cleanup; children[i].pid = pid; @@ -302,7 +283,46 @@ static int test_cpucg_weight_overprovisioned(const char *root) children[i].usage = cg_read_key_long(children[i].cgroup, "cpu.stat", "usage_usec"); - for (i = 0; i < ARRAY_SIZE(children) - 1; i++) { + if (validate(children, ARRAY_SIZE(children))) + goto cleanup; + + ret = KSFT_PASS; +cleanup: + for (i = 0; i < ARRAY_SIZE(children); i++) { + cg_destroy(children[i].cgroup); + free(children[i].cgroup); + } + cg_destroy(parent); + free(parent); + + return ret; +} + +static pid_t weight_hog_ncpus(const struct cpu_hogger *child, int ncpus) +{ + long usage_seconds = 10; + struct cpu_hog_func_param param = { + .nprocs = ncpus, + .ts = { + .tv_sec = usage_seconds, + .tv_nsec = 0, + }, + .clock_type = CPU_HOG_CLOCK_WALL, + }; + return cg_run_nowait(child->cgroup, hog_cpus_timed, (void *)¶m); +} + +static pid_t weight_hog_all_cpus(const struct cpu_hogger *child) +{ + return weight_hog_ncpus(child, get_nprocs()); +} + +static int +overprovision_validate(const struct cpu_hogger *children, int num_children) +{ + int ret = KSFT_FAIL, i; + + for (i = 0; i < num_children - 1; i++) { long delta; if (children[i + 1].usage <= children[i].usage) @@ -315,16 +335,74 @@ static int test_cpucg_weight_overprovisioned(const char *root) ret = KSFT_PASS; cleanup: - for (i = 0; i < ARRAY_SIZE(children); i++) { - cg_destroy(children[i].cgroup); - free(children[i].cgroup); + return ret; +} + +/* + * First, this test creates the following hierarchy: + * A + * A/B cpu.weight = 50 + * A/C cpu.weight = 100 + * A/D cpu.weight = 150 + * + * A separate process is then created for each child cgroup which spawns as + * many threads as there are cores, and hogs each CPU as much as possible + * for some time interval. + * + * Once all of the children have exited, we verify that each child cgroup + * was given proportional runtime as informed by their cpu.weight. + */ +static int test_cpucg_weight_overprovisioned(const char *root) +{ + return run_cpucg_weight_test(root, weight_hog_all_cpus, + overprovision_validate); +} + +static pid_t weight_hog_one_cpu(const struct cpu_hogger *child) +{ + return weight_hog_ncpus(child, 1); +} + +static int +underprovision_validate(const struct cpu_hogger *children, int num_children) +{ + int ret = KSFT_FAIL, i; + + for (i = 0; i < num_children - 1; i++) { + if (!values_close(children[i + 1].usage, children[0].usage, 15)) + goto cleanup; } - cg_destroy(parent); - free(parent); + ret = KSFT_PASS; +cleanup: return ret; } +/* + * First, this test creates the following hierarchy: + * A + * A/B cpu.weight = 50 + * A/C cpu.weight = 100 + * A/D cpu.weight = 150 + * + * A separate process is then created for each child cgroup which spawns a + * single thread that hogs a CPU. The testcase is only run on systems that + * have at least one core per-thread in the child processes. + * + * Once all of the children have exited, we verify that each child cgroup + * had roughly the same runtime despite having different cpu.weight. + */ +static int test_cpucg_weight_underprovisioned(const char *root) +{ + // Only run the test if there are enough cores to avoid overprovisioning + // the system. + if (get_nprocs() < 4) + return KSFT_SKIP; + + return run_cpucg_weight_test(root, weight_hog_one_cpu, + underprovision_validate); +} + #define T(x) { x, #x } struct cpucg_test { int (*fn)(const char *root); @@ -333,6 +411,7 @@ struct cpucg_test { T(test_cpucg_subtree_control), T(test_cpucg_stats), T(test_cpucg_weight_overprovisioned), + T(test_cpucg_weight_underprovisioned), }; #undef T -- 2.30.2