svn commit: r305414 - in head: contrib/top usr.bin/top

Dag-Erling Smørgrav des at FreeBSD.org
Mon Sep 5 08:27:06 UTC 2016


Author: des
Date: Mon Sep  5 08:27:04 2016
New Revision: 305414
URL: https://svnweb.freebsd.org/changeset/base/305414

Log:
  Add a toggle to display the approximate amount of swap used by each
  process.  We don't *quite* pull that number out of our backside, as
  the actual number is difficult to determine without modifying the VM
  system to report it, but it's still useful to get an idea of what's
  going on when a machine unexpectedly starts swapping.
  
  MFC after:	1 week

Modified:
  head/contrib/top/commands.c
  head/contrib/top/machine.h
  head/contrib/top/top.c
  head/contrib/top/top.xs
  head/usr.bin/top/machine.c

Modified: head/contrib/top/commands.c
==============================================================================
--- head/contrib/top/commands.c	Mon Sep  5 06:46:04 2016	(r305413)
+++ head/contrib/top/commands.c	Mon Sep  5 08:27:04 2016	(r305414)
@@ -104,6 +104,7 @@ S       - toggle the displaying of syste
 a       - toggle the displaying of process titles\n\
 t       - toggle the display of this process\n\
 u       - display processes for only one user (+ selects all users)\n\
+w       - toggle the display of swap use for each process\n\
 z       - toggle the displaying of the system idle process\n\
 \n\
 \n", stdout);

Modified: head/contrib/top/machine.h
==============================================================================
--- head/contrib/top/machine.h	Mon Sep  5 06:46:04 2016	(r305413)
+++ head/contrib/top/machine.h	Mon Sep  5 08:27:04 2016	(r305414)
@@ -72,6 +72,7 @@ struct process_select
     int wcpu;		/* show weighted cpu */
     int jid;		/* only this jid (unless jid == -1) */
     int jail;		/* show jail ID */
+    int swap;		/* show swap usage */
     int kidle;		/* show per-CPU idle threads */
     char *command;	/* only this command (unless == NULL) */
 };
@@ -82,8 +83,8 @@ char	*format_header();
 char	*format_next_process();
 void	 toggle_pcpustats(void);
 void	 get_system_info(struct system_info *si);
-int		 machine_init(struct statics *statics, char do_unames);
-int		 proc_owner(int pid);
+int	 machine_init(struct statics *statics, char do_unames);
+int	 proc_owner(int pid);
 
 /* non-int routines typically used by the machine dependent module */
 char	*printable();

Modified: head/contrib/top/top.c
==============================================================================
--- head/contrib/top/top.c	Mon Sep  5 06:46:04 2016	(r305413)
+++ head/contrib/top/top.c	Mon Sep  5 08:27:04 2016	(r305414)
@@ -188,9 +188,9 @@ char *argv[];
     fd_set readfds;
 
 #ifdef ORDER
-    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJo";
+    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJwo";
 #else
-    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJ";
+    static char command_chars[] = "\f qh?en#sdkriIutHmSCajzPJw";
 #endif
 /* these defines enumerate the "strchr"s of the commands in command_chars */
 #define CMD_redraw	0
@@ -219,8 +219,9 @@ char *argv[];
 #define CMD_kidletog	22
 #define CMD_pcputog	23
 #define CMD_jail	24
+#define CMD_swaptog	25
 #ifdef ORDER
-#define CMD_order       25
+#define CMD_order       26
 #endif
 
     /* set the buffer for stdout */
@@ -254,6 +255,7 @@ char *argv[];
     ps.wcpu    = 1;
     ps.jid     = -1;
     ps.jail    = No;
+    ps.swap    = No;
     ps.kidle   = Yes;
     ps.command = NULL;
 
@@ -280,7 +282,7 @@ char *argv[];
 	    optind = 1;
 	}
 
