First pass at updating top(1):
authorHiten Pandya <hmp@dragonflybsd.org>
Sat, 29 May 2004 05:11:15 +0000 (05:11 +0000)
committerHiten Pandya <hmp@dragonflybsd.org>
Sat, 29 May 2004 05:11:15 +0000 (05:11 +0000)
* add command line option '-T' for displaying kernel threads
  such as pagedaemon, tcp_thread, and so on; the threads are
  now marked '<thread>' in the top(1) display.

* cleanup manipulation of COMMAND strings, insipired by a
  similar change in NetBSD's top(1).

* add a toggle for system processes, called 'S' so we dont
  need to restart top(1) to {un}display system processes.

* change some sprintf's to snprintfs for safety.

* update the sort/ordering top(1) commands so that it correctly
  displays kernel threads by priority time used etc.

* add a 'thr' sort order function so that kernel threads can be
  collected together in the top(1) display; this is useful when
  running it in batch mode.

* fix the screen width issue for terminals that have more than
  80 columns; this was necessary for showing threads properly in
  SMP mode.

* add ability for top(1) to sort kernel threads their priority
  (note, thread priorities are stored differently).

NOTE! top(1) is now using the contrib-patching framework just like
we do with GCC-3 so that it will be simple to update the base code
in the future if required.

CREDITS
Thanks go to Matthew Dillon <dillon@backplane.com> for reviewing the
patches and supplying me with an SMP machine to test the changes.

contrib/top/patches/commands.c.patch [new file with mode: 0644]
contrib/top/patches/machine.h.patch [new file with mode: 0644]
contrib/top/patches/top.X.patch [new file with mode: 0644]
contrib/top/patches/top.c.patch [new file with mode: 0644]
contrib/top/patches/top.h.patch [new file with mode: 0644]
usr.bin/top/Makefile
usr.bin/top/machine.c

