From 931e0a1ecb9c8786e268f6d40e18456909721de7 Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 16 Sep 2011 17:39:39 +0000 Subject: [PATCH] MFC 223936,224205: Allow per-CPU statistics to be toggled at runtime via the 'P' key. While here, make -P a toggle similar to other options such as -I. git-svn-id: svn://svn.freebsd.org/base/stable/8@225619 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- contrib/top/commands.c | 1 + contrib/top/display.c | 37 +++++++++-- contrib/top/top.X | 4 ++ contrib/top/top.c | 19 ++++-- usr.bin/top/machine.c | 146 +++++++++++++++++++++-------------------- 5 files changed, 127 insertions(+), 80 deletions(-) diff --git a/contrib/top/commands.c b/contrib/top/commands.c index 7891068a2..49472fd13 100644 --- a/contrib/top/commands.c +++ b/contrib/top/commands.c @@ -88,6 +88,7 @@ o - specify sort order (vcsw, ivcsw, read, write, fault, total, jid)\n", stdout); #endif fputs("\ +P - toggle the displaying of per-CPU statistics\n\ r - renice a process\n\ s - change number of seconds to delay between updates\n\ S - toggle the displaying of system processes\n\ diff --git a/contrib/top/display.c b/contrib/top/display.c index 8d89d825a..89795c05e 100644 --- a/contrib/top/display.c +++ b/contrib/top/display.c @@ -151,25 +151,50 @@ int display_resize() return(smart_terminal ? lines : Largest); } -int display_init(statics) +int display_updatecpus(statics) struct statics *statics; { + register int *lp; register int lines; - register char **pp; - register int *ip; register int i; - + /* call resize to do the dirty work */ lines = display_resize(); - num_cpus = statics->ncpus; + if (pcpu_stats) + num_cpus = statics->ncpus; + else + num_cpus = 1; cpustates_column = 5; /* CPU: */ if (num_cpus != 1) cpustates_column += 2; /* CPU 0: */ for (i = num_cpus; i > 9; i /= 10) cpustates_column++; + /* fill the "last" array with all -1s, to insure correct updating */ + lp = lcpustates; + i = num_cpustates * num_cpus; + while (--i >= 0) + { + *lp++ = -1; + } + + return(lines); +} + +int display_init(statics) + +struct statics *statics; + +{ + register int lines; + register char **pp; + register int *ip; + register int i; + + lines = display_updatecpus(statics); + /* only do the rest if we need to */ if (lines > -1) { @@ -184,7 +209,7 @@ struct statics *statics; num_swap = string_count(swap_names); lswap = (int *)malloc(num_swap * sizeof(int)); num_cpustates = string_count(cpustate_names); - lcpustates = (int *)malloc(num_cpustates * sizeof(int) * num_cpus); + lcpustates = (int *)malloc(num_cpustates * sizeof(int) * statics->ncpus); cpustate_columns = (int *)malloc(num_cpustates * sizeof(int)); memory_names = statics->memory_names; diff --git a/contrib/top/top.X b/contrib/top/top.X index 7c93a2e64..9c54f8563 100644 --- a/contrib/top/top.X +++ b/contrib/top/top.X @@ -205,6 +205,7 @@ The options .BR \-H , .BR \-I , .BR \-j , +.BR \-P , .BR \-S , .BR \-t , .BR \-u , @@ -314,6 +315,9 @@ Toggle the display of .IR jail (8) ID. .TP +.B P +Toggle the display of per-CPU statistics. +.TP .B t Toggle the display of the .I top diff --git a/contrib/top/top.c b/contrib/top/top.c index 33185947a..fc385b42f 100644 --- a/contrib/top/top.c +++ b/contrib/top/top.c @@ -196,9 +196,9 @@ char *argv[]; fd_set readfds; #ifdef ORDER - static char command_chars[] = "\f qh?en#sdkriIutHmSCajzo"; + static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPo"; #else - static char command_chars[] = "\f qh?en#sdkriIutHmSCajz"; + static char command_chars[] = "\f qh?en#sdkriIutHmSCajzP"; #endif /* these defines enumerate the "strchr"s of the commands in command_chars */ #define CMD_redraw 0 @@ -225,8 +225,9 @@ char *argv[]; #define CMD_showargs 20 #define CMD_jidtog 21 #define CMD_kidletog 22 +#define CMD_pcputog 23 #ifdef ORDER -#define CMD_order 23 +#define CMD_order 24 #endif /* set the buffer for stdout */ @@ -411,7 +412,7 @@ char *argv[]; break; case 'P': - pcpu_stats = Yes; + pcpu_stats = !pcpu_stats; break; case 'z': @@ -1088,6 +1089,16 @@ restart: ps.kidle ? "D" : "Not d"); putchar('\r'); break; + case CMD_pcputog: + pcpu_stats = !pcpu_stats; + new_message(MT_standout | MT_delayed, + " Displaying %sCPU statistics.", + pcpu_stats ? "per-" : "global "); + toggle_pcpustats(); + max_topn = display_updatecpus(&statics); + reset_display(); + putchar('\r'); + break; default: new_message(MT_standout, " BAD CASE IN SWITCH!"); putchar('\r'); diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c index 4083ba0de..19b93b7a7 100644 --- a/usr.bin/top/machine.c +++ b/usr.bin/top/machine.c @@ -239,19 +239,46 @@ static const char *format_nice(const struct kinfo_proc *pp); static void getsysctl(const char *name, void *ptr, size_t len); static int swapmode(int *retavail, int *retfree); +void +toggle_pcpustats(void) +{ + + if (ncpus == 1) + return; + + /* Adjust display based on ncpus */ + if (pcpu_stats) { + y_mem += ncpus - 1; /* 3 */ + y_swap += ncpus - 1; /* 4 */ + y_idlecursor += ncpus - 1; /* 5 */ + y_message += ncpus - 1; /* 5 */ + y_header += ncpus - 1; /* 6 */ + y_procs += ncpus - 1; /* 7 */ + Header_lines += ncpus - 1; /* 7 */ + } else { + y_mem = 3; + y_swap = 4; + y_idlecursor = 5; + y_message = 5; + y_header = 6; + y_procs = 7; + Header_lines = 7; + } +} + int machine_init(struct statics *statics, char do_unames) { - int pagesize; - size_t modelen; + int i, j, empty, pagesize; + size_t size; struct passwd *pw; - modelen = sizeof(smpmode); - if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, + size = sizeof(smpmode); + if ((sysctlbyname("machdep.smp_active", &smpmode, &size, NULL, 0) != 0 && - sysctlbyname("kern.smp.active", &smpmode, &modelen, + sysctlbyname("kern.smp.active", &smpmode, &size, NULL, 0) != 0) || - modelen != sizeof(smpmode)) + size != sizeof(smpmode)) smpmode = 0; if (do_unames) { @@ -299,51 +326,37 @@ machine_init(struct statics *statics, char do_unames) statics->order_names = ordernames; #endif - /* Adjust display based on ncpus */ - if (pcpu_stats) { - int i, j, empty; - size_t size; - - cpumask = 0; - ncpus = 0; - GETSYSCTL("kern.smp.maxcpus", maxcpu); - size = sizeof(long) * maxcpu * CPUSTATES; - times = malloc(size); - if (times == NULL) - err(1, "malloc %zd bytes", size); - if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1) - err(1, "sysctlbyname kern.cp_times"); - pcpu_cp_time = calloc(1, size); - maxid = (size / CPUSTATES / sizeof(long)) - 1; - for (i = 0; i <= maxid; i++) { - empty = 1; - for (j = 0; empty && j < CPUSTATES; j++) { - if (times[i * CPUSTATES + j] != 0) - empty = 0; - } - if (!empty) { - cpumask |= (1ul << i); - ncpus++; - } + /* Allocate state for per-CPU stats. */ + cpumask = 0; + ncpus = 0; + GETSYSCTL("kern.smp.maxcpus", maxcpu); + size = sizeof(long) * maxcpu * CPUSTATES; + times = malloc(size); + if (times == NULL) + err(1, "malloc %zd bytes", size); + if (sysctlbyname("kern.cp_times", times, &size, NULL, 0) == -1) + err(1, "sysctlbyname kern.cp_times"); + pcpu_cp_time = calloc(1, size); + maxid = (size / CPUSTATES / sizeof(long)) - 1; + for (i = 0; i <= maxid; i++) { + empty = 1; + for (j = 0; empty && j < CPUSTATES; j++) { + if (times[i * CPUSTATES + j] != 0) + empty = 0; } - - if (ncpus > 1) { - y_mem += ncpus - 1; /* 3 */ - y_swap += ncpus - 1; /* 4 */ - y_idlecursor += ncpus - 1; /* 5 */ - y_message += ncpus - 1; /* 5 */ - y_header += ncpus - 1; /* 6 */ - y_procs += ncpus - 1; /* 7 */ - Header_lines += ncpus - 1; /* 7 */ + if (!empty) { + cpumask |= (1ul << i); + ncpus++; } - size = sizeof(long) * ncpus * CPUSTATES; - pcpu_cp_old = calloc(1, size); - pcpu_cp_diff = calloc(1, size); - pcpu_cpu_states = calloc(1, size); - statics->ncpus = ncpus; - } else { - statics->ncpus = 1; } + size = sizeof(long) * ncpus * CPUSTATES; + pcpu_cp_old = calloc(1, size); + pcpu_cp_diff = calloc(1, size); + pcpu_cpu_states = calloc(1, size); + statics->ncpus = ncpus; + + if (pcpu_stats) + toggle_pcpustats(); /* all done! */ return (0); @@ -398,14 +411,11 @@ get_system_info(struct system_info *si) int i, j; size_t size; - /* get the cp_time array */ - if (pcpu_stats) { - size = (maxid + 1) * CPUSTATES * sizeof(long); - if (sysctlbyname("kern.cp_times", pcpu_cp_time, &size, NULL, 0) == -1) - err(1, "sysctlbyname kern.cp_times"); - } else { - GETSYSCTL("kern.cp_time", cp_time); - } + /* get the CPU stats */ + size = (maxid + 1) * CPUSTATES * sizeof(long); + if (sysctlbyname("kern.cp_times", pcpu_cp_time, &size, NULL, 0) == -1) + err(1, "sysctlbyname kern.cp_times"); + GETSYSCTL("kern.cp_time", cp_time); GETSYSCTL("vm.loadavg", sysload); GETSYSCTL("kern.lastpid", lastpid); @@ -413,21 +423,17 @@ get_system_info(struct system_info *si) for (i = 0; i < 3; i++) si->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale; - if (pcpu_stats) { - for (i = j = 0; i <= maxid; i++) { - if ((cpumask & (1ul << i)) == 0) - continue; - /* convert cp_time counts to percentages */ - percentages(CPUSTATES, &pcpu_cpu_states[j * CPUSTATES], - &pcpu_cp_time[j * CPUSTATES], - &pcpu_cp_old[j * CPUSTATES], - &pcpu_cp_diff[j * CPUSTATES]); - j++; - } - } else { - /* convert cp_time counts to percentages */ - percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); + /* convert cp_time counts to percentages */ + for (i = j = 0; i <= maxid; i++) { + if ((cpumask & (1ul << i)) == 0) + continue; + percentages(CPUSTATES, &pcpu_cpu_states[j * CPUSTATES], + &pcpu_cp_time[j * CPUSTATES], + &pcpu_cp_old[j * CPUSTATES], + &pcpu_cp_diff[j * CPUSTATES]); + j++; } + percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); /* sum memory & swap statistics */ { -- 2.45.0