From owner-p4-projects@FreeBSD.ORG Thu Nov 29 05:02:06 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id A72C516A419; Thu, 29 Nov 2007 05:02:05 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4562216A417 for ; Thu, 29 Nov 2007 05:02:05 +0000 (UTC) (envelope-from peter@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 4B59E13C4D9 for ; Thu, 29 Nov 2007 05:02:05 +0000 (UTC) (envelope-from peter@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id lAT525KH098433 for ; Thu, 29 Nov 2007 05:02:05 GMT (envelope-from peter@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id lAT524Li098430 for perforce@freebsd.org; Thu, 29 Nov 2007 05:02:04 GMT (envelope-from peter@freebsd.org) Date: Thu, 29 Nov 2007 05:02:04 GMT Message-Id: <200711290502.lAT524Li098430@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to peter@freebsd.org using -f From: Peter Wemm To: Perforce Change Reviews Cc: Subject: PERFORCE change 129752 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Nov 2007 05:02:06 -0000 http://perforce.freebsd.org/chv.cgi?CH=129752 Change 129752 by peter@peter_overcee on 2007/11/29 05:01:39 Teach top to show per-cpu load statistics when -P is specified Affected files ... .. //depot/projects/hammer/contrib/top/display.c#4 edit .. //depot/projects/hammer/contrib/top/layout.h#2 edit .. //depot/projects/hammer/contrib/top/machine.h#5 edit .. //depot/projects/hammer/contrib/top/top.c#10 edit .. //depot/projects/hammer/contrib/top/top.h#4 edit .. //depot/projects/hammer/usr.bin/top/machine.c#21 edit Differences ... ==== //depot/projects/hammer/contrib/top/display.c#4 (text+ko) ==== @@ -78,8 +78,10 @@ static int *lmemory; static int *lswap; +static int num_cpus; static int *cpustate_columns; static int cpustate_total_length; +static int cpustates_column; static enum { OFF, ON, ERASE } header_status = ON; @@ -87,6 +89,29 @@ static void summary_format(); static void line_update(); +int x_lastpid = 10; +int y_lastpid = 0; +int x_loadave = 33; +int x_loadave_nompid = 15; +int y_loadave = 0; +int x_procstate = 0; +int y_procstate = 1; +int x_brkdn = 15; +int y_brkdn = 1; +int x_mem = 5; +int y_mem = 3; +int x_swap = 6; +int y_swap = 4; +int y_message = 5; +int x_header = 0; +int y_header = 6; +int x_idlecursor = 0; +int y_idlecursor = 5; +int y_procs = 7; + +int y_cpustates = 2; +int Header_lines = 7; + int display_resize() { @@ -138,6 +163,12 @@ /* call resize to do the dirty work */ lines = display_resize(); + num_cpus = statics->ncpus; + cpustates_column = 5; /* CPU: */ + if (num_cpus != 1) + cpustates_column += 2; /* CPU 0: */ + for (i = num_cpus; i > 9; i /= 10) + cpustates_column++; /* only do the rest if we need to */ if (lines > -1) @@ -153,7 +184,7 @@ 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)); + lcpustates = (int *)malloc(num_cpustates * sizeof(int) * num_cpus); cpustate_columns = (int *)malloc(num_cpustates * sizeof(int)); memory_names = statics->memory_names; @@ -365,14 +396,13 @@ } } +#ifdef no_more /* * *_cpustates(states, names) - print the cpu state percentages * * Assumptions: cursor is on the PREVIOUS line */ -static int cpustates_column; - /* cpustates_tag() calculates the correct tag to use to label the line */ char *cpustates_tag() @@ -398,6 +428,7 @@ cpustates_column = strlen(use); return(use); } +#endif i_cpustates(states) @@ -406,11 +437,18 @@ { register int i = 0; register int value; - register char **names = cpustate_names; + register char **names; register char *thisname; + int cpu; + +for (cpu = 0; cpu < num_cpus; cpu++) { + names = cpustate_names; /* print tag and bump lastline */ - printf("\n%s", cpustates_tag()); + if (num_cpus == 1) + printf("\nCPU: "); + else + printf("\nCPU %d: ", cpu); lastline++; /* now walk thru the names and print the line */ @@ -423,14 +461,15 @@ /* if percentage is >= 1000, print it as 100% */ printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"), - i++ == 0 ? "" : ", ", + (i++ % num_cpustates) == 0 ? "" : ", ", ((float)value)/10., thisname); } } +} /* copy over values into "last" array */ - memcpy(lcpustates, states, num_cpustates * sizeof(int)); + memcpy(lcpustates, states, num_cpustates * sizeof(int) * num_cpus); } u_cpustates(states) @@ -439,14 +478,18 @@ { register int value; - register char **names = cpustate_names; + register char **names; register char *thisname; register int *lp; register int *colp; + int cpu; + +for (cpu = 0; cpu < num_cpus; cpu++) { + names = cpustate_names; - Move_to(cpustates_column, y_cpustates); - lastline = y_cpustates; - lp = lcpustates; + Move_to(cpustates_column, y_cpustates + cpu); + lastline = y_cpustates + cpu; + lp = lcpustates + (cpu * num_cpustates); colp = cpustate_columns; /* we could be much more optimal about this */ @@ -458,8 +501,8 @@ if (*lp != *states) { /* yes, move and change */ - Move_to(cpustates_column + *colp, y_cpustates); - lastline = y_cpustates; + Move_to(cpustates_column + *colp, y_cpustates + cpu); + lastline = y_cpustates + cpu; /* retrieve value and remember it */ value = *states; @@ -479,30 +522,39 @@ colp++; } } +} z_cpustates() { register int i = 0; - register char **names = cpustate_names; + register char **names; register char *thisname; register int *lp; + int cpu; + +for (cpu = 0; cpu < num_cpus; cpu++) { + names = cpustate_names; /* show tag and bump lastline */ - printf("\n%s", cpustates_tag()); + if (num_cpus == 1) + printf("\nCPU: "); + else + printf("\nCPU %d: ", cpu); lastline++; while ((thisname = *names++) != NULL) { if (*thisname != '\0') { - printf("%s %% %s", i++ == 0 ? "" : ", ", thisname); + printf("%s %% %s", (i++ % num_cpustates) == 0 ? "" : ", ", thisname); } } +} /* fill the "last" array with all -1s, to insure correct updating */ lp = lcpustates; - i = num_cpustates; + i = num_cpustates * num_cpus; while (--i >= 0) { *lp++ = -1; ==== //depot/projects/hammer/contrib/top/layout.h#2 (text+ko) ==== @@ -6,24 +6,24 @@ * cursor addressing. */ -#define x_lastpid 10 -#define y_lastpid 0 -#define x_loadave 33 -#define x_loadave_nompid 15 -#define y_loadave 0 -#define x_procstate 0 -#define y_procstate 1 -#define x_brkdn 15 -#define y_brkdn 1 -#define x_mem 5 -#define y_mem 3 -#define x_swap 6 -#define y_swap 4 -#define y_message 5 -#define x_header 0 -#define y_header 6 -#define x_idlecursor 0 -#define y_idlecursor 5 -#define y_procs 7 +extern int x_lastpid; /* 10 */ +extern int y_lastpid; /* 0 */ +extern int x_loadave; /* 33 */ +extern int x_loadave_nompid; /* 15 */ +extern int y_loadave; /* 0 */ +extern int x_procstate; /* 0 */ +extern int y_procstate; /* 1 */ +extern int x_brkdn; /* 15 */ +extern int y_brkdn; /* 1 */ +extern int x_mem; /* 5 */ +extern int y_mem; /* 3 */ +extern int x_swap; /* 6 */ +extern int y_swap; /* 4 */ +extern int y_message; /* 5 */ +extern int x_header; /* 0 */ +extern int y_header; /* 6 */ +extern int x_idlecursor; /* 0 */ +extern int y_idlecursor; /* 5 */ +extern int y_procs; /* 7 */ -#define y_cpustates 2 +extern int y_cpustates; /* 2 */ ==== //depot/projects/hammer/contrib/top/machine.h#5 (text+ko) ==== @@ -20,6 +20,7 @@ #ifdef ORDER char **order_names; #endif + int ncpus; }; /* @@ -43,6 +44,8 @@ int *memory; int *swap; struct timeval boottime; + unsigned long cpumask; /* bitfield of cpu states represented */ + int ncpus; }; /* cpu_states is an array of percentages * 10. For example, ==== //depot/projects/hammer/contrib/top/top.c#10 (text+ko) ==== @@ -66,6 +66,7 @@ extern int overstrike; static int fmt_flags = 0; +int pcpu_stats = No; /* signal handling routines */ sigret_t leave(); @@ -282,7 +283,7 @@ optind = 1; } - while ((i = getopt(ac, av, "CSIHabijnquvs:d:U:m:o:t")) != EOF) + while ((i = getopt(ac, av, "CSIHPabijnpquvs:d:U:m:o:t")) != EOF) { switch(i) { @@ -407,6 +408,14 @@ ps.jail = !ps.jail; break; + case 'P': + pcpu_stats = Yes; + break; + + case 'p': + pcpu_stats = No; + break; + default: fprintf(stderr, "Top version %s\n" ==== //depot/projects/hammer/contrib/top/top.h#4 (text+ko) ==== @@ -11,7 +11,7 @@ #define VERSION 3 /* Number of lines of header information on the standard screen */ -#define Header_lines 7 +extern int Header_lines; /* 7 */ /* Maximum number of columns allowed for display */ #define MAX_COLS 128 @@ -45,3 +45,5 @@ #define FMT_SHOWARGS 0x00000001 extern enum displaymodes displaymode; + +extern int pcpu_stats; ==== //depot/projects/hammer/usr.bin/top/machine.c#21 (text+ko) ==== @@ -51,6 +51,7 @@ #include "machine.h" #include "screen.h" #include "utils.h" +#include "layout.h" #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) #define SMPUNAMELEN 13 @@ -216,6 +217,17 @@ }; #endif +/* Per-cpu time states */ +static int maxcpu; +static int maxid; +static int ncpus; +static u_long cpumask; +static long *times; +static long *pcpu_cp_time; +static long *pcpu_cp_old; +static long *pcpu_cp_diff; +static int *pcpu_cpu_states; + static int compare_jid(const void *a, const void *b); static int compare_pid(const void *a, const void *b); static const char *format_nice(const struct kinfo_proc *pp); @@ -280,6 +292,56 @@ 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"); + 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++; + } + } + + 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 */ + } + size = sizeof(long) * ncpus * CPUSTATES; + pcpu_cp_time = malloc(size); + pcpu_cp_old = malloc(size); + pcpu_cp_diff = malloc(size); + pcpu_cpu_states = malloc(size); + bzero(pcpu_cp_time, size); + bzero(pcpu_cp_old, size); + bzero(pcpu_cp_diff, size); + bzero(pcpu_cpu_states, size); + statics->ncpus = ncpus; + } else { + statics->ncpus = 1; + } + /* all done! */ return (0); } @@ -321,6 +383,7 @@ static int swappgsout = -1; extern struct timeval timeout; + void get_system_info(struct system_info *si) { @@ -329,10 +392,17 @@ int mib[2]; struct timeval boottime; size_t bt_size; - int i; + int i, j; + size_t size; /* get the cp_time array */ - GETSYSCTL("kern.cp_time", cp_time); + 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); + } GETSYSCTL("vm.loadavg", sysload); GETSYSCTL("kern.lastpid", lastpid); @@ -340,8 +410,20 @@ for (i = 0; i < 3; i++) si->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale; - /* convert cp_time counts to percentages */ - total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); + if (pcpu_stats) { + for (i = j = 0; i <= maxid; i++, j++) { + 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]); + } + } else { + /* convert cp_time counts to percentages */ + percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff); + } /* sum memory & swap statistics */ { @@ -395,7 +477,15 @@ } /* set arrays and strings */ - si->cpustates = cpu_states; + if (pcpu_stats) { + si->cpustates = pcpu_cpu_states; + si->cpumask = cpumask; + si->ncpus = ncpus; + } else { + si->cpustates = cpu_states; + si->cpumask = 1; + si->ncpus = 1; + } si->memory = memory_stats; si->swap = swap_stats;