Commit 7c74d2bc authored by Thomas Renninger's avatar Thomas Renninger Committed by Dominik Brodowski

cpupower: Better detect offlined CPUs

Before, checking for offlined CPUs was done dirty and
it was checked whether topology parsing returned -1 values.
But this is a valid case on a Xen (and possibly other) kernels.

Do proper online/offline checking, also take CONFIG_HOTPLUG_CPU
option into account (no /sys/devices/../cpuX/online file).
Signed-off-by: default avatarThomas Renninger <trenn@suse.de>
Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 88f984e0
...@@ -96,6 +96,9 @@ struct cpupower_topology { ...@@ -96,6 +96,9 @@ struct cpupower_topology {
int pkg; int pkg;
int core; int core;
int cpu; int cpu;
/* flags */
unsigned int is_online:1;
} *core_info; } *core_info;
}; };
......
...@@ -56,6 +56,56 @@ static unsigned int sysfs_write_file(const char *path, ...@@ -56,6 +56,56 @@ static unsigned int sysfs_write_file(const char *path,
return (unsigned int) numwrite; return (unsigned int) numwrite;
} }
/*
* Detect whether a CPU is online
*
* Returns:
* 1 -> if CPU is online
* 0 -> if CPU is offline
* negative errno values in error case
*/
int sysfs_is_cpu_online(unsigned int cpu)
{
char path[SYSFS_PATH_MAX];
int fd;
ssize_t numread;
unsigned long long value;
char linebuf[MAX_LINE_LEN];
char *endp;
struct stat statbuf;
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u", cpu);
if (stat(path, &statbuf) != 0)
return 0;
/*
* kernel without CONFIG_HOTPLUG_CPU
* -> cpuX directory exists, but not cpuX/online file
*/
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/online", cpu);
if (stat(path, &statbuf) != 0)
return 1;
fd = open(path, O_RDONLY);
if (fd == -1)
return -errno;
numread = read(fd, linebuf, MAX_LINE_LEN - 1);
if (numread < 1) {
close(fd);
return -EIO;
}
linebuf[numread] = '\0';
close(fd);
value = strtoull(linebuf, &endp, 0);
if (value > 1 || value < 0)
return -EINVAL;
return value;
}
/* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */ /* CPUidle idlestate specific /sys/devices/system/cpu/cpuX/cpuidle/ access */
/* /*
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen); extern unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
extern int sysfs_is_cpu_online(unsigned int cpu);
extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu, extern unsigned long sysfs_get_idlestate_latency(unsigned int cpu,
unsigned int idlestate); unsigned int idlestate);
extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu, extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
......
...@@ -41,6 +41,8 @@ struct cpuid_core_info { ...@@ -41,6 +41,8 @@ struct cpuid_core_info {
unsigned int pkg; unsigned int pkg;
unsigned int thread; unsigned int thread;
unsigned int cpu; unsigned int cpu;
/* flags */
unsigned int is_online:1;
}; };
static int __compare(const void *t1, const void *t2) static int __compare(const void *t1, const void *t2)
...@@ -78,6 +80,8 @@ int get_cpu_topology(struct cpupower_topology *cpu_top) ...@@ -78,6 +80,8 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
return -ENOMEM; return -ENOMEM;
cpu_top->pkgs = cpu_top->cores = 0; cpu_top->pkgs = cpu_top->cores = 0;
for (cpu = 0; cpu < cpus; cpu++) { for (cpu = 0; cpu < cpus; cpu++) {
cpu_top->core_info[cpu].cpu = cpu;
cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
cpu_top->core_info[cpu].pkg = cpu_top->core_info[cpu].pkg =
sysfs_topology_read_file(cpu, "physical_package_id"); sysfs_topology_read_file(cpu, "physical_package_id");
if ((int)cpu_top->core_info[cpu].pkg != -1 && if ((int)cpu_top->core_info[cpu].pkg != -1 &&
...@@ -85,7 +89,6 @@ int get_cpu_topology(struct cpupower_topology *cpu_top) ...@@ -85,7 +89,6 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
cpu_top->pkgs = cpu_top->core_info[cpu].pkg; cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
cpu_top->core_info[cpu].core = cpu_top->core_info[cpu].core =
sysfs_topology_read_file(cpu, "core_id"); sysfs_topology_read_file(cpu, "core_id");
cpu_top->core_info[cpu].cpu = cpu;
} }
cpu_top->pkgs++; cpu_top->pkgs++;
......
...@@ -190,9 +190,13 @@ void print_results(int topology_depth, int cpu) ...@@ -190,9 +190,13 @@ void print_results(int topology_depth, int cpu)
} }
} }
} }
/* cpu offline */ /*
if (cpu_top.core_info[cpu].pkg == -1 || * The monitor could still provide useful data, for example
cpu_top.core_info[cpu].core == -1) { * AMD HW counters partly sit in PCI config space.
* It's up to the monitor plug-in to check .is_online, this one
* is just for additional info.
*/
if (!cpu_top.core_info[cpu].is_online) {
printf(_(" *is offline\n")); printf(_(" *is offline\n"));
return; return;
} else } else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment