tools/power turbostat: fix bugs in --add option

When --add was used more than once, overflowed buffers
caused some counters to be stored on top of others,
corrupting the results.  Simplify the code by simply
reserving space for up to 16 added counters per each
cpu, core, package.

Per-cpu added counters were being printed only per-core.

Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
Len Brown 2017-02-09 22:22:13 -05:00
parent c470abd4fd
commit 678a3bd1b3
1 changed files with 53 additions and 37 deletions

View File

@ -154,6 +154,7 @@ char *progname;
cpu_set_t *cpu_present_set, *cpu_affinity_set; cpu_set_t *cpu_present_set, *cpu_affinity_set;
size_t cpu_present_setsize, cpu_affinity_setsize; size_t cpu_present_setsize, cpu_affinity_setsize;
#define MAX_ADDED_COUNTERS 16
struct thread_data { struct thread_data {
unsigned long long tsc; unsigned long long tsc;
@ -166,7 +167,7 @@ struct thread_data {
unsigned int flags; unsigned int flags;
#define CPU_IS_FIRST_THREAD_IN_CORE 0x2 #define CPU_IS_FIRST_THREAD_IN_CORE 0x2
#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4 #define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
unsigned long long counter[1]; unsigned long long counter[MAX_ADDED_COUNTERS];
} *thread_even, *thread_odd; } *thread_even, *thread_odd;
struct core_data { struct core_data {
@ -175,7 +176,7 @@ struct core_data {
unsigned long long c7; unsigned long long c7;
unsigned int core_temp_c; unsigned int core_temp_c;
unsigned int core_id; unsigned int core_id;
unsigned long long counter[1]; unsigned long long counter[MAX_ADDED_COUNTERS];
} *core_even, *core_odd; } *core_even, *core_odd;
struct pkg_data { struct pkg_data {
@ -200,7 +201,7 @@ struct pkg_data {
unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */ unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */ unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
unsigned int pkg_temp_c; unsigned int pkg_temp_c;
unsigned long long counter[1]; unsigned long long counter[MAX_ADDED_COUNTERS];
} *package_even, *package_odd; } *package_even, *package_odd;
#define ODD_COUNTERS thread_odd, core_odd, package_odd #define ODD_COUNTERS thread_odd, core_odd, package_odd
@ -228,9 +229,9 @@ struct msr_counter {
}; };
struct sys_counters { struct sys_counters {
unsigned int thread_counter_bytes; unsigned int added_thread_counters;
unsigned int core_counter_bytes; unsigned int added_core_counters;
unsigned int package_counter_bytes; unsigned int added_package_counters;
struct msr_counter *tp; struct msr_counter *tp;
struct msr_counter *cp; struct msr_counter *cp;
struct msr_counter *pp; struct msr_counter *pp;
@ -374,12 +375,6 @@ void print_header(void)
if (do_nhm_cstates) if (do_nhm_cstates)
outp += sprintf(outp, "\tCPU%%c1"); outp += sprintf(outp, "\tCPU%%c1");
if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
outp += sprintf(outp, "\tCPU%%c3");
if (do_nhm_cstates)
outp += sprintf(outp, "\tCPU%%c6");
if (do_snb_cstates)
outp += sprintf(outp, "\tCPU%%c7");
for (mp = sys.tp; mp; mp = mp->next) { for (mp = sys.tp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) { if (mp->format == FORMAT_RAW) {
@ -392,6 +387,14 @@ void print_header(void)
} }
} }
if (do_nhm_cstates && !do_slm_cstates && !do_knl_cstates)
outp += sprintf(outp, "\tCPU%%c3");
if (do_nhm_cstates)
outp += sprintf(outp, "\tCPU%%c6");
if (do_snb_cstates)
outp += sprintf(outp, "\tCPU%%c7");
if (do_dts) if (do_dts)
outp += sprintf(outp, "\tCoreTmp"); outp += sprintf(outp, "\tCoreTmp");
@ -635,9 +638,24 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (do_smi) if (do_smi)
outp += sprintf(outp, "\t%d", t->smi_count); outp += sprintf(outp, "\t%d", t->smi_count);
/* C1 */
if (do_nhm_cstates) if (do_nhm_cstates)
outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/t->tsc); outp += sprintf(outp, "\t%.2f", 100.0 * t->c1/t->tsc);
/* Added counters */
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
outp += sprintf(outp, "\t0x%08lx", (unsigned long) t->counter[i]);
else
outp += sprintf(outp, "\t0x%016llx", t->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
outp += sprintf(outp, "\t%lld", t->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/t->tsc);
}
}
/* print per-core data only for 1st thread in core */ /* print per-core data only for 1st thread in core */
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE)) if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
goto done; goto done;
@ -649,19 +667,6 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (do_snb_cstates) if (do_snb_cstates)
outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc); outp += sprintf(outp, "\t%.2f", 100.0 * c->c7/t->tsc);
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
outp += sprintf(outp, "\t0x%08lx", (unsigned long) t->counter[i]);
else
outp += sprintf(outp, "\t0x%016llx", t->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
outp += sprintf(outp, "\t%8lld", t->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * t->counter[i]/t->tsc);
}
}
if (do_dts) if (do_dts)
outp += sprintf(outp, "\t%d", c->core_temp_c); outp += sprintf(outp, "\t%d", c->core_temp_c);
@ -673,7 +678,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
else else
outp += sprintf(outp, "\t0x%016llx", c->counter[i]); outp += sprintf(outp, "\t0x%016llx", c->counter[i]);
} else if (mp->format == FORMAT_DELTA) { } else if (mp->format == FORMAT_DELTA) {
outp += sprintf(outp, "\t%8lld", c->counter[i]); outp += sprintf(outp, "\t%lld", c->counter[i]);
} else if (mp->format == FORMAT_PERCENT) { } else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/t->tsc); outp += sprintf(outp, "\t%.2f", 100.0 * c->counter[i]/t->tsc);
} }
@ -770,7 +775,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
else else
outp += sprintf(outp, "\t0x%016llx", p->counter[i]); outp += sprintf(outp, "\t0x%016llx", p->counter[i]);
} else if (mp->format == FORMAT_DELTA) { } else if (mp->format == FORMAT_DELTA) {
outp += sprintf(outp, "\t%8lld", p->counter[i]); outp += sprintf(outp, "\t%lld", p->counter[i]);
} else if (mp->format == FORMAT_PERCENT) { } else if (mp->format == FORMAT_PERCENT) {
outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/t->tsc); outp += sprintf(outp, "\t%.2f", 100.0 * p->counter[i]/t->tsc);
} }
@ -1036,7 +1041,6 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
p->gfx_rc6_ms = 0; p->gfx_rc6_ms = 0;
p->gfx_mhz = 0; p->gfx_mhz = 0;
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
t->counter[i] = 0; t->counter[i] = 0;
@ -3662,7 +3666,7 @@ allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data
int i; int i;
*t = calloc(topo.num_threads_per_core * topo.num_cores_per_pkg * *t = calloc(topo.num_threads_per_core * topo.num_cores_per_pkg *
topo.num_packages, sizeof(struct thread_data) + sys.thread_counter_bytes); topo.num_packages, sizeof(struct thread_data));
if (*t == NULL) if (*t == NULL)
goto error; goto error;
@ -3671,14 +3675,14 @@ allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data
(*t)[i].cpu_id = -1; (*t)[i].cpu_id = -1;
*c = calloc(topo.num_cores_per_pkg * topo.num_packages, *c = calloc(topo.num_cores_per_pkg * topo.num_packages,
sizeof(struct core_data) + sys.core_counter_bytes); sizeof(struct core_data));
if (*c == NULL) if (*c == NULL)
goto error; goto error;
for (i = 0; i < topo.num_cores_per_pkg * topo.num_packages; i++) for (i = 0; i < topo.num_cores_per_pkg * topo.num_packages; i++)
(*c)[i].core_id = -1; (*c)[i].core_id = -1;
*p = calloc(topo.num_packages, sizeof(struct pkg_data) + sys.package_counter_bytes); *p = calloc(topo.num_packages, sizeof(struct pkg_data));
if (*p == NULL) if (*p == NULL)
goto error; goto error;
@ -3901,24 +3905,36 @@ int add_counter(unsigned int msr_num, char *name, unsigned int width,
switch (scope) { switch (scope) {
case SCOPE_CPU: case SCOPE_CPU:
sys.thread_counter_bytes += 64;
msrp->next = sys.tp; msrp->next = sys.tp;
sys.tp = msrp; sys.tp = msrp;
sys.thread_counter_bytes += sizeof(unsigned long long); sys.added_thread_counters++;
if (sys.added_thread_counters > MAX_ADDED_COUNTERS) {
fprintf(stderr, "exceeded max %d added thread counters\n",
MAX_ADDED_COUNTERS);
exit(-1);
}
break; break;
case SCOPE_CORE: case SCOPE_CORE:
sys.core_counter_bytes += 64;
msrp->next = sys.cp; msrp->next = sys.cp;
sys.cp = msrp; sys.cp = msrp;
sys.core_counter_bytes += sizeof(unsigned long long); sys.added_core_counters++;
if (sys.added_core_counters > MAX_ADDED_COUNTERS) {
fprintf(stderr, "exceeded max %d added core counters\n",
MAX_ADDED_COUNTERS);
exit(-1);
}
break; break;
case SCOPE_PACKAGE: case SCOPE_PACKAGE:
sys.package_counter_bytes += 64;
msrp->next = sys.pp; msrp->next = sys.pp;
sys.pp = msrp; sys.pp = msrp;
sys.package_counter_bytes += sizeof(unsigned long long); sys.added_package_counters++;
if (sys.added_package_counters > MAX_ADDED_COUNTERS) {
fprintf(stderr, "exceeded max %d added package counters\n",
MAX_ADDED_COUNTERS);
exit(-1);
}
break; break;
} }