From 95578ad0d6591b76fc515f8e171862fa7d3d37dc Mon Sep 17 00:00:00 2001 From: Hiten Pandya Date: Sat, 29 May 2004 05:11:15 +0000 Subject: [PATCH] First pass at updating top(1): * add command line option '-T' for displaying kernel threads such as pagedaemon, tcp_thread, and so on; the threads are now marked '' 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 for reviewing the patches and supplying me with an SMP machine to test the changes. --- contrib/top/patches/commands.c.patch | 23 +++++++ contrib/top/patches/machine.h.patch | 16 +++++ contrib/top/patches/top.X.patch | 33 ++++++++++ contrib/top/patches/top.c.patch | 83 +++++++++++++++++++++++++ contrib/top/patches/top.h.patch | 17 ++++++ usr.bin/top/Makefile | 7 ++- usr.bin/top/machine.c | 90 +++++++++++++++++++++++----- 7 files changed, 252 insertions(+), 17 deletions(-) create mode 100644 contrib/top/patches/commands.c.patch create mode 100644 contrib/top/patches/machine.h.patch create mode 100644 contrib/top/patches/top.X.patch create mode 100644 contrib/top/patches/top.c.patch create mode 100644 contrib/top/patches/top.h.patch diff --git a/contrib/top/patches/commands.c.patch b/contrib/top/patches/commands.c.patch new file mode 100644 index 0000000000..1848cbaae2 --- /dev/null +++ b/contrib/top/patches/commands.c.patch @@ -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 index 0000000000..f60ddfab45 --- /dev/null +++ b/contrib/top/patches/machine.h.patch @@ -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 index 0000000000..52ddb54d60 --- /dev/null +++ b/contrib/top/patches/top.X.patch @@ -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 index 0000000000..11c794b3d2 --- /dev/null +++ b/contrib/top/patches/top.c.patch @@ -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 index 0000000000..f3a00c0c84 --- /dev/null +++ b/contrib/top/patches/top.h.patch @@ -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(); + diff --git a/usr.bin/top/Makefile b/usr.bin/top/Makefile index 6bf2f8d4f5..8a6d455af3 100644 --- a/usr.bin/top/Makefile +++ b/usr.bin/top/Makefile @@ -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 diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c index ac42e7a0b3..0428c11439 100644 --- a/usr.bin/top/machine.c +++ b/usr.bin/top/machine.c @@ -18,9 +18,10 @@ * AUTHOR: Christos Zoulas * Steven Wallace * Wolfram Schneider + * Hiten Pandya * * $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 */ + else + wrapper = NULL; + /* get the process's command name */ - if ((PP(pp, p_flag) & P_INMEM) == 0) { - /* - * Print swapped processes as - */ + 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 /* -- 2.41.0