From eae5910982acd983a47a3d98046dc0af087d9862 Mon Sep 17 00:00:00 2001 From: keramida Date: Thu, 14 Apr 2005 15:02:03 +0000 Subject: - Add a THR column to the process listing, that shows the number of threads a process has. The THR column is disabled and disappears when 'H' is hit, because then every thread gets its own output line. - Allow sorting processes by "threads". Approved by: davidxu Inspired by: Jiawei Ye --- contrib/top/commands.c | 2 +- contrib/top/top.c | 8 +++--- usr.bin/top/machine.c | 69 +++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/contrib/top/commands.c b/contrib/top/commands.c index b79e19a..8d7f331 100644 --- a/contrib/top/commands.c +++ b/contrib/top/commands.c @@ -78,7 +78,7 @@ n or # - change number of processes to display\n", stdout); #ifdef ORDER if (displaymode == DISP_CPU) fputs("\ -o - specify sort order (pri, size, res, cpu, time)\n", stdout); +o - specify sort order (pri, size, res, cpu, time, threads)\n", stdout); else fputs("\ o - specify sort order (vcsw, ivcsw, read, write, fault, total)\n", stdout); diff --git a/contrib/top/top.c b/contrib/top/top.c index d3e1c56..2f7fa2f 100644 --- a/contrib/top/top.c +++ b/contrib/top/top.c @@ -84,6 +84,7 @@ void quit(); static int max_topn; /* maximum displayable processes */ /* miscellaneous things */ +struct process_select ps; char *myname = "top"; jmp_buf jmp_int; @@ -179,7 +180,6 @@ char *argv[]; char *iptr; char no_command = 1; struct timeval timeout; - struct process_select ps; #ifdef ORDER char *order_name = NULL; int order_index = 0; @@ -987,8 +987,10 @@ restart: case CMD_thrtog: ps.thread = !ps.thread; new_message(MT_standout | MT_delayed, - " %sisplaying threads.", - ps.thread ? "D" : "Not d"); + "Displaying threads %s", + ps.thread ? "separately" : "as a count"); + header_text = format_header(uname_field); + reset_display(); putchar('\r'); break; case CMD_viewtog: diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c index 44b0470..98248d5 100644 --- a/usr.bin/top/machine.c +++ b/usr.bin/top/machine.c @@ -55,6 +55,7 @@ static void getsysctl(char *, void *, size_t); #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) +extern struct process_select ps; extern char* printable(char *); int swapmode(int *retavail, int *retfree); static int smpmode; @@ -101,18 +102,21 @@ static char io_header[] = #define io_Proc_format \ "%5d %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s" +static char smp_header_thr[] = + " PID %-*.*s THR PRI NICE SIZE RES STATE C TIME WCPU CPU COMMAND"; static char smp_header[] = - " PID %-*.*s PRI NICE SIZE RES STATE C TIME WCPU CPU COMMAND"; + " PID %-*.*s " "PRI NICE SIZE RES STATE C TIME WCPU CPU COMMAND"; #define smp_Proc_format \ - "%5d %-*.*s %3d %4d%7s %6s %-6.6s %1x%7s %5.2f%% %5.2f%% %.*s" + "%5d %-*.*s %s%3d %4d%7s %6s %-6.6s %1x%7s %5.2f%% %5.2f%% %.*s" +static char up_header_thr[] = + " PID %-*.*s THR PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; static char up_header[] = - " PID %-*.*s PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; + " PID %-*.*s " "PRI NICE SIZE RES STATE TIME WCPU CPU COMMAND"; #define up_Proc_format \ - "%5d %-*.*s %3d %4d%7s %6s %-6.6s%.0d%7s %5.2f%% %5.2f%% %.*s" - + "%5d %-*.*s %s%3d %4d%7s %6s %-6.6s%.0d%7s %5.2f%% %5.2f%% %.*s" /* process state names for the "STATE" column of the display */ @@ -208,11 +212,10 @@ long percentages(); #ifdef ORDER /* - * Sorting orders. One vector per display mode. - * The first element is the default for each mode. + * Sorting orders. The first element is the default. */ char *ordernames[] = { - "cpu", "size", "res", "time", "pri", + "cpu", "size", "res", "time", "pri", "threads", "total", "read", "write", "fault", "vcsw", "ivcsw", NULL }; #endif @@ -286,7 +289,15 @@ format_header(char *uname_field) switch (displaymode) { case DISP_CPU: - prehead = smpmode ? smp_header : up_header; + /* + * The logic of picking the right header format seems reverse + * here because we only want to display a THR column when + * "thread mode" is off (and threads are not listed as + * separate lines). + */ + prehead = smpmode ? + (ps.thread ? smp_header : smp_header_thr) : + (ps.thread ? up_header : up_header_thr); break; case DISP_IO: prehead = io_header; @@ -646,6 +657,7 @@ format_next_process(caddr_t handle, char *(*get_userid)(int)) int state; struct rusage ru, *rup; long p_tot, s_tot; + char *proc_fmt, thr_buf[7]; /* find and remember the next proc structure */ hp = (struct handle *)handle; @@ -737,12 +749,20 @@ format_next_process(caddr_t handle, char *(*get_userid)(int)) printable(pp->ki_comm)); return (fmt); } + /* format this entry */ - sprintf(fmt, - smpmode ? smp_Proc_format : up_Proc_format, + proc_fmt = smpmode ? smp_Proc_format : up_Proc_format; + if (ps.thread != 0) + thr_buf[0] = '\0'; + else + snprintf(thr_buf, sizeof(thr_buf), "%*d ", + sizeof(thr_buf) - 2, pp->ki_numthreads); + + sprintf(fmt, proc_fmt, pp->ki_pid, namelength, namelength, (*get_userid)(pp->ki_ruid), + thr_buf, pp->ki_pri.pri_level - PZERO, /* @@ -849,6 +869,12 @@ static int sorted_state[] = return (diff > 0 ? 1 : -1); \ } while (0) +#define ORDERKEY_THREADS(a, b) do { \ + int diff = (int)(b)->ki_numthreads - (int)(a)->ki_numthreads; \ + if (diff != 0) \ + return (diff > 0 ? 1 : -1); \ +} while (0) + #define ORDERKEY_RSSIZE(a, b) do { \ long diff = (long)(b)->ki_rssize - (long)(a)->ki_rssize; \ if (diff != 0) \ @@ -885,7 +911,7 @@ proc_compare(void *arg1, void *arg2) #ifdef ORDER /* compare routines */ -int compare_size(), compare_res(), compare_time(), compare_prio(); +int compare_size(), compare_res(), compare_time(), compare_prio(), compare_threads(); /* io compare routines */ int compare_iototal(), compare_ioread(), compare_iowrite(), compare_iofault(), compare_vcsw(), compare_ivcsw(); @@ -895,6 +921,7 @@ int (*compares[])() = { compare_res, compare_time, compare_prio, + compare_threads, compare_iototal, compare_ioread, compare_iowrite, @@ -975,6 +1002,24 @@ compare_prio(void *arg1, void *arg2) return (0); } + +/* compare_threads - the comparison function for sorting by threads */ +int +compare_threads(void *arg1, void *arg2) +{ + struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1; + struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2; + + ORDERKEY_THREADS(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 /* compare_io - the comparison function for sorting by total io */ -- cgit v1.1