diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-13 16:51:44 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-13 16:51:44 -0700 |
| commit | cbc08c20479c6da3db077f9b170bb8cc2d09df20 (patch) | |
| tree | 64ae8aa0891991df12873874b17b11be689e38a0 /tools | |
| parent | 03741bcea0a9ec4c8f386fd5c6051c1a14070240 (diff) | |
| parent | d3eea584b56fecf5c3fba0979f0da28a6600d6a3 (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.c | 86 |
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); |
