turbostat-2026.09.28

Since turbostat-2026.04.21: bug fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCgAyFiEE67dNfPFP+XUaA73mB9BFOha3NhcFAmrBOeQUHGxlbi5icm93
 bkBpbnRlbC5jb20ACgkQB9BFOha3Nhd3HBAAswLnK3kpYJ9hv/DzeH1vBpZBxXM4
 fS3hydlvPHjnJ0XCxnCfpITzzJm9VRVdBm4cVKYbzZe/KPC8IqhaPN1/mxa226JB
 wGNg5GaWqmHyCnd0oTEnqnsp1xSIubAOCsAbJiqxvJaNvLfJ2x329WAD87MSjkSD
 OWiJJyOWno57ZnriC8S6HjqVbc15luDh0Iu/OsuVbGo85cbLh/jgfok4MmGEEQma
 ms/csuE4Fz7xnM3bgezs5xyr+Mk6AYlGKFJQsjNnmplWKS31UIw//DW4c0ESmpan
 0xYwkJL8S/+/fZxZVHDsIHqUTolaTEH6P99fpvaVhUo/ewrUX8uUpJJM017+kvCD
 2ZmLqwwqsZ8cDU27eoyv0lCKEkO5kyesXmmx5pfxLEYZNPS2NpASlAmgC7iONQdR
 MRVTrgbaUs1L1u8jlpPG6mWJwrAE9LXNVkoDeVCtEmSHJk+GbRFN/NoBeUck9iwT
 5YHUWjU1Ccs4Ac04eoa2YB8yM51nDyeb8CAgUTHSZ/hRjy+fzFt2rblf3IIjRti7
 1PFsG+vTGK82PqwGwq3mHew5K8302x1rvwIt9VJk89DLYHHjR7pGkyuYVLNUe75a
 XTTDTxCv8pBC8wJNW5HTOUhdl4gcM+2P1pouNkoCFU79/V9m5u/HJkv7mrZYybIW
 9VmBSMFKV0y87FE=
 =5B9V
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2026-10-13 16:51:44 -07:00
commit cbc08c2047

View File

@ -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 @@ int add_rapl_perf_counter(int cpu, struct rapl_counter_info_t *rci, const struct
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);