From 179d461b79387bd3877cd239da933a8dfceae05c Mon Sep 17 00:00:00 2001 Message-Id: <179d461b79387bd3877cd239da933a8dfceae05c.1587532692.git.kamalesh@linux.vnet.ibm.com> In-Reply-To: References: From: Kamalesh Babulal Date: Tue, 21 Apr 2020 08:23:24 -0500 Subject: [PATCH V4 13/14] lparstat: Add support for cpu-hotplug To: powerpc-utils-devel@googlegroups.com Cc: Tyrel Datwyler , Nathan Lynch , Naveen N . Rao , Gautham R . Shenoy , Vasant Hegde For optimizing the read of sysfs file, the file descriptors are assigned at the beginning of the run but they do not change dynamically in event of a cpu hotplug, resulting under-estimated load average in case of new cpus onlined or error in case of cpu removed. This can be solved by checking for the online cpus every interval and re-assign the file descriptors again with new set of cpu on hotplug event. Signed-off-by: Kamalesh Babulal --- src/lparstat.c | 78 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/src/lparstat.c b/src/lparstat.c index 5390b9f..51caa3d 100644 --- a/src/lparstat.c +++ b/src/lparstat.c @@ -21,6 +21,7 @@ * @author Nathan Fontenot */ +#define _GNU_SOURCE #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +49,7 @@ static int cpus_in_system; static int threads_in_system; static cpu_sysfs_fd *cpu_sysfs_fds; +static cpu_set_t *online_cpus; struct sysentry *get_sysentry(char *name) { @@ -180,7 +183,7 @@ int parse_sysfs_values(void) if (rc == -1) { fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/spurr\n", cpu_sysfs_fds[i].cpu); - goto error; + goto check_cpu_hotplug; } value = strtoll(line, NULL, 16); @@ -190,7 +193,7 @@ int parse_sysfs_values(void) if (rc == -1) { fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/idle_purr\n", cpu_sysfs_fds[i].cpu); - goto error; + goto check_cpu_hotplug; } value = strtoll(line, NULL, 16); @@ -200,7 +203,7 @@ int parse_sysfs_values(void) if (rc == -1) { fprintf(stderr, "Failed to /sys/devices/system/cpu/cpu%d/idle_spurr\n", cpu_sysfs_fds[i].cpu); - goto error; + goto check_cpu_hotplug; } value = strtoll(line, NULL, 16); @@ -216,9 +219,11 @@ int parse_sysfs_values(void) return 0; -error: - close_cpu_sysfs_fds(threads_in_system); - return -1; +check_cpu_hotplug: + if(!cpu_online(cpu_sysfs_fds[i].cpu)) + return 1; + + return rc; } static void sig_int_handler(int signal) @@ -917,6 +922,52 @@ void get_cpu_stat(struct sysentry *se, char *buf) sprintf(buf, "%.2f", percent); } +int has_cpu_topology_changed(void) +{ + int i, changed = 1; + cpu_set_t *tmp_cpuset; + size_t online_cpus_size = CPU_ALLOC_SIZE(threads_in_system); + + if (!online_cpus) { + online_cpus = CPU_ALLOC(threads_in_system); + if (!online_cpus) { + fprintf(stderr, "Failed to allocate memory for cpu_set\n"); + return -1; + } + + CPU_ZERO_S(online_cpus_size, online_cpus); + + for (i = 0; i < threads_in_system; i++) { + if (!cpu_online(i)) + continue; + CPU_SET_S(i, online_cpus_size, online_cpus); + } + + return changed; + } + + tmp_cpuset = CPU_ALLOC(threads_in_system); + if (!tmp_cpuset) { + fprintf(stderr, "Failed to allocate memory for cpu_set\n"); + return -1; + } + + CPU_ZERO_S(online_cpus_size, tmp_cpuset); + + for (i = 0; i < threads_in_system; i++) { + if (!cpu_online(i)) + continue; + CPU_SET_S(i, online_cpus_size, tmp_cpuset); + } + + changed = CPU_EQUAL_S(online_cpus_size, online_cpus, tmp_cpuset); + + CPU_FREE(online_cpus); + online_cpus = tmp_cpuset; + + return changed; +} + void init_sysinfo(void) { int rc = 0; @@ -964,10 +1015,23 @@ void init_sysdata(void) if (!o_scaled) return; + rc = has_cpu_topology_changed(); + if (!rc) + goto cpu_hotplug_restart; + rc = parse_sysfs_values(); - if (rc) + if (rc == -1) exit(rc); + else if (rc) + goto cpu_hotplug_restart; + get_effective_frequency(); + + return; + +cpu_hotplug_restart: + close_cpu_sysfs_fds(threads_in_system); + init_sysinfo(); } void update_sysdata(void) -- 2.25.3