[PATCH] Make top -P an interactive toggle
Alexander Best
arundel at freebsd.org
Fri Jul 8 21:50:51 UTC 2011
On Fri Jul 8 11, John Baldwin wrote:
> This patch lets you use 'P' while top is running to toggle between per-CPU and
> global CPU stats.
very cool. i always thought that being able to interactivly enable/disable
per-cpu stats in top would be a useful feature. great to see this being
implemented.
top is nearing perfection. ;)
>
> Index: contrib/top/top.c
> ===================================================================
> --- contrib/top/top.c (revision 223873)
> +++ contrib/top/top.c (working copy)
> @@ -196,9 +196,9 @@
> 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 @@
> #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 @@
> break;
>
> case 'P':
> - pcpu_stats = Yes;
> + pcpu_stats = !pcpu_stats;
> break;
>
> case 'z':
> @@ -1088,6 +1089,12 @@
> ps.kidle ? "D" : "Not d");
> putchar('\r');
> break;
> + case CMD_pcputog:
> + pcpu_stats = !pcpu_stats;
> + toggle_pcpustats(&statics);
> + max_topn = display_updatecpus(&statics);
> + reset_display();
> + break;
> default:
> new_message(MT_standout, " BAD CASE IN SWITCH!");
> putchar('\r');
> Index: contrib/top/display.c
> ===================================================================
> --- contrib/top/display.c (revision 223873)
> +++ contrib/top/display.c (working copy)
> @@ -151,16 +151,14 @@
> return(smart_terminal ? lines : Largest);
> }
>
> -int display_init(statics)
> +int display_updatecpus(statics)
>
> struct statics *statics;
>
> {
> 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;
> @@ -170,6 +168,21 @@
> for (i = num_cpus; i > 9; i /= 10)
> cpustates_column++;
>
> + 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)
> {
> Index: contrib/top/top.X
> ===================================================================
> --- contrib/top/top.X (revision 223873)
> +++ contrib/top/top.X (working copy)
> @@ -205,6 +205,7 @@
> .BR \-H ,
> .BR \-I ,
> .BR \-j ,
> +.BR \-P ,
> .BR \-S ,
> .BR \-t ,
> .BR \-u ,
> @@ -314,6 +315,9 @@
> .IR jail (8)
> ID.
> .TP
> +.B P
> +Toggle the display of per-CPU statistics.
> +.TP
> .B t
> Toggle the display of the
> .I top
> Index: usr.bin/top/machine.c
> ===================================================================
> --- usr.bin/top/machine.c (revision 223873)
> +++ usr.bin/top/machine.c (working copy)
> @@ -239,19 +239,48 @@
> static void getsysctl(const char *name, void *ptr, size_t len);
> static int swapmode(int *retavail, int *retfree);
>
> +void
> +toggle_pcpustats(struct statics *statics)
> +{
> +
> + 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 */
> + statics->ncpus = ncpus;
> + } else {
> + y_mem = 3;
> + y_swap = 4;
> + y_idlecursor = 5;
> + y_message = 5;
> + y_header = 6;
> + y_procs = 7;
> + Header_lines = 7;
> + statics->ncpus = 1;
> + }
> +}
> +
> 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,52 +328,38 @@
> 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 = 1;
>
> + if (pcpu_stats)
> + toggle_pcpustats(statics);
> +
> /* all done! */
> return (0);
> }
> @@ -398,14 +413,11 @@
> 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 +425,17 @@
> 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 */
> {
>
> --
> John Baldwin
More information about the freebsd-current
mailing list