Re: How does one know how many thread a process owns?

From: Giorgos Keramidas <keramida_at_freebsd.org>
Date: Wed, 13 Apr 2005 16:26:04 +0300
On 2005-04-13 17:15, Jiawei Ye <leafy7382_at_gmail.com> wrote:
> On 4/13/05, David Xu <davidxu_at_freebsd.org> wrote:
> > I believe he wants to see total threads number in a process. add a column
> > to top to display total kernel threads in per-process, p_numthreads in proc
> > structure is what you need . :)
> >
> > David Xu
>
> Exactly what I want. Is is possible to modify our top?

Can you try the following patch?

I've added a THR column when top displays only one line per process.
So when the "display each thread separately" mode is off, you should see
something like this:

% last pid: 39064;  load averages:  0.08,  0.05,  0.32     up 0+02:00:58  16:22:00
% 69 processes:  1 running, 65 sleeping, 3 stopped
% CPU states:     % user,     % nice,     % system,     % interrupt,     % idle
% Mem: 117M Active, 211M Inact, 77M Wired, 14M Cache, 54M Buf, 11M Free
% Swap: 1535M Total, 4K Used, 1535M Free
%
%   PID USERNAME THR PRI NICE   SIZE    RES STATE    TIME   WCPU    CPU COMMAND
%   662 keramida   1  96    0 84584K 29864K select   1:08  0.00%  0.00% Xorg
% 16554 keramida   4  20    0 50136K 38240K kserel   0:40  0.00%  0.00% mozilla-bin
%   700 keramida   1  96    0  6012K  4440K select   0:25  0.00%  0.00% xterm-static
%   711 root       1  96    0  3368K  2864K select   0:13  0.00%  0.00% screen
%   718 keramida   1  96    0  5348K  3772K select   0:10  0.00%  0.00% xterm-static
%   691 keramida   1  96    0  6896K  4920K select   0:09  0.00%  0.00% wmaker

The sprintf() calls near the end of format_next_process() are duplicated,
which is ugly as hell, but I couldn't find a good way to avoid the code
duplication.  If people don't have a problem with constantly displaying this
column, even when no threads are used, this will be even easier to do without
the extra clutter.  Then, we can add a sort function to order by number of
threads and then I think we're pretty much done :-)

%%%
Index: contrib/top/top.c
===================================================================
RCS file: /home/ncvs/src/contrib/top/top.c,v
retrieving revision 1.15
diff -u -r1.15 top.c
--- contrib/top/top.c	16 Aug 2004 07:51:21 -0000	1.15
+++ contrib/top/top.c	13 Apr 2005 12:56:10 -0000
_at__at_ -84,6 +84,7 _at__at_
 static int max_topn;		/* maximum displayable processes */
 
 /* miscellaneous things */
+struct process_select ps;
 char *myname = "top";
 jmp_buf jmp_int;
 
_at__at_ -179,7 +180,6 _at__at_
     char *iptr;
     char no_command = 1;
     struct timeval timeout;
-    struct process_select ps;
 #ifdef ORDER
     char *order_name = NULL;
     int order_index = 0;
_at__at_ -987,8 +987,10 _at__at_
 			    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:
Index: usr.bin/top/machine.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/top/machine.c,v
retrieving revision 1.69
diff -u -r1.69 machine.c
--- usr.bin/top/machine.c	4 Apr 2005 21:19:48 -0000	1.69
+++ usr.bin/top/machine.c	13 Apr 2005 13:18:45 -0000
_at__at_ -55,6 +55,7 _at__at_
 
 #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;
_at__at_ -101,18 +102,25 _at__at_
 #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_thr \
+	"%5d %-*.*s %3d %3d %4d%7s %6s %-6.6s %1x%7s %5.2f%% %5.2f%% %.*s"
 #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_thr \
+	"%5d %-*.*s %3d %3d %4d%7s %6s %-6.6s%.0d%7s %5.2f%% %5.2f%% %.*s"
 #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 */
_at__at_ -286,7 +294,15 _at__at_
 
 	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;
_at__at_ -646,6 +662,7 _at__at_
 	int state;
 	struct rusage ru, *rup;
 	long p_tot, s_tot;
+	char *proc_fmt;
 
 	/* find and remember the next proc structure */
 	hp = (struct handle *)handle;
_at__at_ -737,12 +754,48 _at__at_
 		    printable(pp->ki_comm));
 		return (fmt);
 	}
+
 	/* format this entry */
-	sprintf(fmt,
-	    smpmode ? smp_Proc_format : up_Proc_format,
+	proc_fmt = smpmode ?
+	    (ps.thread ? smp_Proc_format : smp_Proc_format_thr) :
+	    (ps.thread ? up_Proc_format : up_Proc_format_thr);
+
+	if (ps.thread) {
+		sprintf(fmt, proc_fmt,
+		    pp->ki_pid,
+		    namelength, namelength,
+		    (*get_userid)(pp->ki_ruid),
+		    "",
+		    pp->ki_pri.pri_level - PZERO,
+
+		    /*
+		     * normal time      -> nice value -20 - +20
+		     * real time 0 - 31 -> nice value -52 - -21
+		     * idle time 0 - 31 -> nice value +21 - +52
+		     */
+		    (pp->ki_pri.pri_class ==  PRI_TIMESHARE ?
+			pp->ki_nice - NZERO :
+			(PRI_IS_REALTIME(pp->ki_pri.pri_class) ?
+			    (PRIO_MIN - 1 - (PRI_MAX_REALTIME - pp->ki_pri.pri_level)) :
+			    (PRIO_MAX + 1 + pp->ki_pri.pri_level - PRI_MIN_IDLE))),
+		    format_k2(PROCSIZE(pp)),
+		    format_k2(pagetok(pp->ki_rssize)),
+		    status,
+		    smpmode ? pp->ki_lastcpu : 0,
+		    format_time(cputime),
+		    100.0 * weighted_cpu(pct, pp),
+		    100.0 * pct,
+		    screen_width > cmdlengthdelta ?
+		    screen_width - cmdlengthdelta :
+		    0,
+		    printable(pp->ki_comm));
+		return (fmt);
+	}
+	sprintf(fmt, proc_fmt,
 	    pp->ki_pid,
 	    namelength, namelength,
 	    (*get_userid)(pp->ki_ruid),
+	    pp->ki_numthreads,
 	    pp->ki_pri.pri_level - PZERO,
 
 	    /*
%%%
Received on Wed Apr 13 2005 - 11:26:08 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:32 UTC