-	while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:t")) != EOF)
+	while ((i = getopt(ac, av, "CSIHPabijJ:nquvzs:d:U:m:o:tw")) != EOF)
 	{
 	    switch(i)
 	    {
@@ -418,6 +420,10 @@ char *argv[];
 		pcpu_stats = !pcpu_stats;
 		break;
 
+	      case 'w':
+		ps.swap = 1;
+		break;
+
 	      case 'z':
 		ps.kidle = !ps.kidle;
 		break;
@@ -1141,6 +1147,15 @@ restart:
 				reset_display();
 				putchar('\r');
 				break;
+			    case CMD_swaptog:
+				ps.swap = !ps.swap;
+				new_message(MT_standout | MT_delayed,
+				    " %sisplaying per-process swap usage.",
+				    ps.swap ? "D" : "Not d");
+				header_text = format_header(uname_field);
+				reset_display();
+				putchar('\r');
+				break;
 			    default:
 				new_message(MT_standout, " BAD CASE IN SWITCH!");
 				putchar('\r');

Modified: head/contrib/top/top.xs
==============================================================================
--- head/contrib/top/top.xs	Mon Sep  5 06:46:04 2016	(r305413)
+++ head/contrib/top/top.xs	Mon Sep  5 08:27:04 2016	(r305414)
@@ -10,7 +10,7 @@ top \- display and update information ab
 .SH SYNOPSIS
 .B top
 [
-.B \-abCHIijnPqStuvz
+.B \-abCHIijnPqStuvwz
 ] [
 .BI \-d count
 ] [
@@ -148,6 +148,9 @@ Write version number information to stde
 No other processing takes place when this option is used.  To see current
 revision information while top is running, use the help command \*(lq?\*(rq.
 .TP
+.B \-w
+Display approximate swap usage for each process.
+.TP
 .B \-z
 Do not display the system idle process.
 .TP
@@ -167,11 +170,12 @@ Set the delay between screen updates to
 seconds.  The default delay between updates is \nD seconds.
 .TP
 .BI \-o field
-Sort the process display area on the specified field.  The field name is
-the name of the column as seen in the output, but in lower case.  Likely
-values are \*(lqcpu\*(rq, \*(lqsize\*(rq, \*(lqres\*(rq, and \*(lqtime\*(rq,
-but may vary on different operating systems.  Note that
-not all operating systems support this option.
+Sort the process display area on the specified field.  The field name
+is the name of the column as seen in the output, but in lower case:
+\*(lqcpu\*(lq, \*(rqsize\*(lq, \*(rqres\*(lq, \*(rqtime\*(lq,
+\*(rqpri\*(lq, \*(rqthreads\*(lq, \*(lqtotal\*(lq, \*(rqread\*(lq,
+\*(rqwrite\*(lq, \*(rqfault\*(lq, \*(rqvcsw\*(lq, \*(rqivcsw\*(lq,
+\*(lqjid\*(lq, \*(rqswap\*(lq or \*(rqpid\*(lq.
 .TP
 .BI \-J jail
 Show only those processes owned by
@@ -226,6 +230,7 @@ The options
 .BR \-S ,
 .BR \-t ,
 .BR \-u ,
+.BR \-w ,
 and
 .B \-z
 are actually toggles.  A second specification of any of these options
@@ -346,6 +351,9 @@ Toggle the display of the
 .I top
 process.
 .TP
+.B w
+Toggle the display of swap usage.
+.TP
 .B z
 Toggle the display of the system idle process.
 .SH "THE DISPLAY"
@@ -379,8 +387,9 @@ is specified, a UID column will be subst
 PRI is the current priority of the process,
 NICE is the nice amount (in the range \-20 to 20),
 SIZE is the total size of the process (text, data, and stack),
-RES is the current amount of resident memory (both SIZE and RES are
-given in kilobytes),
+RES is the current amount of resident memory,
+SWAP is the approximate amount of swap, if enabled
+(SIZE, RES and SWAP are given in kilobytes),
 STATE is the current state (one of \*(lqSTART\*(rq, \*(lqRUN\*(rq
 (shown as \*(lqCPUn\*(rq on SMP systems), \*(lqSLEEP\*(rq, \*(lqSTOP\*(rq,
 \*(lqZOMB\*(rq, \*(lqWAIT\*(rq, \*(lqLOCK\*(rq or the event on which the

Modified: head/usr.bin/top/machine.c
==============================================================================
--- head/usr.bin/top/machine.c	Mon Sep  5 06:46:04 2016	(r305413)
+++ head/usr.bin/top/machine.c	Mon Sep  5 08:27:04 2016	(r305414)
@@ -69,7 +69,9 @@ static int namelength = 8;
 #endif
 /* TOP_JID_LEN based on max of 999999 */
 #define TOP_JID_LEN 7
+#define TOP_SWAP_LEN 6
 static int jidlength;
+static int swaplength;
 static int cmdlengthdelta;
 
 /* Prototypes for top internals */
@@ -111,20 +113,20 @@ static char io_header[] =
     "%5d%*s %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s"
 
 static char smp_header_thr[] =
-    "  PID%*s %-*.*s  THR PRI NICE   SIZE    RES STATE   C   TIME %7s COMMAND";
+    "  PID%*s %-*.*s  THR PRI NICE   SIZE    RES%*s STATE   C   TIME %7s COMMAND";
 static char smp_header[] =
-    "  PID%*s %-*.*s "   "PRI NICE   SIZE    RES STATE   C   TIME %7s COMMAND";
+    "  PID%*s %-*.*s "   "PRI NICE   SIZE    RES%*s STATE   C   TIME %7s COMMAND";
 
 #define smp_Proc_format \
-    "%5d%*s %-*.*s %s%3d %4s%7s %6s %-6.6s %2d%7s %6.2f%% %.*s"
+    "%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s %2d%7s %6.2f%% %.*s"
 
 static char up_header_thr[] =
-    "  PID%*s %-*.*s  THR PRI NICE   SIZE    RES STATE    TIME %7s COMMAND";
+    "  PID%*s %-*.*s  THR PRI NICE   SIZE    RES%*s STATE    TIME %7s COMMAND";
 static char up_header[] =
-    "  PID%*s %-*.*s "   "PRI NICE   SIZE    RES STATE    TIME %7s COMMAND";
+    "  PID%*s %-*.*s "   "PRI NICE   SIZE    RES%*s STATE    TIME %7s COMMAND";
 
 #define up_Proc_format \
-    "%5d%*s %-*.*s %s%3d %4s%7s %6s %-6.6s%.0d%7s %6.2f%% %.*s"
+    "%5d%*s %-*.*s %s%3d %4s%7s %6s%*.*s %-6.6s%.0d%7s %6.2f%% %.*s"
 
 
 /* process state names for the "STATE" column of the display */
@@ -227,6 +229,10 @@ static int pageshift;		/* log base 2 of 
 
 #define pagetok(size) ((size) << pageshift)
 
+/* swap usage */
+#define ki_swap(kip) \
+    ((kip)->ki_swrss > (kip)->ki_rssize ? (kip)->ki_swrss - (kip)->ki_rssize : 0)
+
 /* useful externals */
 long percentages();
 
@@ -237,7 +243,7 @@ long percentages();
 char *ordernames[] = {
 	"cpu", "size", "res", "time", "pri", "threads",
 	"total", "read", "write", "fault", "vcsw", "ivcsw",
-	"jid", "pid", NULL
+	"jid", "swap", "pid", NULL
 };
 #endif
 
@@ -252,6 +258,7 @@ static long *pcpu_cp_old;
 static long *pcpu_cp_diff;
 static int *pcpu_cpu_states;
 
+static int compare_swap(const void *a, const void *b);
 static int compare_jid(const void *a, const void *b);
 static int compare_pid(const void *a, const void *b);
 static int compare_tid(const void *a, const void *b);
@@ -412,6 +419,11 @@ format_header(char *uname_field)
 	else
 		jidlength = 0;
 
+	if (ps.swap)
+		swaplength = TOP_SWAP_LEN + 1;  /* +1 for extra left space */
+	else
+		swaplength = 0;
+
 	switch (displaymode) {
 	case DISP_CPU:
 		/*
@@ -426,6 +438,7 @@ format_header(char *uname_field)
 		snprintf(Header, sizeof(Header), prehead,
 		    jidlength, ps.jail ? " JID" : "",
 		    namelength, namelength, uname_field,
+		    swaplength, ps.swap ? " SWAP" : "",
 		    ps.wcpu ? "WCPU" : "CPU");
 		break;
 	case DISP_IO:
@@ -902,7 +915,8 @@ format_next_process(caddr_t handle, char
 	int cpu, state;
 	struct rusage ru, *rup;
 	long p_tot, s_tot;
-	char *proc_fmt, thr_buf[6], jid_buf[TOP_JID_LEN + 1];
+	char *proc_fmt, thr_buf[6];
+	char jid_buf[TOP_JID_LEN + 1], swap_buf[TOP_SWAP_LEN + 1];
 	char *cmdbuf = NULL;
 	char **args;
 	const int cmdlen = 128;
@@ -1061,6 +1075,13 @@ format_next_process(caddr_t handle, char
 		snprintf(jid_buf, sizeof(jid_buf), "%*d",
 		    jidlength - 1, pp->ki_jid);
 
+	if (ps.swap == 0)
+		swap_buf[0] = '\0';
+	else
+		snprintf(swap_buf, sizeof(swap_buf), "%*s",
+		    swaplength - 1,
+		    format_k2(pagetok(ki_swap(pp)))); /* XXX */
+
 	if (displaymode == DISP_IO) {
 		oldp = get_old_proc(pp);
 		if (oldp != NULL) {
@@ -1122,6 +1143,7 @@ format_next_process(caddr_t handle, char
 	    format_nice(pp),
 	    format_k2(PROCSIZE(pp)),
 	    format_k2(pagetok(pp->ki_rssize)),
+	    swaplength, swaplength, swap_buf,
 	    status,
 	    cpu,
 	    format_time(cputime),
@@ -1309,6 +1331,12 @@ static int sorted_state[] = {
 		return (diff > 0 ? 1 : -1); \
 } while (0)
 
+#define ORDERKEY_SWAP(a, b) do { \
+	int diff = (int)ki_swap(b) - (int)ki_swap(a); \
+	if (diff != 0) \
+		return (diff > 0 ? 1 : -1); \
+} while (0)
+
 /* compare_cpu - the comparison function for sorting by cpu percentage */
 
 int
@@ -1357,6 +1385,7 @@ int (*compares[])() = {
 	compare_vcsw,
 	compare_ivcsw,
 	compare_jid,
+	compare_swap,
 	NULL
 };
 
@@ -1467,6 +1496,24 @@ compare_jid(const void *arg1, const void
 
 	return (0);
 }
+
+/* compare_swap - the comparison function for sorting by swap */
+static int
+compare_swap(const void *arg1, const void *arg2)
+{
+	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
+	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
+
+	ORDERKEY_SWAP(p1, p2);
+	ORDERKEY_PCTCPU(p1, p2);
+	ORDERKEY_CPTICKS(p1, p2);
+	ORDERKEY_STATE(p1, p2);
+	ORDERKEY_PRIO(p1, p2);
+	ORDERKEY_RSSIZE(p1, p2);
+	ORDERKEY_MEM(p1, p2);
+
+	return (0);
+}
 #endif /* ORDER */
 
 /* assorted comparison functions for sorting by i/o */


More information about the svn-src-all mailing list