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

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 {
int pkg;
int core;
int cpu;
/* flags */
unsigned int is_online:1;
} *core_info;
};
......
......@@ -56,6 +56,56 @@ static unsigned int sysfs_write_file(const char *path,
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 */
/*
......
......@@ -7,6 +7,8 @@
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,
unsigned int idlestate);
extern unsigned long sysfs_get_idlestate_usage(unsigned int cpu,
......
......@@ -41,6 +41,8 @@ struct cpuid_core_info {
unsigned int pkg;
unsigned int thread;
unsigned int cpu;
/* flags */
unsigned int is_online:1;
};
static int __compare(const void *t1, const void *t2)
......@@ -78,6 +80,8 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
return -ENOMEM;
cpu_top->pkgs = cpu_top->cores = 0;
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 =
sysfs_topology_read_file(cpu, "physical_package_id");
if ((int)cpu_top->core_info[cpu].pkg != -1 &&
......@@ -85,7 +89,6 @@ int get_cpu_topology(struct cpupower_topology *cpu_top)
cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
cpu_top->core_info[cpu].core =
sysfs_topology_read_file(cpu, "core_id");
cpu_top->core_info[cpu].cpu = cpu;
}
cpu_top->pkgs++;
......
......@@ -190,9 +190,13 @@ void print_results(int topology_depth, int cpu)
}
}
}
/* cpu offline */
if (cpu_top.core_info[cpu].pkg == -1 ||
cpu_top.core_info[cpu].core == -1) {
/*
* The monitor could still provide useful data, for example
* 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"));
return;
} 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