enum hog_clock_type { // Count elapsed time using the CLOCK_PROCESS_CPUTIME_ID clock.
CPU_HOG_CLOCK_PROCESS, // Count elapsed time using system wallclock time.
CPU_HOG_CLOCK_WALL,
};
struct cpu_hogger { char *cgroup;
pid_t pid; long usage;
};
/* Try to keep niced CPU usage as constrained to hog_cpu as possible */
nice(1);
hog_cpus_timed(cpucg, ¶m); exit(0);
} else {
waitpid(pid, &status, 0); if (!WIFEXITED(status)) goto cleanup;
staticint
run_cpucg_weight_test( constchar *root,
pid_t (*spawn_child)(conststruct cpu_hogger *child), int (*validate)(conststruct cpu_hogger *children, int num_children))
{ int ret = KSFT_FAIL, i; char *parent = NULL; struct cpu_hogger children[3] = {};
parent = cg_name(root, "cpucg_test_0"); if (!parent) goto cleanup;
if (cg_create(parent)) goto cleanup;
if (cg_write(parent, "cgroup.subtree_control", "+cpu")) goto cleanup;
for (i = 0; i < ARRAY_SIZE(children); i++) {
children[i].cgroup = cg_name_indexed(parent, "cpucg_child", i); if (!children[i].cgroup) goto cleanup;
if (cg_create(children[i].cgroup)) goto cleanup;
if (cg_write_numeric(children[i].cgroup, "cpu.weight", 50 * (i + 1))) goto cleanup;
}
for (i = 0; i < ARRAY_SIZE(children); i++) {
pid_t pid = spawn_child(&children[i]); if (pid <= 0) goto cleanup;
children[i].pid = pid;
}
for (i = 0; i < ARRAY_SIZE(children); i++) { int retcode;
waitpid(children[i].pid, &retcode, 0); if (!WIFEXITED(retcode)) goto cleanup; if (WEXITSTATUS(retcode)) goto cleanup;
}
for (i = 0; i < ARRAY_SIZE(children); i++)
children[i].usage = cg_read_key_long(children[i].cgroup, "cpu.stat", "usage_usec");
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);
staticint
underprovision_validate(conststruct 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;
}
ret = KSFT_PASS;
cleanup: return ret;
}
/* *First,thistestcreatesthefollowinghierarchy: *A *A/Bcpu.weight=50 *A/Ccpu.weight=100 *A/Dcpu.weight=150 * *Aseparateprocessisthencreatedforeachchildcgroupwhichspawnsa *singlethreadthathogsaCPU.Thetestcaseisonlyrunonsystemsthat *haveatleastonecoreper-threadinthechildprocesses. * *Onceallofthechildrenhaveexited,weverifythateachchildcgroup *hadroughlythesameruntimedespitehavingdifferentcpu.weight.
*/ staticint test_cpucg_weight_underprovisioned(constchar *root)
{ // Only run the test if there are enough cores to avoid overprovisioning // the system. if (get_nprocs() < 4) return KSFT_SKIP;
child_usage = cg_read_key_long(child, "cpu.stat", "usage_usec"); if (child_usage <= 0) goto cleanup; if (!values_close(child_usage, nested_leaf_usage, 1)) goto cleanup;
ret = KSFT_PASS;
cleanup: for (i = 0; i < ARRAY_SIZE(leaf); i++) {
cg_destroy(leaf[i].cgroup);
free(leaf[i].cgroup);
}
cg_destroy(child);
free(child);
cg_destroy(parent);
free(parent);
/* *Thistestcreatesacgroupwithsomemaximumvaluewithinaperiod,and *verifiesthataprocessinthecgroupisnotoverscheduled.
*/ staticint test_cpucg_max(constchar *root)
{ int ret = KSFT_FAIL; long quota_usec = 1000; long default_period_usec = 100000; /* cpu.max's default period */ long duration_seconds = 1;
long duration_usec = duration_seconds * USEC_PER_SEC; long usage_usec, n_periods, remainder_usec, expected_usage_usec; char *cpucg; char quota_buf[32];
if (!values_close(usage_usec, expected_usage_usec, 10)) goto cleanup;
ret = KSFT_PASS;
cleanup:
cg_destroy(cpucg);
free(cpucg);
return ret;
}
/* *Thistestverifiesthataprocessinsideofanestedcgroupwhoseparent *grouphasacpu.maxvalueset,isproperlythrottled.
*/ staticint test_cpucg_max_nested(constchar *root)
{ int ret = KSFT_FAIL; long quota_usec = 1000; long default_period_usec = 100000; /* cpu.max's default period */ long duration_seconds = 1;
long duration_usec = duration_seconds * USEC_PER_SEC; long usage_usec, n_periods, remainder_usec, expected_usage_usec; char *parent, *child; char quota_buf[32];
int main(int argc, char *argv[])
{ char root[PATH_MAX]; int i, ret = EXIT_SUCCESS;
if (cg_find_unified_root(root, sizeof(root), NULL))
ksft_exit_skip("cgroup v2 isn't mounted\n");
if (cg_read_strstr(root, "cgroup.subtree_control", "cpu")) if (cg_write(root, "cgroup.subtree_control", "+cpu"))
ksft_exit_skip("Failed to set cpu controller\n");
for (i = 0; i < ARRAY_SIZE(tests); i++) { switch (tests[i].fn(root)) { case KSFT_PASS:
ksft_test_result_pass("%s\n", tests[i].name); break; case KSFT_SKIP:
ksft_test_result_skip("%s\n", tests[i].name); break; default:
ret = EXIT_FAILURE;
ksft_test_result_fail("%s\n", tests[i].name); break;
}
}
return ret;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet am 2026-10-11)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.