Skip to content

Commit 80f0f07

Browse files
committed
Merge tag 'linux-cpupower-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux
Merge cpupower utility updates for 6.15-rc1 from Shuah Khan: "Fixes lib version-ing, memory leaks in error legs, removes hard-coded values, and implements CPU physical core querying." * tag 'linux-cpupower-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux: cpupower: Make lib versioning scheme more obvious and fix version link cpupower: Implement CPU physical core querying pm: cpupower: remove hard-coded topology depth values pm: cpupower: Fix cmd_monitor() error legs to free cpu_topology cpupower: monitor: Exit with error status if execvp() fail pm: cpupower: bench: Prevent NULL dereference on malloc failure
2 parents 80e54e8 + fffadbd commit 80f0f07

File tree

5 files changed

+94
-28
lines changed

5 files changed

+94
-28
lines changed

tools/power/cpupower/Makefile

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@ DESTDIR ?=
5252
# and _should_ modify the PACKAGE_BUGREPORT definition
5353

5454
VERSION:= $(shell ./utils/version-gen.sh)
55-
LIB_MAJ= 0.0.1
56-
LIB_MIN= 1
55+
LIB_FIX= 1
56+
LIB_MIN= 0
57+
LIB_MAJ= 1
58+
LIB_VER= $(LIB_MAJ).$(LIB_MIN).$(LIB_FIX)
59+
5760

5861
PACKAGE = cpupower
5962
PACKAGE_BUGREPORT = linux-pm@vger.kernel.org
@@ -200,14 +203,14 @@ $(OUTPUT)lib/%.o: $(LIB_SRC) $(LIB_HEADERS)
200203
$(ECHO) " CC " $@
201204
$(QUIET) $(CC) $(CFLAGS) -fPIC -o $@ -c lib/$*.c
202205

203-
$(OUTPUT)libcpupower.so.$(LIB_MAJ): $(LIB_OBJS)
206+
$(OUTPUT)libcpupower.so.$(LIB_VER): $(LIB_OBJS)
204207
$(ECHO) " LD " $@
205208
$(QUIET) $(CC) -shared $(CFLAGS) $(LDFLAGS) -o $@ \
206-
-Wl,-soname,libcpupower.so.$(LIB_MIN) $(LIB_OBJS)
209+
-Wl,-soname,libcpupower.so.$(LIB_MAJ) $(LIB_OBJS)
207210
@ln -sf $(@F) $(OUTPUT)libcpupower.so
208-
@ln -sf $(@F) $(OUTPUT)libcpupower.so.$(LIB_MIN)
211+
@ln -sf $(@F) $(OUTPUT)libcpupower.so.$(LIB_MAJ)
209212

210-
libcpupower: $(OUTPUT)libcpupower.so.$(LIB_MAJ)
213+
libcpupower: $(OUTPUT)libcpupower.so.$(LIB_VER)
211214

212215
# Let all .o files depend on its .c file and all headers
213216
# Might be worth to put this into utils/Makefile at some point of time
@@ -217,7 +220,7 @@ $(OUTPUT)%.o: %.c
217220
$(ECHO) " CC " $@
218221
$(QUIET) $(CC) $(CFLAGS) -I./lib -I ./utils -o $@ -c $*.c
219222

220-
$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ)
223+
$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_VER)
221224
$(ECHO) " CC " $@
222225
ifeq ($(strip $(STATIC)),true)
223226
$(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lrt -lpci -L$(OUTPUT) -o $@
@@ -262,7 +265,7 @@ update-po: $(OUTPUT)po/$(PACKAGE).pot
262265
done;
263266
endif
264267

265-
compile-bench: $(OUTPUT)libcpupower.so.$(LIB_MAJ)
268+
compile-bench: $(OUTPUT)libcpupower.so.$(LIB_VER)
266269
@V=$(V) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT)
267270

268271
# we compile into subdirectories. if the target directory is not the

