aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-13 16:51:44 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-13 16:51:44 -0700
commitcbc08c20479c6da3db077f9b170bb8cc2d09df20 (patch)
tree64ae8aa0891991df12873874b17b11be689e38a0 /tools
parent03741bcea0a9ec4c8f386fd5c6051c1a14070240 (diff)
parentd3eea584b56fecf5c3fba0979f0da28a6600d6a3 (diff)
Merge tag 'turbostat-2026.09.28' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
Pull turbostat fixes from Len Brown. * tag 'turbostat-2026.09.28' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux: turbostat 2026.09.28 tools/power turbostat: Fix add_counter issue if > 24 counters. tools/power turbostat: Fix PMT error path fd handling tools/power turbostat: Fix CWF PMT off-by-one tools/power turbostat: Fix fd_perf leak on reset tools/power turbostat: Sanity check GFX%rc6 and SAM%mc6 percentages tools/power turbostat: add NULL check after calloc() tools/power turbostat: Warn, but don't Err on out-dated perf systems tools/power turbostat: Read complete CPU lists
Diffstat (limited to 'tools')
-rw-r--r--tools/power/x86/turbostat/turbostat.c86
1 files changed, 54 insertions, 32 deletions
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 920694c3c1ec..cb3d571f121e 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -2034,8 +2034,11 @@ const struct dirent *pmt_diriter_begin(struct pmt_diriter_t *iter, const char *p
return NULL;
num_names = scandir(pmt_root_path, &iter->namelist, pmt_telemdir_filter, pmt_telemdir_sort);
- if (num_names == -1)
+ if (num_names == -1) {
+ closedir(iter->dir);
+ iter->dir = NULL;
return NULL;
+ }
}
iter->current_name_idx = 0;
@@ -2063,8 +2066,10 @@ void pmt_diriter_remove(struct pmt_diriter_t *iter)
iter->num_names = 0;
iter->current_name_idx = 0;
- closedir(iter->dir);
- iter->dir = NULL;
+ if (iter->dir) {
+ closedir(iter->dir);
+ iter->dir = NULL;
+ }
}
unsigned int pmt_counter_get_width(const struct pmt_counter *p)
@@ -3636,7 +3641,7 @@ int format_counters(PER_THREAD_PARAMS)
if (p->gfx_rc6_ms == -1) { /* detect GFX counter reset */
outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));
} else {
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), p->gfx_rc6_ms / 10.0 / interval_float);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->gfx_rc6_ms / 10.0, interval_float));
}
}
@@ -3653,7 +3658,7 @@ int format_counters(PER_THREAD_PARAMS)
if (p->sam_mc6_ms == -1) { /* detect GFX counter reset */
outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));
} else {
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), p->sam_mc6_ms / 10.0 / interval_float);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->sam_mc6_ms / 10.0, interval_float));
}
}
@@ -5915,7 +5920,7 @@ void free_fd_msr(void)
if (!msr_counter_info)
return;
- for (int cpu = 0; cpu < topo.max_cpu_num; ++cpu) {
+ for (int cpu = 0; cpu <= topo.max_cpu_num; ++cpu) {
if (msr_counter_info[cpu].fd_perf != -1)
close(msr_counter_info[cpu].fd_perf);
}
@@ -6311,33 +6316,35 @@ int for_all_proc_cpus(int (func) (int))
#define PATH_EFFECTIVE_CPUS "/sys/fs/cgroup/cpuset.cpus.effective"
-static char cpu_effective_str[1024];
+static char *cpu_effective_str;
static int update_effective_str(bool startup)
{
FILE *fp;
- char *pos;
- char buf[1024];
+ char *buf = NULL;
+ size_t size = 0;
int ret;
- if (cpu_effective_str[0] == '\0' && !startup)
+ if (!cpu_effective_str && !startup)
return 0;
fp = fopen(PATH_EFFECTIVE_CPUS, "r");
if (!fp)
return 0;
- pos = fgets(buf, 1024, fp);
- if (!pos)
+ if (getline(&buf, &size, fp) < 0)
err(1, "%s: file read failed", PATH_EFFECTIVE_CPUS);
fclose(fp);
- ret = strncmp(cpu_effective_str, buf, 1024);
- if (!ret)
+ ret = cpu_effective_str ? strcmp(cpu_effective_str, buf) : 1;
+ if (!ret) {
+ free(buf);
return 0;
+ }
- strncpy(cpu_effective_str, buf, 1024);
+ free(cpu_effective_str);
+ cpu_effective_str = buf;
return 1;
}
@@ -8529,13 +8536,16 @@ end:
return ret;
}
-char cpuset_buf[1024];
-int initialize_cpu_set_from_sysfs(cpu_set_t *cpu_set, char *sysfs_path, char *sysfs_file)
+int initialize_cpu_set_from_sysfs(cpu_set_t *cpu_set, const char *sysfs_path,
+ const char *sysfs_file)
{
FILE *fp;
+ char *cpuset_buf = NULL;
+ size_t size = 0;
char path[128];
+ int ret = -1;
- if (snprintf(path, 128, "%s/%s", sysfs_path, sysfs_file) > 128)
+ if (snprintf(path, sizeof(path), "%s/%s", sysfs_path, sysfs_file) >= (int)sizeof(path))
err(-1, "%s %s", sysfs_path, sysfs_file);
fp = fopen(path, "r");
@@ -8543,19 +8553,20 @@ int initialize_cpu_set_from_sysfs(cpu_set_t *cpu_set, char *sysfs_path, char *sy
warn("open %s", path);
return -1;
}
- if (fread(cpuset_buf, sizeof(char), 1024, fp) == 0) {
+ if (getline(&cpuset_buf, &size, fp) < 0) {
warn("read %s", sysfs_path);
- goto err;
+ goto out;
}
if (parse_cpu_str(cpuset_buf, cpu_set, cpu_possible_setsize)) {
- warnx("%s: cpu str malformat %s\n", sysfs_path, cpu_effective_str);
- goto err;
+ warnx("%s: cpu str malformat %s\n", sysfs_path, cpuset_buf);
+ goto out;
}
- return 0;
+ ret = 0;
-err:
+out:
fclose(fp);
- return -1;
+ free(cpuset_buf);
+ return ret;
}
void print_cpu_set(char *s, cpu_set_t *set)
@@ -8655,6 +8666,8 @@ void rapl_perf_init(void)
{
const unsigned int num_domains = get_rapl_num_domains();
bool *domain_visited = calloc(num_domains, sizeof(bool));
+ if (!domain_visited)
+ err(-1, "calloc domain_visited");
rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain));
if (rapl_counter_info_perdomain == NULL)
@@ -9471,8 +9484,10 @@ void perf_l2_init(void)
free_fd_l2_percpu();
return;
}
- } else
- err(-1, "%s: cpu%d: type %d", __func__, cpu, cpus[cpu].type);
+ } else {
+ warn("%s: cpu%d: type %d: Update kernel perf support or use \"--hide L2MRPS,L2%%hit\" or \"--hide cache\" or \"--no-perf\"", __func__, cpu, cpus[cpu].type);
+ return;
+ }
}
BIC_PRESENT(BIC_L2_MRPS);
BIC_PRESENT(BIC_L2_HIT);
@@ -9999,6 +10014,8 @@ int added_perf_counters_init_(struct perf_counter_info *pinfo)
const size_t max_num_domains = MAX(topo.max_cpu_num + 1, MAX(topo.max_core_id + 1, topo.max_package_id + 1));
domain_visited = calloc(max_num_domains, sizeof(*domain_visited));
+ if (!domain_visited)
+ errx(1, "%s: alloc %s", __func__, "domain_visited");
while (pinfo) {
switch (pinfo->scope) {
@@ -10390,6 +10407,8 @@ int pmt_add_counter(unsigned int guid, unsigned int seq, const char *name, enum
pcounter = pmt_find_counter(*pmt_root, name);
if (!pcounter) {
pcounter = calloc(1, sizeof(*pcounter));
+ if (!pcounter)
+ return 1;
new_counter = true;
}
@@ -10439,7 +10458,7 @@ void pmt_init(void)
mod_num = 0; /* Relative module number for current PMT file. */
/* Open the counter for each CPU. */
- for (cpu_num = 0; cpu_num < topo.max_cpu_num;) {
+ for (cpu_num = 0; cpu_num <= topo.max_cpu_num;) {
if (cpu_is_not_allowed(cpu_num))
goto next_loop_iter;
@@ -10608,7 +10627,7 @@ int get_and_dump_counters(void)
void print_version()
{
- fprintf(outf, "turbostat version 2026.04.21 - Len Brown <lenb@kernel.org>\n");
+ fprintf(outf, "turbostat version 2026.09.28 - Len Brown <lenb@kernel.org>\n");
}
#define COMMAND_LINE_SIZE 2048
@@ -10668,10 +10687,11 @@ int add_counter(unsigned int msr_num, char *path, char *name,
fprintf(stderr, "%s: %s FOUND\n", __func__, name);
break;
}
- if (sys.added_thread_counters++ >= MAX_ADDED_THREAD_COUNTERS) {
+ if (sys.added_thread_counters >= MAX_ADDED_THREAD_COUNTERS) {
warnx("ignoring thread counter %s", name);
return -1;
}
+ sys.added_thread_counters++;
break;
case SCOPE_CORE:
msrp = find_msrp_by_name(sys.cp, name);
@@ -10680,10 +10700,11 @@ int add_counter(unsigned int msr_num, char *path, char *name,
fprintf(stderr, "%s: %s FOUND\n", __func__, name);
break;
}
- if (sys.added_core_counters++ >= MAX_ADDED_CORE_COUNTERS) {
+ if (sys.added_core_counters >= MAX_ADDED_CORE_COUNTERS) {
warnx("ignoring core counter %s", name);
return -1;
}
+ sys.added_core_counters++;
break;
case SCOPE_PACKAGE:
msrp = find_msrp_by_name(sys.pp, name);
@@ -10692,10 +10713,11 @@ int add_counter(unsigned int msr_num, char *path, char *name,
fprintf(stderr, "%s: %s FOUND\n", __func__, name);
break;
}
- if (sys.added_package_counters++ >= MAX_ADDED_PACKAGE_COUNTERS) {
+ if (sys.added_package_counters >= MAX_ADDED_PACKAGE_COUNTERS) {
warnx("ignoring package counter %s", name);
return -1;
}
+ sys.added_package_counters++;
break;
default:
warnx("ignoring counter %s with unknown scope", name);