Skip to content

Commit 08e11ed

Browse files
committed
tools/power turbostat: Fix --cpu-set 1 regression on HT systems
When the "--cpu-set" option limits turbostat to run on a higher numbered HT sibling, it exits upon dividing by zero. This is because the HT support handles higher numbered siblings at the same time as lower numbered siblings. But when that lower number sibling is dis-allowed, the higher numbered sibling is never processed. The result is a time delta of 0, which results in a divide by 0 for any of the "per-second" metrics. Enhance the HT enumeration code to record all siblings (up to SMT4). Consult this complete HT sibling list to determine when to process an HT sibling, and when to skip it. Fixes: a2b4d0f ("tools/power turbostat: Favor cpu# over core#") Signed-off-by: Len Brown <len.brown@intel.com>
1 parent 2c52f94 commit 08e11ed

1 file changed

Lines changed: 55 additions & 15 deletions

File tree

tools/power/x86/turbostat/turbostat.c

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,6 +2449,22 @@ int cpu_is_not_allowed(int cpu)
24492449

24502450
#define PER_THREAD_PARAMS struct thread_data *t, struct core_data *c, struct pkg_data *p
24512451

2452+
int has_allowed_lower_ht_sibling(int cpu)
2453+
{
2454+
int i;
2455+
2456+
for (i = 0; i <= cpus[cpu].ht_id; ++i) {
2457+
int sibling_cpu_id = cpus[cpu].ht_sibling_cpu_id[i];
2458+
2459+
if (sibling_cpu_id == cpu)
2460+
return 0;
2461+
2462+
if (!cpu_is_not_allowed(sibling_cpu_id))
2463+
return 1;
2464+
}
2465+
return 0;
2466+
}
2467+
24522468
int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pkg_data *),
24532469
struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
24542470
{
@@ -2466,7 +2482,7 @@ int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pk
24662482
if (cpu_is_not_allowed(cpu))
24672483
continue;
24682484

2469-
if (cpus[cpu].ht_id > 0) /* skip HT sibling */
2485+
if (has_allowed_lower_ht_sibling(cpu)) /* skip HT sibling */
24702486
continue;
24712487

24722488
t = &thread_base[cpu];
@@ -2475,12 +2491,18 @@ int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pk
24752491

24762492
retval |= func(t, c, p);
24772493

2478-
/* Handle HT sibling now */
2494+
/* Handle other HT siblings now */
24792495
int i;
24802496

2481-
for (i = MAX_HT_ID; i > 0; --i) { /* ht_id 0 is self */
2497+
for (i = 0; i <= MAX_HT_ID; ++i) {
24822498
int sibling_cpu_id = cpus[cpu].ht_sibling_cpu_id[i];
24832499

2500+
if (sibling_cpu_id < 0)
2501+
break;
2502+
2503+
if (sibling_cpu_id == cpu)
2504+
continue;
2505+
24842506
if (cpu_is_not_allowed(sibling_cpu_id))
24852507
continue;
24862508

@@ -6178,11 +6200,11 @@ int set_thread_siblings(struct cpu_topology *thiscpu)
61786200
int cpu = thiscpu->cpu_id;
61796201
int offset = topo.max_cpu_num + 1;
61806202
size_t size;
6181-
int thread_id = 0;
6203+
int ht_id = 0;
61826204

61836205
thiscpu->put_ids = CPU_ALLOC((topo.max_cpu_num + 1));
61846206
if (thiscpu->ht_id < 0)
6185-
thiscpu->ht_id = thread_id++;
6207+
thiscpu->ht_id = 0; /* first CPU in core */
61866208
if (!thiscpu->put_ids)
61876209
return -1;
61886210

@@ -6206,13 +6228,9 @@ int set_thread_siblings(struct cpu_topology *thiscpu)
62066228
sib_core = get_core_id(so);
62076229
if (sib_core == thiscpu->core_id) {
62086230
CPU_SET_S(so, size, thiscpu->put_ids);
6209-
if ((so != cpu) && (cpus[so].ht_id < 0)) {
6210-
cpus[so].ht_id = thread_id;
6211-
cpus[cpu].ht_sibling_cpu_id[thread_id] = so;
6212-
if (debug)
6213-
fprintf(stderr, "%s: cpu%d.ht_sibling_cpu_id[%d] = %d\n", __func__, cpu, thread_id, so);
6214-
thread_id += 1;
6215-
}
6231+
cpus[so].ht_id = ht_id;
6232+
cpus[cpu].ht_sibling_cpu_id[ht_id] = so;
6233+
ht_id += 1;
62166234
}
62176235
}
62186236
}
@@ -6245,7 +6263,7 @@ int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *,
62456263
if (cpu_is_not_allowed(cpu))
62466264
continue;
62476265

6248-
if (cpus[cpu].ht_id > 0) /* skip HT sibling */
6266+
if (has_allowed_lower_ht_sibling(cpu)) /* skip HT sibling */
62496267
continue;
62506268

62516269
t = &thread_base[cpu];
@@ -6260,9 +6278,15 @@ int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *,
62606278
/* Handle HT sibling now */
62616279
int i;
62626280

6263-
for (i = MAX_HT_ID; i > 0; --i) { /* ht_id 0 is self */
6281+
for (i = 0; i <= MAX_HT_ID; ++i) {
62646282
int sibling_cpu_id = cpus[cpu].ht_sibling_cpu_id[i];
62656283

6284+
if (sibling_cpu_id < 0)
6285+
break;
6286+
6287+
if (sibling_cpu_id == cpu)
6288+
continue;
6289+
62666290
if (cpu_is_not_allowed(sibling_cpu_id))
62676291
continue;
62686292

@@ -9517,6 +9541,8 @@ void topology_probe(bool startup)
95179541
cpu_present_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
95189542
CPU_ZERO_S(cpu_present_setsize, cpu_present_set);
95199543
for_all_proc_cpus(mark_cpu_present);
9544+
if (debug)
9545+
print_cpu_set("present set", cpu_present_set);
95209546

95219547
/*
95229548
* Allocate and initialize cpu_possible_set
@@ -9527,6 +9553,8 @@ void topology_probe(bool startup)
95279553
cpu_possible_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
95289554
CPU_ZERO_S(cpu_possible_setsize, cpu_possible_set);
95299555
initialize_cpu_set_from_sysfs(cpu_possible_set, "/sys/devices/system/cpu", "possible");
9556+
if (debug)
9557+
print_cpu_set("possible set", cpu_possible_set);
95309558

95319559
/*
95329560
* Allocate and initialize cpu_effective_set
@@ -9537,6 +9565,8 @@ void topology_probe(bool startup)
95379565
cpu_effective_setsize = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
95389566
CPU_ZERO_S(cpu_effective_setsize, cpu_effective_set);
95399567
update_effective_set(startup);
9568+
if (debug)
9569+
print_cpu_set("effective set", cpu_effective_set);
95409570

95419571
/*
95429572
* Allocate and initialize cpu_allowed_set
@@ -9580,6 +9610,8 @@ void topology_probe(bool startup)
95809610

95819611
CPU_SET_S(i, cpu_allowed_setsize, cpu_allowed_set);
95829612
}
9613+
if (debug)
9614+
print_cpu_set("allowed set", cpu_allowed_set);
95839615

95849616
if (!CPU_COUNT_S(cpu_allowed_setsize, cpu_allowed_set))
95859617
err(-ENODEV, "No valid cpus found");
@@ -9683,12 +9715,18 @@ void topology_probe(bool startup)
96839715
return;
96849716

96859717
for (i = 0; i <= topo.max_cpu_num; ++i) {
9718+
int ht_id;
9719+
96869720
if (cpu_is_not_present(i))
96879721
continue;
96889722
fprintf(outf,
9689-
"cpu %d pkg %d die %d l3 %d node %d lnode %d core %d thread %d\n",
9723+
"cpu %d pkg %d die %d l3 %d node %d lnode %d core %d ht_id %d",
96909724
i, cpus[i].package_id, cpus[i].die_id, cpus[i].l3_id,
96919725
cpus[i].physical_node_id, cpus[i].logical_node_id, cpus[i].core_id, cpus[i].ht_id);
9726+
fprintf(outf, " siblings");
9727+
for (ht_id = 0; ht_id <= MAX_HT_ID; ++ht_id)
9728+
fprintf(outf, " %d", cpus[i].ht_sibling_cpu_id[ht_id]);
9729+
fprintf(outf, "\n");
96929730
}
96939731

96949732
}
@@ -9829,6 +9867,8 @@ void topology_update(void)
98299867
topo.allowed_cores = 0;
98309868
topo.allowed_packages = 0;
98319869
for_all_cpus(update_topo, ODD_COUNTERS);
9870+
if (debug)
9871+
fprintf(stderr, "allowed_cpus %d allowed_cores %d allowed_packages %d\n", topo.allowed_cpus, topo.allowed_cores, topo.allowed_packages);
98329872
}
98339873

98349874
void setup_all_buffers(bool startup)

0 commit comments

Comments
 (0)