tools/power/cpupower/bench/parse.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ FILE *prepare_output(const char *dirname)
121121
struct config *prepare_default_config()
122122
{
123123
struct config *config = malloc(sizeof(struct config));
124+
if (!config) {
125+
perror("malloc");
126+
return NULL;
127+
}
124128

125129
dprintf("loading defaults\n");
126130

tools/power/cpupower/lib/cpupower.c

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <stdio.h>
1111
#include <errno.h>
1212
#include <stdlib.h>
13+
#include <string.h>
1314

1415
#include "cpupower.h"
1516
#include "cpupower_intern.h"
@@ -150,15 +151,25 @@ static int __compare(const void *t1, const void *t2)
150151
return 0;
151152
}
152153

154+
static int __compare_core_cpu_list(const void *t1, const void *t2)
155+
{
156+
struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
157+
struct cpuid_core_info *top2 = (struct cpuid_core_info *)t2;
158+
159+
return strcmp(top1->core_cpu_list, top2->core_cpu_list);
160+
}
161+
153162
/*
154163
* Returns amount of cpus, negative on error, cpu_top must be
155164
* passed to cpu_topology_release to free resources
156165
*
157-
* Array is sorted after ->pkg, ->core, then ->cpu
166+
* Array is sorted after ->cpu_smt_list ->pkg, ->core
158167
*/
159168
int get_cpu_topology(struct cpupower_topology *cpu_top)
160169
{
161170
int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
171+
char path[SYSFS_PATH_MAX];
172+
char *last_cpu_list;
162173

163174
cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
164175
if (cpu_top->core_info == NULL)
@@ -183,6 +194,34 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
183194
cpu_top->core_info[cpu].core = -1;
184195
continue;
185196
}
197+
if (cpu_top->core_info[cpu].core == -1) {
198+
strncpy(cpu_top->core_info[cpu].core_cpu_list, "-1", CPULIST_BUFFER);
199+
continue;
200+
}
201+
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
202+
cpu, "core_cpus_list");
203+
if (cpupower_read_sysfs(
204+
path,
205+
cpu_top->core_info[cpu].core_cpu_list,
206+
CPULIST_BUFFER) < 1) {
207+
printf("Warning CPU%u has a 0 size core_cpus_list string", cpu);
208+
}
209+
}
210+
211+
/* Count the number of distinct cpu lists to get the physical core
212+
* count.
213+
*/
214+
qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
215+
__compare_core_cpu_list);
216+
217+
last_cpu_list = cpu_top->core_info[0].core_cpu_list;
218+
cpu_top->cores = 1;
219+
for (cpu = 1; cpu < cpus; cpu++) {
220+
if (strcmp(cpu_top->core_info[cpu].core_cpu_list, last_cpu_list) != 0 &&
221+
cpu_top->core_info[cpu].pkg != -1) {
222+
last_cpu_list = cpu_top->core_info[cpu].core_cpu_list;
223+
cpu_top->cores++;
224+
}
186225
}
187226

188227
qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
@@ -203,13 +242,6 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
203242
if (!(cpu_top->core_info[0].pkg == -1))
204243
cpu_top->pkgs++;
205244

206-
/* Intel's cores count is not consecutively numbered, there may
207-
* be a core_id of 3, but none of 2. Assume there always is 0
208-
* Get amount of cores by counting duplicates in a package
209-
for (cpu = 0; cpu_top->core_info[cpu].pkg = 0 && cpu < cpus; cpu++) {
210-
if (cpu_top->core_info[cpu].core == 0)
211-
cpu_top->cores++;
212-
*/
213245
return cpus;
214246
}
215247

tools/power/cpupower/lib/cpupower.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef __CPUPOWER_CPUPOWER_H__
33
#define __CPUPOWER_CPUPOWER_H__
44

