Skip to content

Commit f638858

Browse files
committed
tools/power/turbostat: Handle cgroup v2 cpu limitation
CPUs can be isolated via cgroup settings and turbostat should avoid migrating to these CPUs, just like it does for the '-c' cpus. Introduce cpu_effective_set to save the cgroup cpu limitation info from /sys/fs/cgroup/cpuset.cpus.effective. And use cpu_allowed_set as the intersection of cpu_present_set, cpu_effective_set and cpu_subset. Signed-off-by: Zhang Rui <[email protected]>
1 parent 8c3dd2c commit f638858

File tree

1 file changed

+80
-15
lines changed

1 file changed

+80
-15
lines changed

tools/power/x86/turbostat/turbostat.c

Lines changed: 80 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -904,8 +904,8 @@ int backwards_count;
904904
char *progname;
905905

906906
#define CPU_SUBSET_MAXCPUS 1024 /* need to use before probe... */
907-
cpu_set_t *cpu_present_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset;
908-
size_t cpu_present_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size;
907+
cpu_set_t *cpu_present_set, *cpu_effective_set, *cpu_allowed_set, *cpu_affinity_set, *cpu_subset;
908+
size_t cpu_present_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affinity_setsize, cpu_subset_size;
909909
#define MAX_ADDED_COUNTERS 8
910910
#define MAX_ADDED_THREAD_COUNTERS 24
911911
#define BITMASK_SIZE 32
@@ -3419,6 +3419,10 @@ void free_all_buffers(void)
34193419
cpu_present_set = NULL;
34203420
cpu_present_setsize = 0;
34213421

3422+
CPU_FREE(cpu_effective_set);
3423+
cpu_effective_set = NULL;
3424+
cpu_effective_setsize = 0;
3425+
34223426
CPU_FREE(cpu_allowed_set);
34233427
cpu_allowed_set = NULL;
34243428
cpu_allowed_setsize = 0;
@@ -3741,6 +3745,46 @@ int for_all_proc_cpus(int (func) (int))
37413745
return 0;
37423746
}
37433747

3748+
#define PATH_EFFECTIVE_CPUS "/sys/fs/cgroup/cpuset.cpus.effective"
3749+
3750+
static char cpu_effective_str[1024];
3751+
3752+
static int update_effective_str(bool startup)
3753+
{
3754+
FILE *fp;
3755+
char *pos;
3756+
char buf[1024];
3757+
int ret;
3758+
3759+
if (cpu_effective_str[0] == '\0' && !startup)
3760+
return 0;
3761+
3762+
fp = fopen(PATH_EFFECTIVE_CPUS, "r");
3763+
if (!fp)
3764+
return 0;
3765+
3766+
pos = fgets(buf, 1024, fp);
3767+
if (!pos)
3768+
err(1, "%s: file read failed\n", PATH_EFFECTIVE_CPUS);
3769+
3770+
fclose(fp);
3771+
3772+
ret = strncmp(cpu_effective_str, buf, 1024);
3773+
if (!ret)
3774+
return 0;
3775+
3776+
strncpy(cpu_effective_str, buf, 1024);
3777+
return 1;
3778+
}
3779+
3780+
static void update_effective_set(bool startup)
3781+
{
3782+
update_effective_str(startup);
3783+
3784+
if (parse_cpu_str(cpu_effective_str, cpu_effective_set, cpu_effective_setsize))
3785+
err(1, "%s: cpu str malformat %s\n", PATH_EFFECTIVE_CPUS, cpu_effective_str);
3786+
}
3787+
37443788
void re_initialize(void)
37453789
{
37463790
free_all_buffers();
@@ -4257,6 +4301,10 @@ void turbostat_loop()
42574301
re_initialize();
42584302
goto restart;
42594303
}
4304+
if (update_effective_str(false)) {
4305+
re_initialize();
4306+
goto restart;
4307+
}
42604308
do_sleep();
42614309
if (snapshot_proc_sysfs_files())
42624310
goto restart;
@@ -5777,6 +5825,16 @@ void topology_probe(bool startup)
57775825
CPU_ZERO_S(cpu_present_setsize, cpu_present_set);
57785826
for_all_proc_cpus(mark_cpu_present);
57795827

5828+
/*
5829+
* Allocate and initialize cpu_effective_set
5830+
*/
5831+
cpu_effective_set = CPU_ALLOC((topo.max_cpu_num + 1));
5832+
if (cpu_effective_set == NULL)
5833+
err(3, "CPU_ALLOC");
5834+
cpu_effective_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
5835+
CPU_ZERO_S(cpu_effective_setsize, cpu_effective_set);
5836+
update_effective_set(startup);
5837+
57805838
/*
57815839
* Allocate and initialize cpu_allowed_set
57825840
*/
@@ -5787,30 +5845,37 @@ void topology_probe(bool startup)
57875845
CPU_ZERO_S(cpu_allowed_setsize, cpu_allowed_set);
57885846

57895847
/*
5790-
* Validate cpu_subset and update cpu_allowed_set.
5848+
* Validate and update cpu_allowed_set.
57915849
*
5792-
* Make sure all cpus in cpu_subset are also in cpu_present_set during startup,
5793-
* and give a warning when cpus in cpu_subset become unavailable at runtime.
5850+
* Make sure all cpus in cpu_subset are also in cpu_present_set during startup.
5851+
* Give a warning when cpus in cpu_subset become unavailable at runtime.
5852+
* Give a warning when cpus are not effective because of cgroup setting.
57945853
*
5795-
* cpu_allowed_set is the intersection of cpu_present_set and cpu_subset.
5854+
* cpu_allowed_set is the intersection of cpu_present_set/cpu_effective_set/cpu_subset.
57965855
*/
57975856
for (i = 0; i < CPU_SUBSET_MAXCPUS; ++i) {
5798-
if (!cpu_subset) {
5799-
if (CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set))
5800-
CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set);
5857+
if (cpu_subset && !CPU_ISSET_S(i, cpu_subset_size, cpu_subset))
58015858
continue;
5802-
}
5803-
if (CPU_ISSET_S(i, cpu_subset_size, cpu_subset)) {
5804-
if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) {
5805-
/* all cpus in cpu_subset must be in cpu_present_set during startup */
5859+
5860+
if (!CPU_ISSET_S(i, cpu_present_setsize, cpu_present_set)) {
5861+
if (cpu_subset) {
5862+
/* cpus in cpu_subset must be in cpu_present_set during startup */
58065863
if (startup)
58075864
err(1, "cpu%d not present", i);
58085865
else
58095866
fprintf(stderr, "cpu%d not present\n", i);
5810-
} else {
5811-
CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set);
58125867
}
5868+
continue;
58135869
}
5870+
5871+
if (CPU_COUNT_S(cpu_effective_setsize, cpu_effective_set)) {
5872+
if (!CPU_ISSET_S(i, cpu_effective_setsize, cpu_effective_set)) {
5873+
fprintf(stderr, "cpu%d not effective\n", i);
5874+
continue;
5875+
}
5876+
}
5877+
5878+
CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set);
58145879
}
58155880

58165881
if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set))

0 commit comments

Comments
 (0)