diff --git a/contrib/top/patches/commands.c.patch b/contrib/top/patches/commands.c.patch
new file mode 100644 (file)
index 0000000..1848cba
--- /dev/null
@@ -0,0 +1,23 @@
+$DragonFly: src/contrib/top/patches/Attic/commands.c.patch,v 1.1 2004/05/29 05:11:15 hmp Exp $
+Index: contrib/top/commands.c
+===================================================================
+RCS file: /cvs/DragonFly/src/contrib/top/commands.c,v
+retrieving revision 1.2
+diff -u -p -u -r1.2 commands.c
+--- contrib/top/commands.c     17 Jun 2003 04:24:07 -0000      1.2
++++ contrib/top/commands.c     29 May 2004 01:14:21 -0000
+@@ -73,11 +73,13 @@ d       - change number of displays to s
+ e       - list errors generated by last \"kill\" or \"renice\" command\n\
+ i       - toggle the displaying of idle processes\n\
+ I       - same as 'i'\n\
++T     - toggle the displaying of threads\n\
++S     - toggle the displaying of system processes\n\
+ k       - kill processes; send a signal to a list of processes\n\
+ n or #  - change number of processes to display\n", stdout);
+ #ifdef ORDER
+       fputs("\
+-o       - specify sort order (pri, size, res, cpu, time)\n", stdout);
++o       - specify sort order (pri, size, res, cpu, time, thr)\n", stdout);
+ #endif
+       fputs("\
+ r       - renice a process\n\
diff --git a/contrib/top/patches/machine.h.patch b/contrib/top/patches/machine.h.patch
new file mode 100644 (file)
index 0000000..f60ddfa
--- /dev/null
@@ -0,0 +1,16 @@
+$DragonFly: src/contrib/top/patches/Attic/machine.h.patch,v 1.1 2004/05/29 05:11:15 hmp Exp $
+Index: contrib/top/machine.h
+===================================================================
+RCS file: /cvs/DragonFly/src/contrib/top/machine.h,v
+retrieving revision 1.2
+diff -u -p -u -r1.2 machine.h
+--- contrib/top/machine.h      17 Jun 2003 04:24:07 -0000      1.2
++++ contrib/top/machine.h      28 May 2004 00:39:30 -0000
+@@ -60,6 +60,7 @@ struct process_select
+     int idle;         /* show idle processes */
+     int self;         /* show self */
+     int system;               /* show system processes */
++    int threads;      /* show threads */
+     int uid;          /* only this uid (unless uid == -1) */
+     char *command;    /* only this command (unless == NULL) */
+ };
diff --git a/contrib/top/patches/top.X.patch b/contrib/top/patches/top.X.patch
new file mode 100644 (file)
index 0000000..52ddb54
--- /dev/null
@@ -0,0 +1,33 @@
+$DragonFly: src/contrib/top/patches/Attic/top.X.patch,v 1.1 2004/05/29 05:11:15 hmp Exp $
+Index: contrib/top/top.X
+===================================================================
+RCS file: /cvs/src/contrib/top/top.X,v
+retrieving revision 1.2
+diff -p -u -r1.2 top.X
+--- contrib/top/top.X  17 Jun 2003 04:24:07 -0000      1.2
++++ contrib/top/top.X  29 May 2004 04:39:35 -0000
+@@ -65,6 +65,11 @@ terminal.
+ Show system processes in the display.  Normally, system processes such as
+ the pager and the swapper are not shown.  This option makes them visible.
+ .TP
++.B \-T
++Show kernel threads in the display.  Normally, kernel threads such as
++the pagedaemon and bufdaemon are not shown.  This option makes them
++visible.
++.TP
+ .B \-b
+ Use \*(lqbatch\*(rq mode.  In this mode, all input from the terminal is
+ ignored.  Interrupt characters (such as ^C and ^\e) still have an effect.
+@@ -203,6 +208,12 @@ Redraw the screen.
+ Display a summary of the commands (help screen).  Version information
+ is included in this display.
+ .TP
++.B S
++Display system processes.
++.TP
++.B T
++Display kernel threads, such as bufdaemon and pagedaemon.
++.TP
+ .B q
+ Quit
+ .IR top.
diff --git a/contrib/top/patches/top.c.patch b/contrib/top/patches/top.c.patch
new file mode 100644 (file)
index 0000000..11c794b
--- /dev/null
@@ -0,0 +1,83 @@
+$DragonFly: src/contrib/top/patches/Attic/top.c.patch,v 1.1 2004/05/29 05:11:15 hmp Exp $
+Index: contrib/top/top.c
+===================================================================
+RCS file: /cvs/DragonFly/src/contrib/top/top.c,v
+retrieving revision 1.2
+diff -u -p -u -r1.2 top.c
+--- contrib/top/top.c  17 Jun 2003 04:24:07 -0000      1.2
++++ contrib/top/top.c  29 May 2004 01:02:10 -0000
+@@ -193,9 +193,9 @@ char *argv[];
+     fd_set readfds;
+ #ifdef ORDER
+-    static char command_chars[] = "\f qh?en#sdkriIuto";
++    static char command_chars[] = "\f qh?en#sdkriIutTSo";
+ #else
+-    static char command_chars[] = "\f qh?en#sdkriIut";
++    static char command_chars[] = "\f qh?en#sdkriIutTS";
+ #endif
+ /* these defines enumerate the "strchr"s of the commands in command_chars */
+ #define CMD_redraw    0
+@@ -215,8 +215,10 @@ char *argv[];
+ #define CMD_idletog2    13
+ #define CMD_user      14
+ #define CMD_selftog   15
++#define CMD_threads   16
++#define CMD_system    17
+ #ifdef ORDER
+-#define CMD_order       16
++#define CMD_order       18
+ #endif
+     /* set the buffer for stdout */
+@@ -245,6 +247,7 @@ char *argv[];
+     ps.idle    = Yes;
+     ps.self    = -1;
+     ps.system  = No;
++    ps.threads = No;
+     ps.uid     = -1;
+     ps.command = NULL;
+@@ -271,7 +274,7 @@ char *argv[];
+           optind = 1;
+       }
+-      while ((i = getopt(ac, av, "SIbinquvs:d:U:o:t")) != EOF)
++      while ((i = getopt(ac, av, "SITNbinquvs:d:U:o:t")) != EOF)
+       {
+           switch(i)
+           {
+@@ -300,6 +303,10 @@ char *argv[];
+             case 'I':                   /* show idle processes */
+               ps.idle = !ps.idle;
+               break;
++      
++            case 'T':
++              ps.threads = !ps.threads;       /* show threads */
++              break;
+             case 'i':                 /* go interactive regardless */
+               interactive = Yes;
+@@ -928,6 +935,22 @@ restart:
+                               putchar('\r');
+                               break;
++                          case CMD_threads:
++                              ps.threads = !ps.threads;
++                              new_message(MT_standout | MT_delayed,
++                                 " %sisplaying threads.",
++                                 ps.threads ? "D" : "Not d");
++                              putchar('\r');
++                              break;
++
++                          case CMD_system:
++                              ps.system = !ps.system;
++                              new_message(MT_standout | MT_delayed,
++                                 " %sisplaying system processes.",
++                                 ps.system ? "D" : "Not d");
++                              putchar('\r');
++                              break;
++
+                           case CMD_user:
+                               new_message(MT_standout,
+                                   "Username to show: ");
diff --git a/contrib/top/patches/top.h.patch b/contrib/top/patches/top.h.patch
new file mode 100644 (file)
index 0000000..f3a00c0
--- /dev/null
@@ -0,0 +1,17 @@
+$DragonFly: src/contrib/top/patches/Attic/top.h.patch,v 1.1 2004/05/29 05:11:15 hmp Exp $
+Index: contrib/top/top.h
+===================================================================
+RCS file: /cvs/src/contrib/top/top.h,v
+retrieving revision 1.1
+diff -p -u -r1.1 top.h
+--- contrib/top/top.h  17 Jun 2003 02:47:20 -0000      1.1
++++ contrib/top/top.h  29 May 2004 02:21:56 -0000
+@@ -16,6 +16,8 @@
+ /* Log base 2 of 1024 is 10 (2^10 == 1024) */
+ #define LOG1024               10
++extern int screen_width;
++
+ char *itoa();
+ char *itoa7();
index 6bf2f8d..8a6d455 100644 (file)
@@ -1,5 +1,5 @@
 # $FreeBSD: src/usr.bin/top/Makefile,v 1.5.6.2 2002/08/11 17:09:54 dwmalone Exp $
-# $DragonFly: src/usr.bin/top/Makefile,v 1.2 2003/06/17 04:29:33 dillon Exp $
+# $DragonFly: src/usr.bin/top/Makefile,v 1.3 2004/05/29 05:11:15 hmp Exp $
 PROG=  top
 
 TOPDIR=        ${.CURDIR}/../../contrib/top
@@ -16,7 +16,10 @@ CFLAGS+= -DHAVE_GETOPT -DHAVE_STRERROR -I${.CURDIR} -I${TOPDIR} -I. -DORDER
 CFLAGS+= -D"Table_size=${TOP_TABLE_SIZE}"
 .endif
 
-SRCS=  commands.c display.c machine.c screen.c top.c \
+CONTRIBDIR=    ${TOPDIR}
+PATCHES!=       echo ${TOPDIR}/patches/*.patch
+
+SRCS=  ${PATCHES} commands.c display.c machine.c screen.c top.c \
        username.c utils.c version.c top.local.h
 
 CLEANFILES+= top.local.h top.x top.1
index ac42e7a..0428c11 100644 (file)
  * AUTHOR:  Christos Zoulas <christos@ee.cornell.edu>
  *          Steven Wallace  <swallace@freebsd.org>
  *          Wolfram Schneider <wosch@FreeBSD.org>
+ *          Hiten Pandya <hmp@backplane.com>
  *
  * $FreeBSD: src/usr.bin/top/machine.c,v 1.29.2.2 2001/07/31 20:27:05 tmm Exp $
- * $DragonFly: src/usr.bin/top/machine.c,v 1.10 2003/11/21 22:46:14 dillon Exp $
+ * $DragonFly: src/usr.bin/top/machine.c,v 1.11 2004/05/29 05:11:15 hmp Exp $
  */
 
 
@@ -62,6 +63,11 @@ static int smpmode;
 static int namelength;
 static int cmdlength;
 
+/* 
+ * needs to be a global symbol, so wrapper can be
+ * modified accordingly.
+ */
+static int show_threads = 0;
 
 /* get_process_info passes back a handle.  This is what it looks like: */
 
@@ -212,7 +218,7 @@ long percentages();
 #ifdef ORDER
 /* sorting orders. first is default */
 char *ordernames[] = {
-    "cpu", "size", "res", "time", "pri", NULL
+    "cpu", "size", "res", "time", "pri", "thr", NULL
 };
 #endif
 
@@ -308,7 +314,12 @@ char *format_header(register char *uname_field)
     snprintf(Header, sizeof(Header), smpmode ? smp_header : up_header,
             namelength, namelength, uname_field);
 
-    cmdlength = 80 - strlen(Header) + 6;
+    if (screen_width <= 79)
+       cmdlength = 80;
+    else
+       cmdlength = 89;
+
+    cmdlength = cmdlength - strlen(Header) + 6;
 
     return Header;
 }
@@ -479,6 +490,7 @@ caddr_t get_process_info(struct system_info *si, struct process_select *sel,
     show_idle = sel->idle;
     show_self = sel->self;
     show_system = sel->system;
+    show_threads = sel->threads;
     show_uid = sel->uid != -1;
     show_command = sel->command != NULL;
 
@@ -495,14 +507,16 @@ caddr_t get_process_info(struct system_info *si, struct process_select *sel,
         *  status field.  Processes with P_SYSTEM set are system
         *  processes---these get ignored unless show_sysprocs is set.
         */
-       if (PP(pp, p_stat) != 0 &&
+       if ((show_threads && (TP(pp, td_proc) == NULL)) ||
+           PP(pp, p_stat) != 0 &&
            (show_self != PP(pp, p_pid)) &&
            (show_system || ((PP(pp, p_flag) & P_SYSTEM) == 0)))
        {
            total_procs++;
            process_states[(unsigned char) PP(pp, p_stat)]++;
-           if ((PP(pp, p_stat) != SZOMB) &&
-               (show_idle || (PP(pp, p_pctcpu) != 0) || 
+           if ((show_threads && (TP(pp, td_proc) == NULL)) ||
+               (PP(pp, p_stat) != SZOMB) &&
+               (show_idle || (PP(pp, p_pctcpu) != 0) ||
                 (PP(pp, p_stat) == SRUN)) &&
                (!show_uid || EP(pp, e_ucred.cr_ruid) == (uid_t)sel->uid))
            {
@@ -537,6 +551,7 @@ char *format_next_process(caddr_t handle, char *(*get_userid)())
     double pct;
     struct handle *hp;
     char status[16];
+    char const *wrapper;
     int state;
     int nice;
 
@@ -545,19 +560,26 @@ char *format_next_process(caddr_t handle, char *(*get_userid)())
     pp = *(hp->next_proc++);
     hp->remaining--;
     
+    /* set the wrapper for the process/thread name */
+    if ((PP(pp, p_flag) & P_INMEM) == 0)
+        wrapper = "[]"; /* swapped process [pname] */
+    else if (((PP(pp, p_flag) & P_SYSTEM) != 0) && (TP(pp, td_proc) != NULL))
+        wrapper = "()"; /* system process (pname) */
+    else if (show_threads && (TP(pp, td_proc) == NULL))
+        wrapper = "<>"; /* pure kernel threads <thread> */
+    else
+        wrapper = NULL;
+  
     /* get the process's command name */
-    if ((PP(pp, p_flag) & P_INMEM) == 0) {
-       /*
-        * Print swapped processes as <pname>
-        */
+    if (wrapper != NULL) {
        char *comm = TP(pp, td_comm);
 #define COMSIZ sizeof(TP(pp, td_comm))
        char buf[COMSIZ];
        (void) strncpy(buf, comm, COMSIZ);
-       comm[0] = '<';
+       comm[0] = wrapper[0];
        (void) strncpy(&comm[1], buf, COMSIZ - 2);
        comm[COMSIZ - 2] = '\0';
-       (void) strncat(comm, ">", COMSIZ - 1);
+       (void) strncat(comm, &wrapper[1], COMSIZ - 1);
        comm[COMSIZ - 1] = '\0';
     }
 
@@ -618,12 +640,13 @@ char *format_next_process(caddr_t handle, char *(*get_userid)())
 
 
     /* format this entry */
-    sprintf(fmt,
+    snprintf(fmt, sizeof(fmt),
            smpmode ? smp_Proc_format : up_Proc_format,
            PP(pp, p_pid),
            namelength, namelength,
            (*get_userid)(EP(pp, e_ucred.cr_ruid)),
-           PP(pp, p_priority),
+           (show_threads && (TP(pp, td_proc) == NULL)) ? TP(pp, td_pri) :
+               PP(pp, p_priority),
            nice,
            format_k2(PROCSIZE(pp)),
            format_k2(pagetok(VP(pp, vm_rssize))),
@@ -743,6 +766,12 @@ static unsigned char sorted_state[] =
 #define ORDERKEY_PRIO \
   if ((result = PP(p2, p_priority) - PP(p1, p_priority)) == 0)
 
+#define ORDERKEY_KTHREADS \
+  if ((result = (TP(p1, td_proc) == NULL) - (TP(p2, td_proc) == NULL)) == 0)
+
+#define ORDERKEY_KTHREADS_PRIO \
+  if ((result = TP(p2, td_pri) - TP(p1, td_pri)) == 0)
+
 #define ORDERKEY_RSSIZE \
   if ((result = VP(p2, vm_rssize) - VP(p1, vm_rssize)) == 0) 
 
@@ -780,7 +809,7 @@ proc_compare(struct proc **pp1, struct proc **pp2)
 
 #ifdef ORDER
 /* compare routines */
-int compare_size(), compare_res(), compare_time(), compare_prio();
+int compare_size(), compare_res(), compare_time(), compare_prio(), compare_thr();
 
 int (*proc_compares[])() = {
     compare_cpu,
@@ -788,6 +817,7 @@ int (*proc_compares[])() = {
     compare_res,
     compare_time,
     compare_prio,
+    compare_thr,
     NULL
 };
 
@@ -857,6 +887,8 @@ compare_time(struct proc **pp1, struct proc **pp2)
 
     ORDERKEY_CPTICKS
     ORDERKEY_PCTCPU
+    ORDERKEY_KTHREADS
+    ORDERKEY_KTHREADS_PRIO
     ORDERKEY_STATE
     ORDERKEY_PRIO
     ORDERKEY_RSSIZE
@@ -880,6 +912,8 @@ compare_prio(struct proc **pp1, struct proc **pp2)
     p1 = *(struct kinfo_proc **) pp1;
     p2 = *(struct kinfo_proc **) pp2;
 
+    ORDERKEY_KTHREADS
+    ORDERKEY_KTHREADS_PRIO
     ORDERKEY_PRIO
     ORDERKEY_CPTICKS
     ORDERKEY_PCTCPU
@@ -890,6 +924,32 @@ compare_prio(struct proc **pp1, struct proc **pp2)
 
     return(result);
 }
+
+int
+compare_thr(struct proc **pp1, struct proc **pp2)
+{
+    register struct kinfo_proc *p1;
+    register struct kinfo_proc *p2;
+    register int result;
+    register pctcpu lresult;
+
+    /* remove one level of indirection */
+    p1 = *(struct kinfo_proc **) pp1;
+    p2 = *(struct kinfo_proc **) pp2;
+
+    ORDERKEY_KTHREADS
+    ORDERKEY_KTHREADS_PRIO
+    ORDERKEY_CPTICKS
+    ORDERKEY_PCTCPU
+    ORDERKEY_STATE
+    ORDERKEY_RSSIZE
+    ORDERKEY_MEM
+    ;
+
+    return(result);
+}
+
+
 #endif
 
 /*