Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Nov 2007 05:02:04 GMT
From:      Peter Wemm <peter@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 129752 for review
Message-ID:  <200711290502.lAT524Li098430@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711290502.lAT524Li098430>