commit d1576f88dcc7008bcd3448172caff1b928be1254 Author: Aravinda Prasad Date: Thu Sep 6 15:01:04 2018 +0530 lparstat: Show available physical processors in the shared pool This patch adds the "app" field that displays the available processors in the shared pool. The platform provides the summation of the physical processor pool idle cycles through H_PIC hypercall. This data is updated in the "pool_idle_time" field of the /proc/ppc64/lparcfg file. This patch derives the "app" from the "pool_idle_time" field. v2: Handle fgets() errors Signed-off-by: Aravinda Prasad Signed-off-by: Tyrel Datwyler diff --git a/man/lparstat.8 b/man/lparstat.8 index 6d94486..4872a37 100644 --- a/man/lparstat.8 +++ b/man/lparstat.8 @@ -77,6 +77,9 @@ Shows the percentage of the entitled capacity consumed. Because the time base ov lbusy Shows the percentage of logical processor(s) utilization that occurred while executing at the user and system level. .TP +app +Shows the available physical processors in the shared pool. +.TP phint Shows the number of phantom (targeted to another shared partition in this pool) interruptions received. .SH OPTIONS diff --git a/src/lparstat.c b/src/lparstat.c index 6c54c7e..23e45f7 100644 --- a/src/lparstat.c +++ b/src/lparstat.c @@ -123,6 +123,32 @@ int get_time_base() return 0; } +void get_sys_uptime(struct sysentry *unused_se, char *uptime) +{ + FILE *f; + char buf[80]; + + f = fopen("/proc/uptime", "r"); + if (!f) { + fprintf(stderr, "Could not open /proc/uptime\n"); + sprintf(uptime, SE_NOT_VALID); + return; + } + + if ((fgets(buf, 80, f)) != NULL) { + char *value; + + value = strchr(buf, ' '); + *value = '\0'; + sprintf(uptime, "%s", buf); + } else { + sprintf(uptime, SE_NOT_VALID); + } + + fclose(f); +} + + void get_cpu_physc(struct sysentry *unused_se, char *buf) { struct sysentry *se; @@ -155,6 +181,44 @@ void get_per_entc(struct sysentry *unused_se, char *buf) sprintf(buf, "%.6f", atof(physc) / atof(entc) * 100.0); } +void get_cpu_app(struct sysentry *unused_se, char *buf) +{ + struct sysentry *se; + float timebase, app, elapsed_time; + long long new_app, old_app, newtime, oldtime; + char *descr, uptime[32]; + + se = get_sysentry("time"); + if (se->old_value[0] == '\0') { + /* Single report since boot */ + get_sysdata("uptime", &descr, uptime); + + if (!strcmp(uptime, SE_NOT_VALID)) { + sprintf(buf, "-"); + return; + } + elapsed_time = atof(uptime); + } else { + newtime = strtoll(se->value, NULL, 0); + oldtime = strtoll(se->old_value, NULL, 0); + elapsed_time = (newtime - oldtime) / 1000000.0; + } + + se = get_sysentry("timebase"); + timebase = atof(se->value); + + se = get_sysentry("pool_idle_time"); + new_app = strtoll(se->value, NULL, 0); + if (se->old_value[0] == '\0') { + old_app = 0; + } else { + old_app = strtoll(se->old_value, NULL, 0); + } + + app = (new_app - old_app)/timebase/elapsed_time; + sprintf(buf, "%.2f", app); +} + int parse_lparcfg() { FILE *f; @@ -527,13 +591,13 @@ int print_iflag_data() void print_default_output(int interval, int count) { - char *fmt = "%5s %5s %5s %8s %8s %5s %5s %5s %5s\n"; + char *fmt = "%5s %5s %5s %8s %8s %5s %5s %5s %5s %5s\n"; char *descr; char buf[128]; int offset; char value[32]; char user[32], sys[32], wait[32], idle[32], physc[32], entc[32]; - char lbusy[32], vcsw[32], phint[32]; + char lbusy[32], app[32], vcsw[32], phint[32]; memset(buf, 0, 128); get_sysdata("shared_processor_mode", &descr, value); @@ -554,9 +618,9 @@ void print_default_output(int interval, int count) fprintf(stdout, "\nSystem Configuration\n%s\n\n", buf); fprintf(stdout, fmt, "\%user", "\%sys", "\%wait", "\%idle", "physc", - "\%entc", "lbusy", "vcsw", "phint"); + "\%entc", "lbusy", "app", "vcsw", "phint"); fprintf(stdout, fmt, "-----", "-----", "-----", "-----", "-----", - "-----", "-----", "-----", "-----"); + "-----", "-----", "-----", "-----", "-----"); do { if (interval) { @@ -573,9 +637,10 @@ void print_default_output(int interval, int count) get_sysdata("physc", &descr, physc); get_sysdata("per_entc", &descr, entc); get_sysdata("phint", &descr, phint); + get_sysdata("app", &descr, app); fprintf(stdout, fmt, user, sys, wait, idle, physc, entc, - lbusy, vcsw, phint); + lbusy, app, vcsw, phint); fflush(stdout); } while (--count > 0); } diff --git a/src/lparstat.h b/src/lparstat.h index 5412edc..20bb939 100644 --- a/src/lparstat.h +++ b/src/lparstat.h @@ -46,6 +46,8 @@ extern void get_smt_mode(struct sysentry *, char *); extern void get_cpu_stat(struct sysentry *, char *); extern void get_cpu_physc(struct sysentry *, char *); extern void get_per_entc(struct sysentry *, char *); +extern void get_cpu_app(struct sysentry *, char *); +extern void get_sys_uptime(struct sysentry *, char *); struct sysentry system_data[] = { /* System Names */ @@ -221,6 +223,9 @@ struct sysentry system_data[] = { {.name = "per_entc", .descr = "Entitled CPU Consumed", .get = &get_per_entc}, + {.name = "app", + .descr = "Available physical CPUs in pool", + .get = &get_cpu_app}, /* Time */ {.name = "time", @@ -234,6 +239,11 @@ struct sysentry system_data[] = { {.name = "phint", .descr = "Phantom Interrupts"}, + /* /proc/uptime */ + {.name = "uptime", + .descr = "System Uptime", + .get = &get_sys_uptime}, + {.name[0] = '\0'}, };