5+
#define CPULIST_BUFFER 5
6+
57
struct cpupower_topology {
68
/* Amount of CPU cores, packages and threads per core in the system */
79
unsigned int cores;
@@ -16,6 +18,7 @@ struct cpuid_core_info {
1618
int pkg;
1719
int core;
1820
int cpu;
21+
char core_cpu_list[CPULIST_BUFFER];
1922

2023
/* flags */
2124
unsigned int is_online:1;

tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88

9+
#include <errno.h>
910
#include <stdio.h>
1011
#include <unistd.h>
1112
#include <stdlib.h>
@@ -91,7 +92,11 @@ int fill_string_with_spaces(char *s, int n)
9192
return 0;
9293
}
9394

94-
#define MAX_COL_WIDTH 6
95+
#define MAX_COL_WIDTH 6
96+
#define TOPOLOGY_DEPTH_PKG 3
97+
#define TOPOLOGY_DEPTH_CORE 2
98+
#define TOPOLOGY_DEPTH_CPU 1
99+
95100
void print_header(int topology_depth)
96101
{
97102
int unsigned mon;
@@ -113,12 +118,19 @@ void print_header(int topology_depth)
113118
}
114119
printf("\n");
115120

116-
if (topology_depth > 2)
121+
switch (topology_depth) {
122+
case TOPOLOGY_DEPTH_PKG:
117123
printf(" PKG|");
118-
if (topology_depth > 1)
124+
break;
125+
case TOPOLOGY_DEPTH_CORE:
119126
printf("CORE|");
120-
if (topology_depth > 0)
127+
break;
128+
case TOPOLOGY_DEPTH_CPU:
121129
printf(" CPU|");
130+
break;
131+
default:
132+
return;
133+
}
122134

123135
for (mon = 0; mon < avail_monitors; mon++) {
124136
if (mon != 0)
@@ -152,12 +164,19 @@ void print_results(int topology_depth, int cpu)
152164
cpu_top.core_info[cpu].pkg == -1)
153165
return;
154166

155-
if (topology_depth > 2)
167+
switch (topology_depth) {
168+
case TOPOLOGY_DEPTH_PKG:
156169
printf("%4d|", cpu_top.core_info[cpu].pkg);
157-
if (topology_depth > 1)
170+
break;
171+
case TOPOLOGY_DEPTH_CORE:
158172
printf("%4d|", cpu_top.core_info[cpu].core);
159-
if (topology_depth > 0)
173+
break;
174+
case TOPOLOGY_DEPTH_CPU:
160175
printf("%4d|", cpu_top.core_info[cpu].cpu);
176+
break;
177+
default:
178+
return;
179+
}
161180

162181
for (mon = 0; mon < avail_monitors; mon++) {
163182
if (mon != 0)
@@ -294,7 +313,10 @@ int fork_it(char **argv)
294313

295314
if (!child_pid) {
296315
/* child */
297-
execvp(argv[0], argv);
316+
if (execvp(argv[0], argv) == -1) {
317+
printf("Invalid monitor command %s\n", argv[0]);
318+
exit(errno);
319+
}
298320
} else {
299321
/* parent */
300322
if (child_pid == -1) {
@@ -423,11 +445,13 @@ int cmd_monitor(int argc, char **argv)
423445

424446
if (avail_monitors == 0) {
425447
printf(_("No HW Cstate monitors found\n"));
448+
cpu_topology_release(cpu_top);
426449
return 1;
427450
}
428451

429452
if (mode == list) {
430453
list_monitors();
454+
cpu_topology_release(cpu_top);
431455
exit(EXIT_SUCCESS);
432456
}
433457

@@ -448,15 +472,15 @@ int cmd_monitor(int argc, char **argv)
448472
/* ToDo: Topology parsing needs fixing first to do
449473
this more generically */
450474
if (cpu_top.pkgs > 1)
451-
print_header(3);
475+
print_header(TOPOLOGY_DEPTH_PKG);
452476
else
453-
print_header(1);
477+
print_header(TOPOLOGY_DEPTH_CPU);
454478

455479
for (cpu = 0; cpu < cpu_count; cpu++) {
456480
if (cpu_top.pkgs > 1)
457-
print_results(3, cpu);
481+
print_results(TOPOLOGY_DEPTH_PKG, cpu);
458482
else
459-
print_results(1, cpu);
483+
print_results(TOPOLOGY_DEPTH_CPU, cpu);
460484
}
461485

462486
for (num = 0; num < avail_monitors; num++) {

0 commit comments

Comments
 (0)