xref: /freebsd/usr.bin/top/machine.c (revision faac60c8fcc31dcc5cbd4bd575a00cea18c42d7d)
1511d9c65SJoerg Wunsch /*
2511d9c65SJoerg Wunsch  * top - a top users display for Unix
3511d9c65SJoerg Wunsch  *
433d56839SNick Hibma  * SYNOPSIS:  For FreeBSD-2.x and later
5511d9c65SJoerg Wunsch  *
6511d9c65SJoerg Wunsch  * DESCRIPTION:
7511d9c65SJoerg Wunsch  * Originally written for BSD4.4 system by Christos Zoulas.
8511d9c65SJoerg Wunsch  * Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider
9f3b2c2d1SWolfram Schneider  * Order support hacked in from top-3.5beta6/machine/m_aix41.c
10f3b2c2d1SWolfram Schneider  *   by Monte Mitzelfelt (for latest top see http://www.groupsys.com/topinfo/)
11511d9c65SJoerg Wunsch  *
12511d9c65SJoerg Wunsch  * This is the machine-dependent module for FreeBSD 2.2
13511d9c65SJoerg Wunsch  * Works for:
1433d56839SNick Hibma  *	FreeBSD 2.2.x, 3.x, 4.x, and probably FreeBSD 2.1.x
15511d9c65SJoerg Wunsch  *
16511d9c65SJoerg Wunsch  * LIBS: -lkvm
17511d9c65SJoerg Wunsch  *
18511d9c65SJoerg Wunsch  * AUTHOR:  Christos Zoulas <christos@ee.cornell.edu>
19511d9c65SJoerg Wunsch  *          Steven Wallace  <swallace@freebsd.org>
20511d9c65SJoerg Wunsch  *          Wolfram Schneider <wosch@FreeBSD.org>
2139d513ecSRobert Watson  *          Thomas Moestl <tmoestl@gmx.net>
22511d9c65SJoerg Wunsch  *
23c3aac50fSPeter Wemm  * $FreeBSD$
24511d9c65SJoerg Wunsch  */
25511d9c65SJoerg Wunsch 
26511d9c65SJoerg Wunsch #include <sys/param.h>
27511d9c65SJoerg Wunsch #include <sys/errno.h>
28511d9c65SJoerg Wunsch #include <sys/file.h>
29511d9c65SJoerg Wunsch #include <sys/proc.h>
30e5aff02fSPeter Wemm #include <sys/resource.h>
31e5aff02fSPeter Wemm #include <sys/rtprio.h>
32cd23263cSDag-Erling Smørgrav #include <sys/signal.h>
33cd23263cSDag-Erling Smørgrav #include <sys/sysctl.h>
34cd23263cSDag-Erling Smørgrav #include <sys/time.h>
35cd23263cSDag-Erling Smørgrav #include <sys/user.h>
36cd23263cSDag-Erling Smørgrav #include <sys/vmmeter.h>
37511d9c65SJoerg Wunsch 
38cd23263cSDag-Erling Smørgrav #include <kvm.h>
39cd23263cSDag-Erling Smørgrav #include <math.h>
40cd23263cSDag-Erling Smørgrav #include <nlist.h>
414946a00bSDag-Erling Smørgrav #include <paths.h>
42cd23263cSDag-Erling Smørgrav #include <pwd.h>
43cd23263cSDag-Erling Smørgrav #include <stdio.h>
44511d9c65SJoerg Wunsch #include <stdlib.h>
4542649453SStefan Farfeleder #include <string.h>
4642649453SStefan Farfeleder #include <strings.h>
4739d513ecSRobert Watson #include <unistd.h>
48faac60c8SStanislav Sedov #include <vis.h>
49511d9c65SJoerg Wunsch 
50511d9c65SJoerg Wunsch #include "top.h"
51511d9c65SJoerg Wunsch #include "machine.h"
527f18d5d3SJohn Baldwin #include "screen.h"
5339d513ecSRobert Watson #include "utils.h"
54511d9c65SJoerg Wunsch 
5539d513ecSRobert Watson #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
56c413702aSDavid E. O'Brien #define	SMPUNAMELEN	13
57c413702aSDavid E. O'Brien #define	UPUNAMELEN	15
5839d513ecSRobert Watson 
5932efd263SGiorgos Keramidas extern struct process_select ps;
603f330d7dSWarner Losh extern char* printable(char *);
6194154ff8SPeter Wemm static int smpmode;
62db6bb7fcSAlfred Perlstein enum displaymodes displaymode;
63c413702aSDavid E. O'Brien static int namelength = 8;
647f18d5d3SJohn Baldwin static int cmdlengthdelta;
65511d9c65SJoerg Wunsch 
6639d513ecSRobert Watson /* Prototypes for top internals */
673f330d7dSWarner Losh void quit(int);
68511d9c65SJoerg Wunsch 
69511d9c65SJoerg Wunsch /* get_process_info passes back a handle.  This is what it looks like: */
70511d9c65SJoerg Wunsch 
71789e3877SBruce Evans struct handle {
72511d9c65SJoerg Wunsch 	struct kinfo_proc **next_proc;	/* points to next valid proc pointer */
73511d9c65SJoerg Wunsch 	int remaining;			/* number of pointers remaining */
74511d9c65SJoerg Wunsch };
75511d9c65SJoerg Wunsch 
76511d9c65SJoerg Wunsch /* declarations for load_avg */
77511d9c65SJoerg Wunsch #include "loadavg.h"
78511d9c65SJoerg Wunsch 
79511d9c65SJoerg Wunsch /* define what weighted cpu is.  */
801f7d2501SKirk McKusick #define weighted_cpu(pct, pp) ((pp)->ki_swtime == 0 ? 0.0 : \
811f7d2501SKirk McKusick 			 ((pct) / (1.0 - exp((pp)->ki_swtime * logcpu))))
82511d9c65SJoerg Wunsch 
83511d9c65SJoerg Wunsch /* what we consider to be process size: */
841f7d2501SKirk McKusick #define PROCSIZE(pp) ((pp)->ki_size / 1024)
85511d9c65SJoerg Wunsch 
86db6bb7fcSAlfred Perlstein #define RU(pp)	(&(pp)->ki_rusage)
87db6bb7fcSAlfred Perlstein #define RUTOT(pp) \
88db6bb7fcSAlfred Perlstein 	(RU(pp)->ru_inblock + RU(pp)->ru_oublock + RU(pp)->ru_majflt)
89db6bb7fcSAlfred Perlstein 
90db6bb7fcSAlfred Perlstein 
91511d9c65SJoerg Wunsch /* definitions for indices in the nlist array */
92511d9c65SJoerg Wunsch 
93511d9c65SJoerg Wunsch /*
94511d9c65SJoerg Wunsch  *  These definitions control the format of the per-process area
95511d9c65SJoerg Wunsch  */
96511d9c65SJoerg Wunsch 
97db6bb7fcSAlfred Perlstein static char io_header[] =
985d320d4bSAlfred Perlstein     "  PID %-*.*s   VCSW  IVCSW   READ  WRITE  FAULT  TOTAL PERCENT COMMAND";
99db6bb7fcSAlfred Perlstein 
100db6bb7fcSAlfred Perlstein #define io_Proc_format \
1015d320d4bSAlfred Perlstein     "%5d %-*.*s %6ld %6ld %6ld %6ld %6ld %6ld %6.2f%% %.*s"
102db6bb7fcSAlfred Perlstein 
10332efd263SGiorgos Keramidas static char smp_header_thr[] =
104bbf750fbSGiorgos Keramidas     "  PID %-*.*s  THR PRI NICE   SIZE    RES STATE  C   TIME %6s COMMAND";
10594154ff8SPeter Wemm static char smp_header[] =
106bbf750fbSGiorgos Keramidas     "  PID %-*.*s "   "PRI NICE   SIZE    RES STATE  C   TIME %6s COMMAND";
107511d9c65SJoerg Wunsch 
10894154ff8SPeter Wemm #define smp_Proc_format \
109de916c8bSBruce Evans     "%5d %-*.*s %s%3d %4s%7s %6s %-6.6s %1x%7s %5.2f%% %.*s"
110511d9c65SJoerg Wunsch 
11132efd263SGiorgos Keramidas static char up_header_thr[] =
112bbf750fbSGiorgos Keramidas     "  PID %-*.*s  THR PRI NICE   SIZE    RES STATE    TIME %6s COMMAND";
11394154ff8SPeter Wemm static char up_header[] =
114bbf750fbSGiorgos Keramidas     "  PID %-*.*s "   "PRI NICE   SIZE    RES STATE    TIME %6s COMMAND";
115511d9c65SJoerg Wunsch 
11694154ff8SPeter Wemm #define up_Proc_format \
117de916c8bSBruce Evans     "%5d %-*.*s %s%3d %4s%7s %6s %-6.6s%.0d%7s %5.2f%% %.*s"
118511d9c65SJoerg Wunsch 
119511d9c65SJoerg Wunsch 
120511d9c65SJoerg Wunsch /* process state names for the "STATE" column of the display */
121511d9c65SJoerg Wunsch /* the extra nulls in the string "run" are for adding a slash and
122511d9c65SJoerg Wunsch    the processor number when needed */
123511d9c65SJoerg Wunsch 
124789e3877SBruce Evans char *state_abbrev[] = {
1250d632649SJohn Baldwin 	"", "START", "RUN\0\0\0", "SLEEP", "STOP", "ZOMB", "WAIT", "LOCK"
126511d9c65SJoerg Wunsch };
127511d9c65SJoerg Wunsch 
128511d9c65SJoerg Wunsch 
129511d9c65SJoerg Wunsch static kvm_t *kd;
130511d9c65SJoerg Wunsch 
131511d9c65SJoerg Wunsch /* values that we stash away in _init and use in later routines */
132511d9c65SJoerg Wunsch 
133511d9c65SJoerg Wunsch static double logcpu;
134511d9c65SJoerg Wunsch 
135511d9c65SJoerg Wunsch /* these are retrieved from the kernel in _init */
136511d9c65SJoerg Wunsch 
137511d9c65SJoerg Wunsch static load_avg  ccpu;
138511d9c65SJoerg Wunsch 
13939d513ecSRobert Watson /* these are used in the get_ functions */
140511d9c65SJoerg Wunsch 
14139d513ecSRobert Watson static int lastpid;
142511d9c65SJoerg Wunsch 
143511d9c65SJoerg Wunsch /* these are for calculating cpu state percentages */
144511d9c65SJoerg Wunsch 
145511d9c65SJoerg Wunsch static long cp_time[CPUSTATES];
146511d9c65SJoerg Wunsch static long cp_old[CPUSTATES];
147511d9c65SJoerg Wunsch static long cp_diff[CPUSTATES];
148511d9c65SJoerg Wunsch 
149511d9c65SJoerg Wunsch /* these are for detailing the process states */
150511d9c65SJoerg Wunsch 
1510384fff8SJason Evans int process_states[8];
152511d9c65SJoerg Wunsch char *procstatenames[] = {
153511d9c65SJoerg Wunsch 	"", " starting, ", " running, ", " sleeping, ", " stopped, ",
1540d632649SJohn Baldwin 	" zombie, ", " waiting, ", " lock, ",
155511d9c65SJoerg Wunsch 	NULL
156511d9c65SJoerg Wunsch };
157511d9c65SJoerg Wunsch 
158511d9c65SJoerg Wunsch /* these are for detailing the cpu states */
159511d9c65SJoerg Wunsch 
160511d9c65SJoerg Wunsch int cpu_states[CPUSTATES];
161511d9c65SJoerg Wunsch char *cpustatenames[] = {
162511d9c65SJoerg Wunsch 	"user", "nice", "system", "interrupt", "idle", NULL
163511d9c65SJoerg Wunsch };
164511d9c65SJoerg Wunsch 
165511d9c65SJoerg Wunsch /* these are for detailing the memory statistics */
166511d9c65SJoerg Wunsch 
167511d9c65SJoerg Wunsch int memory_stats[7];
168511d9c65SJoerg Wunsch char *memorynames[] = {
169789e3877SBruce Evans 	"K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ",
170789e3877SBruce Evans 	"K Free", NULL
171511d9c65SJoerg Wunsch };
172511d9c65SJoerg Wunsch 
173511d9c65SJoerg Wunsch int swap_stats[7];
174511d9c65SJoerg Wunsch char *swapnames[] = {
175511d9c65SJoerg Wunsch 	"K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
176511d9c65SJoerg Wunsch 	NULL
177511d9c65SJoerg Wunsch };
178511d9c65SJoerg Wunsch 
179511d9c65SJoerg Wunsch 
180511d9c65SJoerg Wunsch /* these are for keeping track of the proc array */
181511d9c65SJoerg Wunsch 
182511d9c65SJoerg Wunsch static int nproc;
183511d9c65SJoerg Wunsch static int onproc = -1;
184511d9c65SJoerg Wunsch static int pref_len;
185511d9c65SJoerg Wunsch static struct kinfo_proc *pbase;
186511d9c65SJoerg Wunsch static struct kinfo_proc **pref;
187db6bb7fcSAlfred Perlstein static struct kinfo_proc *previous_procs;
188db6bb7fcSAlfred Perlstein static struct kinfo_proc **previous_pref;
189db6bb7fcSAlfred Perlstein static int previous_proc_count = 0;
190db6bb7fcSAlfred Perlstein static int previous_proc_count_max = 0;
191511d9c65SJoerg Wunsch 
1927fe9a86aSAlfred Perlstein /* total number of io operations */
1937fe9a86aSAlfred Perlstein static long total_inblock;
1947fe9a86aSAlfred Perlstein static long total_oublock;
1957fe9a86aSAlfred Perlstein static long total_majflt;
1967fe9a86aSAlfred Perlstein 
197511d9c65SJoerg Wunsch /* these are for getting the memory statistics */
198511d9c65SJoerg Wunsch 
199511d9c65SJoerg Wunsch static int pageshift;		/* log base 2 of the pagesize */
200511d9c65SJoerg Wunsch 
201511d9c65SJoerg Wunsch /* define pagetok in terms of pageshift */
202511d9c65SJoerg Wunsch 
203511d9c65SJoerg Wunsch #define pagetok(size) ((size) << pageshift)
204511d9c65SJoerg Wunsch 
205511d9c65SJoerg Wunsch /* useful externals */
206511d9c65SJoerg Wunsch long percentages();
207511d9c65SJoerg Wunsch 
208f3b2c2d1SWolfram Schneider #ifdef ORDER
20926b2243aSGiorgos Keramidas /*
21032efd263SGiorgos Keramidas  * Sorting orders.  The first element is the default.
21126b2243aSGiorgos Keramidas  */
2125d320d4bSAlfred Perlstein char *ordernames[] = {
21332efd263SGiorgos Keramidas 	"cpu", "size", "res", "time", "pri", "threads",
2145d320d4bSAlfred Perlstein 	"total", "read", "write", "fault", "vcsw", "ivcsw", NULL
21526b2243aSGiorgos Keramidas };
216f3b2c2d1SWolfram Schneider #endif
217f3b2c2d1SWolfram Schneider 
218de916c8bSBruce Evans static int compare_pid(const void *a, const void *b);
219de916c8bSBruce Evans static const char *format_nice(const struct kinfo_proc *pp);
220de916c8bSBruce Evans static void getsysctl(const char *name, void *ptr, size_t len);
221de916c8bSBruce Evans static int swapmode(int *retavail, int *retfree);
222de916c8bSBruce Evans 
223511d9c65SJoerg Wunsch int
224f6a10feaSDag-Erling Smørgrav machine_init(struct statics *statics)
225511d9c65SJoerg Wunsch {
226970636e9SAlfred Perlstein 	int pagesize;
22798e53e5bSAndrew Gallatin 	size_t modelen;
228a2aff8b2SPeter Wemm 	struct passwd *pw;
22994154ff8SPeter Wemm 
23094154ff8SPeter Wemm 	modelen = sizeof(smpmode);
231789e3877SBruce Evans 	if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen,
232789e3877SBruce Evans 	    NULL, 0) != 0 &&
233789e3877SBruce Evans 	    sysctlbyname("kern.smp.active", &smpmode, &modelen,
234789e3877SBruce Evans 	    NULL, 0) != 0) ||
23594154ff8SPeter Wemm 	    modelen != sizeof(smpmode))
23694154ff8SPeter Wemm 		smpmode = 0;
237511d9c65SJoerg Wunsch 
238a2aff8b2SPeter Wemm 	while ((pw = getpwent()) != NULL) {
239a2aff8b2SPeter Wemm 		if (strlen(pw->pw_name) > namelength)
240a2aff8b2SPeter Wemm 			namelength = strlen(pw->pw_name);
241a2aff8b2SPeter Wemm 	}
242c413702aSDavid E. O'Brien 	if (smpmode && namelength > SMPUNAMELEN)
243c413702aSDavid E. O'Brien 		namelength = SMPUNAMELEN;
244c413702aSDavid E. O'Brien 	else if (namelength > UPUNAMELEN)
245c413702aSDavid E. O'Brien 		namelength = UPUNAMELEN;
246a2aff8b2SPeter Wemm 
2474946a00bSDag-Erling Smørgrav 	kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
2484946a00bSDag-Erling Smørgrav 	if (kd == NULL)
2494946a00bSDag-Erling Smørgrav 		return (-1);
250511d9c65SJoerg Wunsch 
25139d513ecSRobert Watson 	GETSYSCTL("kern.ccpu", ccpu);
252511d9c65SJoerg Wunsch 
253511d9c65SJoerg Wunsch 	/* this is used in calculating WCPU -- calculate it ahead of time */
254511d9c65SJoerg Wunsch 	logcpu = log(loaddouble(ccpu));
255511d9c65SJoerg Wunsch 
256511d9c65SJoerg Wunsch 	pbase = NULL;
257511d9c65SJoerg Wunsch 	pref = NULL;
258511d9c65SJoerg Wunsch 	nproc = 0;
259511d9c65SJoerg Wunsch 	onproc = -1;
260789e3877SBruce Evans 
261789e3877SBruce Evans 	/* get the page size and calculate pageshift from it */
262511d9c65SJoerg Wunsch 	pagesize = getpagesize();
263511d9c65SJoerg Wunsch 	pageshift = 0;
2644946a00bSDag-Erling Smørgrav 	while (pagesize > 1) {
265511d9c65SJoerg Wunsch 		pageshift++;
266511d9c65SJoerg Wunsch 		pagesize >>= 1;
267511d9c65SJoerg Wunsch 	}
268511d9c65SJoerg Wunsch 
269511d9c65SJoerg Wunsch 	/* we only need the amount of log(2)1024 for our conversion */
270511d9c65SJoerg Wunsch 	pageshift -= LOG1024;
271511d9c65SJoerg Wunsch 
272511d9c65SJoerg Wunsch 	/* fill in the statics information */
273511d9c65SJoerg Wunsch 	statics->procstate_names = procstatenames;
274511d9c65SJoerg Wunsch 	statics->cpustate_names = cpustatenames;
275511d9c65SJoerg Wunsch 	statics->memory_names = memorynames;
276511d9c65SJoerg Wunsch 	statics->swap_names = swapnames;
277f3b2c2d1SWolfram Schneider #ifdef ORDER
2785d320d4bSAlfred Perlstein 	statics->order_names = ordernames;
279f3b2c2d1SWolfram Schneider #endif
280511d9c65SJoerg Wunsch 
281511d9c65SJoerg Wunsch 	/* all done! */
282511d9c65SJoerg Wunsch 	return (0);
283511d9c65SJoerg Wunsch }
284511d9c65SJoerg Wunsch 
285970636e9SAlfred Perlstein char *
286f6a10feaSDag-Erling Smørgrav format_header(char *uname_field)
287511d9c65SJoerg Wunsch {
288a2aff8b2SPeter Wemm 	static char Header[128];
289db6bb7fcSAlfred Perlstein 	const char *prehead;
290511d9c65SJoerg Wunsch 
291db6bb7fcSAlfred Perlstein 	switch (displaymode) {
292db6bb7fcSAlfred Perlstein 	case DISP_CPU:
29332efd263SGiorgos Keramidas 		/*
29432efd263SGiorgos Keramidas 		 * The logic of picking the right header format seems reverse
29532efd263SGiorgos Keramidas 		 * here because we only want to display a THR column when
29632efd263SGiorgos Keramidas 		 * "thread mode" is off (and threads are not listed as
29732efd263SGiorgos Keramidas 		 * separate lines).
29832efd263SGiorgos Keramidas 		 */
29932efd263SGiorgos Keramidas 		prehead = smpmode ?
30032efd263SGiorgos Keramidas 		    (ps.thread ? smp_header : smp_header_thr) :
30132efd263SGiorgos Keramidas 		    (ps.thread ? up_header : up_header_thr);
302bbf750fbSGiorgos Keramidas 		snprintf(Header, sizeof(Header), prehead,
303bbf750fbSGiorgos Keramidas 		    namelength, namelength, uname_field,
304bbf750fbSGiorgos Keramidas 		    ps.wcpu ? "WCPU" : "CPU");
305db6bb7fcSAlfred Perlstein 		break;
306db6bb7fcSAlfred Perlstein 	case DISP_IO:
307db6bb7fcSAlfred Perlstein 		prehead = io_header;
308db6bb7fcSAlfred Perlstein 		snprintf(Header, sizeof(Header), prehead,
309a2aff8b2SPeter Wemm 		    namelength, namelength, uname_field);
310bbf750fbSGiorgos Keramidas 		break;
311bbf750fbSGiorgos Keramidas 	}
3127f18d5d3SJohn Baldwin 	cmdlengthdelta = strlen(Header) - 7;
313ea9e70bfSDag-Erling Smørgrav 	return (Header);
314511d9c65SJoerg Wunsch }
315511d9c65SJoerg Wunsch 
316511d9c65SJoerg Wunsch static int swappgsin = -1;
317511d9c65SJoerg Wunsch static int swappgsout = -1;
318511d9c65SJoerg Wunsch extern struct timeval timeout;
319511d9c65SJoerg Wunsch 
320511d9c65SJoerg Wunsch void
321f6a10feaSDag-Erling Smørgrav get_system_info(struct system_info *si)
322511d9c65SJoerg Wunsch {
323511d9c65SJoerg Wunsch 	long total;
32498e53e5bSAndrew Gallatin 	struct loadavg sysload;
325a2641311SDavid E. O'Brien 	int mib[2];
326a2641311SDavid E. O'Brien 	struct timeval boottime;
327a2641311SDavid E. O'Brien 	size_t bt_size;
3284946a00bSDag-Erling Smørgrav 	int i;
329511d9c65SJoerg Wunsch 
330511d9c65SJoerg Wunsch 	/* get the cp_time array */
33139d513ecSRobert Watson 	GETSYSCTL("kern.cp_time", cp_time);
33298e53e5bSAndrew Gallatin 	GETSYSCTL("vm.loadavg", sysload);
33339d513ecSRobert Watson 	GETSYSCTL("kern.lastpid", lastpid);
334511d9c65SJoerg Wunsch 
335511d9c65SJoerg Wunsch 	/* convert load averages to doubles */
336511d9c65SJoerg Wunsch 	for (i = 0; i < 3; i++)
3374946a00bSDag-Erling Smørgrav 		si->load_avg[i] = (double)sysload.ldavg[i] / sysload.fscale;
338511d9c65SJoerg Wunsch 
339511d9c65SJoerg Wunsch 	/* convert cp_time counts to percentages */
340511d9c65SJoerg Wunsch 	total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
341511d9c65SJoerg Wunsch 
342511d9c65SJoerg Wunsch 	/* sum memory & swap statistics */
343511d9c65SJoerg Wunsch 	{
344511d9c65SJoerg Wunsch 		static unsigned int swap_delay = 0;
345511d9c65SJoerg Wunsch 		static int swapavail = 0;
346511d9c65SJoerg Wunsch 		static int swapfree = 0;
347511d9c65SJoerg Wunsch 		static int bufspace = 0;
34839d513ecSRobert Watson 		static int nspgsin, nspgsout;
349511d9c65SJoerg Wunsch 
35039d513ecSRobert Watson 		GETSYSCTL("vfs.bufspace", bufspace);
35139d513ecSRobert Watson 		GETSYSCTL("vm.stats.vm.v_active_count", memory_stats[0]);
35239d513ecSRobert Watson 		GETSYSCTL("vm.stats.vm.v_inactive_count", memory_stats[1]);
35339d513ecSRobert Watson 		GETSYSCTL("vm.stats.vm.v_wire_count", memory_stats[2]);
35439d513ecSRobert Watson 		GETSYSCTL("vm.stats.vm.v_cache_count", memory_stats[3]);
35539d513ecSRobert Watson 		GETSYSCTL("vm.stats.vm.v_free_count", memory_stats[5]);
35639d513ecSRobert Watson 		GETSYSCTL("vm.stats.vm.v_swappgsin", nspgsin);
35739d513ecSRobert Watson 		GETSYSCTL("vm.stats.vm.v_swappgsout", nspgsout);
358511d9c65SJoerg Wunsch 		/* convert memory stats to Kbytes */
3596243f7acSThomas Moestl 		memory_stats[0] = pagetok(memory_stats[0]);
3606243f7acSThomas Moestl 		memory_stats[1] = pagetok(memory_stats[1]);
3616243f7acSThomas Moestl 		memory_stats[2] = pagetok(memory_stats[2]);
3626243f7acSThomas Moestl 		memory_stats[3] = pagetok(memory_stats[3]);
363511d9c65SJoerg Wunsch 		memory_stats[4] = bufspace / 1024;
3646243f7acSThomas Moestl 		memory_stats[5] = pagetok(memory_stats[5]);
365511d9c65SJoerg Wunsch 		memory_stats[6] = -1;
366511d9c65SJoerg Wunsch 
367511d9c65SJoerg Wunsch 		/* first interval */
368511d9c65SJoerg Wunsch 		if (swappgsin < 0) {
369511d9c65SJoerg Wunsch 			swap_stats[4] = 0;
370511d9c65SJoerg Wunsch 			swap_stats[5] = 0;
371511d9c65SJoerg Wunsch 		}
372511d9c65SJoerg Wunsch 
373511d9c65SJoerg Wunsch 		/* compute differences between old and new swap statistic */
374511d9c65SJoerg Wunsch 		else {
37539d513ecSRobert Watson 			swap_stats[4] = pagetok(((nspgsin - swappgsin)));
37639d513ecSRobert Watson 			swap_stats[5] = pagetok(((nspgsout - swappgsout)));
377511d9c65SJoerg Wunsch 		}
378511d9c65SJoerg Wunsch 
37939d513ecSRobert Watson 		swappgsin = nspgsin;
38039d513ecSRobert Watson 		swappgsout = nspgsout;
381511d9c65SJoerg Wunsch 
382511d9c65SJoerg Wunsch 		/* call CPU heavy swapmode() only for changes */
383511d9c65SJoerg Wunsch 		if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) {
384511d9c65SJoerg Wunsch 			swap_stats[3] = swapmode(&swapavail, &swapfree);
385511d9c65SJoerg Wunsch 			swap_stats[0] = swapavail;
386511d9c65SJoerg Wunsch 			swap_stats[1] = swapavail - swapfree;
387511d9c65SJoerg Wunsch 			swap_stats[2] = swapfree;
388511d9c65SJoerg Wunsch 		}
389511d9c65SJoerg Wunsch 		swap_delay = 1;
390511d9c65SJoerg Wunsch 		swap_stats[6] = -1;
391511d9c65SJoerg Wunsch 	}
392511d9c65SJoerg Wunsch 
393511d9c65SJoerg Wunsch 	/* set arrays and strings */
394511d9c65SJoerg Wunsch 	si->cpustates = cpu_states;
395511d9c65SJoerg Wunsch 	si->memory = memory_stats;
396511d9c65SJoerg Wunsch 	si->swap = swap_stats;
397511d9c65SJoerg Wunsch 
398511d9c65SJoerg Wunsch 
399511d9c65SJoerg Wunsch 	if (lastpid > 0) {
400511d9c65SJoerg Wunsch 		si->last_pid = lastpid;
401511d9c65SJoerg Wunsch 	} else {
402511d9c65SJoerg Wunsch 		si->last_pid = -1;
403511d9c65SJoerg Wunsch 	}
404a2641311SDavid E. O'Brien 
405a2641311SDavid E. O'Brien 	/*
406a2641311SDavid E. O'Brien 	 * Print how long system has been up.
407a2641311SDavid E. O'Brien 	 * (Found by looking getting "boottime" from the kernel)
408a2641311SDavid E. O'Brien 	 */
409a2641311SDavid E. O'Brien 	mib[0] = CTL_KERN;
410a2641311SDavid E. O'Brien 	mib[1] = KERN_BOOTTIME;
411a2641311SDavid E. O'Brien 	bt_size = sizeof(boottime);
412a2641311SDavid E. O'Brien 	if (sysctl(mib, 2, &boottime, &bt_size, NULL, 0) != -1 &&
413a2641311SDavid E. O'Brien 	    boottime.tv_sec != 0) {
414a2641311SDavid E. O'Brien 		si->boottime = boottime;
415a2641311SDavid E. O'Brien 	} else {
416a2641311SDavid E. O'Brien 		si->boottime.tv_sec = -1;
417a2641311SDavid E. O'Brien 	}
418511d9c65SJoerg Wunsch }
419511d9c65SJoerg Wunsch 
42098c151d6SAlfred Perlstein #define NOPROC	((void *)-1)
42198c151d6SAlfred Perlstein 
422dcd6f4bdSAlfred Perlstein /*
423dcd6f4bdSAlfred Perlstein  * We need to compare data from the old process entry with the new
424dcd6f4bdSAlfred Perlstein  * process entry.
425dcd6f4bdSAlfred Perlstein  * To facilitate doing this quickly we stash a pointer in the kinfo_proc
426dcd6f4bdSAlfred Perlstein  * structure to cache the mapping.  We also use a negative cache pointer
427dcd6f4bdSAlfred Perlstein  * of NOPROC to avoid duplicate lookups.
428dcd6f4bdSAlfred Perlstein  * XXX: this could be done when the actual processes are fetched, we do
429dcd6f4bdSAlfred Perlstein  * it here out of laziness.
430dcd6f4bdSAlfred Perlstein  */
431db6bb7fcSAlfred Perlstein const struct kinfo_proc *
432db6bb7fcSAlfred Perlstein get_old_proc(struct kinfo_proc *pp)
433db6bb7fcSAlfred Perlstein {
434db6bb7fcSAlfred Perlstein 	struct kinfo_proc **oldpp, *oldp;
435db6bb7fcSAlfred Perlstein 
436dcd6f4bdSAlfred Perlstein 	/*
437dcd6f4bdSAlfred Perlstein 	 * If this is the first fetch of the kinfo_procs then we don't have
438dcd6f4bdSAlfred Perlstein 	 * any previous entries.
439dcd6f4bdSAlfred Perlstein 	 */
440db6bb7fcSAlfred Perlstein 	if (previous_proc_count == 0)
441db6bb7fcSAlfred Perlstein 		return (NULL);
442dcd6f4bdSAlfred Perlstein 	/* negative cache? */
44398c151d6SAlfred Perlstein 	if (pp->ki_udata == NOPROC)
44498c151d6SAlfred Perlstein 		return (NULL);
445dcd6f4bdSAlfred Perlstein 	/* cached? */
44698c151d6SAlfred Perlstein 	if (pp->ki_udata != NULL)
44798c151d6SAlfred Perlstein 		return (pp->ki_udata);
448dcd6f4bdSAlfred Perlstein 	/*
449dcd6f4bdSAlfred Perlstein 	 * Not cached,
450dcd6f4bdSAlfred Perlstein 	 * 1) look up based on pid.
451dcd6f4bdSAlfred Perlstein 	 * 2) compare process start.
452dcd6f4bdSAlfred Perlstein 	 * If we fail here, then setup a negative cache entry, otherwise
453dcd6f4bdSAlfred Perlstein 	 * cache it.
454dcd6f4bdSAlfred Perlstein 	 */
455db6bb7fcSAlfred Perlstein 	oldpp = bsearch(&pp, previous_pref, previous_proc_count,
4564946a00bSDag-Erling Smørgrav 	    sizeof(*previous_pref), compare_pid);
45798c151d6SAlfred Perlstein 	if (oldpp == NULL) {
45898c151d6SAlfred Perlstein 		pp->ki_udata = NOPROC;
459db6bb7fcSAlfred Perlstein 		return (NULL);
46098c151d6SAlfred Perlstein 	}
461db6bb7fcSAlfred Perlstein 	oldp = *oldpp;
46298c151d6SAlfred Perlstein 	if (bcmp(&oldp->ki_start, &pp->ki_start, sizeof(pp->ki_start)) != 0) {
46398c151d6SAlfred Perlstein 		pp->ki_udata = NOPROC;
464db6bb7fcSAlfred Perlstein 		return (NULL);
46598c151d6SAlfred Perlstein 	}
46698c151d6SAlfred Perlstein 	pp->ki_udata = oldp;
467db6bb7fcSAlfred Perlstein 	return (oldp);
468db6bb7fcSAlfred Perlstein }
469db6bb7fcSAlfred Perlstein 
470dcd6f4bdSAlfred Perlstein /*
471dcd6f4bdSAlfred Perlstein  * Return the total amount of IO done in blocks in/out and faults.
472dcd6f4bdSAlfred Perlstein  * store the values individually in the pointers passed in.
473dcd6f4bdSAlfred Perlstein  */
474db6bb7fcSAlfred Perlstein long
475789e3877SBruce Evans get_io_stats(struct kinfo_proc *pp, long *inp, long *oup, long *flp,
476789e3877SBruce Evans     long *vcsw, long *ivcsw)
477db6bb7fcSAlfred Perlstein {
478db6bb7fcSAlfred Perlstein 	const struct kinfo_proc *oldp;
479db6bb7fcSAlfred Perlstein 	static struct kinfo_proc dummy;
480db6bb7fcSAlfred Perlstein 	long ret;
481db6bb7fcSAlfred Perlstein 
482db6bb7fcSAlfred Perlstein 	oldp = get_old_proc(pp);
483db6bb7fcSAlfred Perlstein 	if (oldp == NULL) {
484db6bb7fcSAlfred Perlstein 		bzero(&dummy, sizeof(dummy));
485db6bb7fcSAlfred Perlstein 		oldp = &dummy;
486db6bb7fcSAlfred Perlstein 	}
4877fe9a86aSAlfred Perlstein 	*inp = RU(pp)->ru_inblock - RU(oldp)->ru_inblock;
4887fe9a86aSAlfred Perlstein 	*oup = RU(pp)->ru_oublock - RU(oldp)->ru_oublock;
4897fe9a86aSAlfred Perlstein 	*flp = RU(pp)->ru_majflt - RU(oldp)->ru_majflt;
4905d320d4bSAlfred Perlstein 	*vcsw = RU(pp)->ru_nvcsw - RU(oldp)->ru_nvcsw;
4915d320d4bSAlfred Perlstein 	*ivcsw = RU(pp)->ru_nivcsw - RU(oldp)->ru_nivcsw;
492db6bb7fcSAlfred Perlstein 	ret =
493db6bb7fcSAlfred Perlstein 	    (RU(pp)->ru_inblock - RU(oldp)->ru_inblock) +
494db6bb7fcSAlfred Perlstein 	    (RU(pp)->ru_oublock - RU(oldp)->ru_oublock) +
495db6bb7fcSAlfred Perlstein 	    (RU(pp)->ru_majflt - RU(oldp)->ru_majflt);
496db6bb7fcSAlfred Perlstein 	return (ret);
497db6bb7fcSAlfred Perlstein }
498db6bb7fcSAlfred Perlstein 
499dcd6f4bdSAlfred Perlstein /*
500dcd6f4bdSAlfred Perlstein  * Return the total number of block in/out and faults by a process.
501dcd6f4bdSAlfred Perlstein  */
5027fe9a86aSAlfred Perlstein long
5037fe9a86aSAlfred Perlstein get_io_total(struct kinfo_proc *pp)
5047fe9a86aSAlfred Perlstein {
5057fe9a86aSAlfred Perlstein 	long dummy;
5067fe9a86aSAlfred Perlstein 
5075d320d4bSAlfred Perlstein 	return (get_io_stats(pp, &dummy, &dummy, &dummy, &dummy, &dummy));
5087fe9a86aSAlfred Perlstein }
5097fe9a86aSAlfred Perlstein 
510511d9c65SJoerg Wunsch static struct handle handle;
511511d9c65SJoerg Wunsch 
512970636e9SAlfred Perlstein caddr_t
513f6a10feaSDag-Erling Smørgrav get_process_info(struct system_info *si, struct process_select *sel,
5144946a00bSDag-Erling Smørgrav     int (*compare)(const void *, const void *))
515511d9c65SJoerg Wunsch {
516970636e9SAlfred Perlstein 	int i;
517970636e9SAlfred Perlstein 	int total_procs;
5187fe9a86aSAlfred Perlstein 	long p_io;
5195d320d4bSAlfred Perlstein 	long p_inblock, p_oublock, p_majflt, p_vcsw, p_ivcsw;
520970636e9SAlfred Perlstein 	int active_procs;
521970636e9SAlfred Perlstein 	struct kinfo_proc **prefp;
522970636e9SAlfred Perlstein 	struct kinfo_proc *pp;
523cac4b14cSBrian Feldman 	struct kinfo_proc *prev_pp = NULL;
524511d9c65SJoerg Wunsch 
525511d9c65SJoerg Wunsch 	/* these are copied out of sel for speed */
526511d9c65SJoerg Wunsch 	int show_idle;
527e7cdb972SDag-Erling Smørgrav 	int show_self;
528511d9c65SJoerg Wunsch 	int show_system;
529511d9c65SJoerg Wunsch 	int show_uid;
530511d9c65SJoerg Wunsch 	int show_command;
531511d9c65SJoerg Wunsch 
532db6bb7fcSAlfred Perlstein 	/*
533db6bb7fcSAlfred Perlstein 	 * Save the previous process info.
534db6bb7fcSAlfred Perlstein 	 */
535db6bb7fcSAlfred Perlstein 	if (previous_proc_count_max < nproc) {
536db6bb7fcSAlfred Perlstein 		free(previous_procs);
5374946a00bSDag-Erling Smørgrav 		previous_procs = malloc(nproc * sizeof(*previous_procs));
538db6bb7fcSAlfred Perlstein 		free(previous_pref);
5394946a00bSDag-Erling Smørgrav 		previous_pref = malloc(nproc * sizeof(*previous_pref));
540db6bb7fcSAlfred Perlstein 		if (previous_procs == NULL || previous_pref == NULL) {
541db6bb7fcSAlfred Perlstein 			(void) fprintf(stderr, "top: Out of memory.\n");
542db6bb7fcSAlfred Perlstein 			quit(23);
543db6bb7fcSAlfred Perlstein 		}
544db6bb7fcSAlfred Perlstein 		previous_proc_count_max = nproc;
545db6bb7fcSAlfred Perlstein 	}
546db6bb7fcSAlfred Perlstein 	if (nproc) {
547db6bb7fcSAlfred Perlstein 		for (i = 0; i < nproc; i++)
548db6bb7fcSAlfred Perlstein 			previous_pref[i] = &previous_procs[i];
5494946a00bSDag-Erling Smørgrav 		bcopy(pbase, previous_procs, nproc * sizeof(*previous_procs));
550789e3877SBruce Evans 		qsort(previous_pref, nproc, sizeof(*previous_pref),
551789e3877SBruce Evans 		    compare_pid);
552db6bb7fcSAlfred Perlstein 	}
553db6bb7fcSAlfred Perlstein 	previous_proc_count = nproc;
554db6bb7fcSAlfred Perlstein 
555cac4b14cSBrian Feldman 	pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
556511d9c65SJoerg Wunsch 	if (nproc > onproc)
5574946a00bSDag-Erling Smørgrav 		pref = realloc(pref, sizeof(*pref) * (onproc = nproc));
558511d9c65SJoerg Wunsch 	if (pref == NULL || pbase == NULL) {
559511d9c65SJoerg Wunsch 		(void) fprintf(stderr, "top: Out of memory.\n");
560511d9c65SJoerg Wunsch 		quit(23);
561511d9c65SJoerg Wunsch 	}
562511d9c65SJoerg Wunsch 	/* get a pointer to the states summary array */
563511d9c65SJoerg Wunsch 	si->procstates = process_states;
564511d9c65SJoerg Wunsch 
565511d9c65SJoerg Wunsch 	/* set up flags which define what we are going to select */
566511d9c65SJoerg Wunsch 	show_idle = sel->idle;
5679b30d697SDag-Erling Smørgrav 	show_self = sel->self == -1;
568511d9c65SJoerg Wunsch 	show_system = sel->system;
569511d9c65SJoerg Wunsch 	show_uid = sel->uid != -1;
570511d9c65SJoerg Wunsch 	show_command = sel->command != NULL;
571511d9c65SJoerg Wunsch 
572511d9c65SJoerg Wunsch 	/* count up process states and get pointers to interesting procs */
573511d9c65SJoerg Wunsch 	total_procs = 0;
574511d9c65SJoerg Wunsch 	active_procs = 0;
5757fe9a86aSAlfred Perlstein 	total_inblock = 0;
5767fe9a86aSAlfred Perlstein 	total_oublock = 0;
5777fe9a86aSAlfred Perlstein 	total_majflt = 0;
578511d9c65SJoerg Wunsch 	memset((char *)process_states, 0, sizeof(process_states));
579511d9c65SJoerg Wunsch 	prefp = pref;
5804946a00bSDag-Erling Smørgrav 	for (pp = pbase, i = 0; i < nproc; pp++, i++) {
5817fe9a86aSAlfred Perlstein 
582d62a717dSDag-Erling Smørgrav 		if (pp->ki_stat == 0)
583d62a717dSDag-Erling Smørgrav 			/* not in use */
584d62a717dSDag-Erling Smørgrav 			continue;
585d62a717dSDag-Erling Smørgrav 
586d62a717dSDag-Erling Smørgrav 		if (!show_self && pp->ki_pid == sel->self)
587d62a717dSDag-Erling Smørgrav 			/* skip self */
588d62a717dSDag-Erling Smørgrav 			continue;
589d62a717dSDag-Erling Smørgrav 
590d62a717dSDag-Erling Smørgrav 		if (!show_system && (pp->ki_flag & P_SYSTEM))
591d62a717dSDag-Erling Smørgrav 			/* skip system process */
592d62a717dSDag-Erling Smørgrav 			continue;
593d62a717dSDag-Erling Smørgrav 
594789e3877SBruce Evans 		p_io = get_io_stats(pp, &p_inblock, &p_oublock, &p_majflt,
595789e3877SBruce Evans 		    &p_vcsw, &p_ivcsw);
5967fe9a86aSAlfred Perlstein 		total_inblock += p_inblock;
5977fe9a86aSAlfred Perlstein 		total_oublock += p_oublock;
5987fe9a86aSAlfred Perlstein 		total_majflt += p_majflt;
599511d9c65SJoerg Wunsch 		total_procs++;
6004946a00bSDag-Erling Smørgrav 		process_states[pp->ki_stat]++;
601d62a717dSDag-Erling Smørgrav 
602d62a717dSDag-Erling Smørgrav 		if (pp->ki_stat == SZOMB)
603d62a717dSDag-Erling Smørgrav 			/* skip zombies */
604d62a717dSDag-Erling Smørgrav 			continue;
605d62a717dSDag-Erling Smørgrav 
606d62a717dSDag-Erling Smørgrav 		if (displaymode == DISP_CPU && !show_idle &&
607d1b76f3fSStefan Eßer 		    (pp->ki_pctcpu == 0 ||
608d1b76f3fSStefan Eßer 		     pp->ki_stat == SSTOP || pp->ki_stat == SIDL))
609d62a717dSDag-Erling Smørgrav 			/* skip idle or non-running processes */
610d62a717dSDag-Erling Smørgrav 			continue;
611d62a717dSDag-Erling Smørgrav 
612d62a717dSDag-Erling Smørgrav 		if (displaymode == DISP_IO && !show_idle && p_io == 0)
613d62a717dSDag-Erling Smørgrav 			/* skip processes that aren't doing I/O */
614d62a717dSDag-Erling Smørgrav 			continue;
615d62a717dSDag-Erling Smørgrav 
616d62a717dSDag-Erling Smørgrav 		if (show_uid && pp->ki_ruid != (uid_t)sel->uid)
617789e3877SBruce Evans 			/* skip proc. that don't belong to the selected UID */
618d62a717dSDag-Erling Smørgrav 			continue;
619d62a717dSDag-Erling Smørgrav 
620cac4b14cSBrian Feldman 		/*
621cac4b14cSBrian Feldman 		 * When not showing threads, take the first thread
622cac4b14cSBrian Feldman 		 * for output and add the fields that we can from
623cac4b14cSBrian Feldman 		 * the rest of the process's threads rather than
624cac4b14cSBrian Feldman 		 * using the system's mostly-broken KERN_PROC_PROC.
625cac4b14cSBrian Feldman 		 */
6264946a00bSDag-Erling Smørgrav 		if (sel->thread || prev_pp == NULL ||
6274946a00bSDag-Erling Smørgrav 		    prev_pp->ki_pid != pp->ki_pid) {
628511d9c65SJoerg Wunsch 			*prefp++ = pp;
629511d9c65SJoerg Wunsch 			active_procs++;
630cac4b14cSBrian Feldman 			prev_pp = pp;
631cac4b14cSBrian Feldman 		} else {
632cac4b14cSBrian Feldman 			prev_pp->ki_pctcpu += pp->ki_pctcpu;
633cac4b14cSBrian Feldman 		}
634511d9c65SJoerg Wunsch 	}
635511d9c65SJoerg Wunsch 
636511d9c65SJoerg Wunsch 	/* if requested, sort the "interesting" processes */
637511d9c65SJoerg Wunsch 	if (compare != NULL)
6384946a00bSDag-Erling Smørgrav 		qsort(pref, active_procs, sizeof(*pref), compare);
639511d9c65SJoerg Wunsch 
640511d9c65SJoerg Wunsch 	/* remember active and total counts */
641511d9c65SJoerg Wunsch 	si->p_total = total_procs;
642511d9c65SJoerg Wunsch 	si->p_active = pref_len = active_procs;
643511d9c65SJoerg Wunsch 
644511d9c65SJoerg Wunsch 	/* pass back a handle */
645511d9c65SJoerg Wunsch 	handle.next_proc = pref;
646511d9c65SJoerg Wunsch 	handle.remaining = active_procs;
647511d9c65SJoerg Wunsch 	return ((caddr_t)&handle);
648511d9c65SJoerg Wunsch }
649511d9c65SJoerg Wunsch 
6504946a00bSDag-Erling Smørgrav static char fmt[128];	/* static area where result is built */
651511d9c65SJoerg Wunsch 
652970636e9SAlfred Perlstein char *
653faac60c8SStanislav Sedov format_next_process(caddr_t handle, char *(*get_userid)(int), int flags)
654511d9c65SJoerg Wunsch {
655970636e9SAlfred Perlstein 	struct kinfo_proc *pp;
656db6bb7fcSAlfred Perlstein 	const struct kinfo_proc *oldp;
657970636e9SAlfred Perlstein 	long cputime;
658970636e9SAlfred Perlstein 	double pct;
659511d9c65SJoerg Wunsch 	struct handle *hp;
660511d9c65SJoerg Wunsch 	char status[16];
6611005b436SBill Fenner 	int state;
662db6bb7fcSAlfred Perlstein 	struct rusage ru, *rup;
6637fe9a86aSAlfred Perlstein 	long p_tot, s_tot;
6645970af4cSGiorgos Keramidas 	char *proc_fmt, thr_buf[6];
665faac60c8SStanislav Sedov 	char *cmdbuf = NULL;
666faac60c8SStanislav Sedov 	char **args;
667511d9c65SJoerg Wunsch 
668511d9c65SJoerg Wunsch 	/* find and remember the next proc structure */
669511d9c65SJoerg Wunsch 	hp = (struct handle *)handle;
670511d9c65SJoerg Wunsch 	pp = *(hp->next_proc++);
671511d9c65SJoerg Wunsch 	hp->remaining--;
672511d9c65SJoerg Wunsch 
673a8224b82SBruce Evans 	/* get the process's command name */
6740821b7caSJohn Baldwin 	if ((pp->ki_sflag & PS_INMEM) == 0) {
675511d9c65SJoerg Wunsch 		/*
676511d9c65SJoerg Wunsch 		 * Print swapped processes as <pname>
677511d9c65SJoerg Wunsch 		 */
678789e3877SBruce Evans 		size_t len;
679789e3877SBruce Evans 
680789e3877SBruce Evans 		len = strlen(pp->ki_comm);
6814946a00bSDag-Erling Smørgrav 		if (len > sizeof(pp->ki_comm) - 3)
6824946a00bSDag-Erling Smørgrav 			len = sizeof(pp->ki_comm) - 3;
6834946a00bSDag-Erling Smørgrav 		memmove(pp->ki_comm + 1, pp->ki_comm, len);
6844946a00bSDag-Erling Smørgrav 		pp->ki_comm[0] = '<';
6854946a00bSDag-Erling Smørgrav 		pp->ki_comm[len + 1] = '>';
6864946a00bSDag-Erling Smørgrav 		pp->ki_comm[len + 2] = '\0';
687511d9c65SJoerg Wunsch 	}
688511d9c65SJoerg Wunsch 
689a8224b82SBruce Evans 	/*
690a8224b82SBruce Evans 	 * Convert the process's runtime from microseconds to seconds.  This
691a8224b82SBruce Evans 	 * time includes the interrupt time although that is not wanted here.
692a8224b82SBruce Evans 	 * ps(1) is similarly sloppy.
693a8224b82SBruce Evans 	 */
6941f7d2501SKirk McKusick 	cputime = (pp->ki_runtime + 500000) / 1000000;
695511d9c65SJoerg Wunsch 
696511d9c65SJoerg Wunsch 	/* calculate the base for cpu percentages */
6971f7d2501SKirk McKusick 	pct = pctdouble(pp->ki_pctcpu);
698511d9c65SJoerg Wunsch 
699511d9c65SJoerg Wunsch 	/* generate "STATE" field */
7001f7d2501SKirk McKusick 	switch (state = pp->ki_stat) {
701511d9c65SJoerg Wunsch 	case SRUN:
7021f7d2501SKirk McKusick 		if (smpmode && pp->ki_oncpu != 0xff)
7031f7d2501SKirk McKusick 			sprintf(status, "CPU%d", pp->ki_oncpu);
704511d9c65SJoerg Wunsch 		else
705511d9c65SJoerg Wunsch 			strcpy(status, "RUN");
706511d9c65SJoerg Wunsch 		break;
7070d632649SJohn Baldwin 	case SLOCK:
7080d632649SJohn Baldwin 		if (pp->ki_kiflag & KI_LOCKBLOCK) {
7090d632649SJohn Baldwin 			sprintf(status, "*%.6s", pp->ki_lockname);
710089f9b7eSJohn Baldwin 			break;
711089f9b7eSJohn Baldwin 		}
712089f9b7eSJohn Baldwin 		/* fall through */
713511d9c65SJoerg Wunsch 	case SSLEEP:
7141f7d2501SKirk McKusick 		if (pp->ki_wmesg != NULL) {
7151f7d2501SKirk McKusick 			sprintf(status, "%.6s", pp->ki_wmesg);
716511d9c65SJoerg Wunsch 			break;
717511d9c65SJoerg Wunsch 		}
71893b0017fSPhilippe Charnier 		/* FALLTHROUGH */
719511d9c65SJoerg Wunsch 	default:
7201005b436SBill Fenner 
7211005b436SBill Fenner 		if (state >= 0 &&
7221005b436SBill Fenner 		    state < sizeof(state_abbrev) / sizeof(*state_abbrev))
7234946a00bSDag-Erling Smørgrav 			sprintf(status, "%.6s", state_abbrev[state]);
7241005b436SBill Fenner 		else
7251005b436SBill Fenner 			sprintf(status, "?%5d", state);
726511d9c65SJoerg Wunsch 		break;
727511d9c65SJoerg Wunsch 	}
728511d9c65SJoerg Wunsch 
729faac60c8SStanislav Sedov 	cmdbuf = (char *)malloc(cmdlengthdelta + 1);
730faac60c8SStanislav Sedov 	if (cmdbuf == NULL) {
731faac60c8SStanislav Sedov 		warn("malloc(%d)", cmdlengthdelta + 1);
732faac60c8SStanislav Sedov 		return NULL;
733faac60c8SStanislav Sedov 	}
734faac60c8SStanislav Sedov 
735faac60c8SStanislav Sedov 	if (!(flags & FMT_SHOWARGS)) {
736faac60c8SStanislav Sedov 		snprintf(cmdbuf, cmdlengthdelta, "%s", pp->ki_comm);
737faac60c8SStanislav Sedov 	}
738faac60c8SStanislav Sedov 	else if (pp->ki_args == NULL ||
739faac60c8SStanislav Sedov 	    (args = kvm_getargv(kd, pp, cmdlengthdelta)) == NULL || !(*args))
740faac60c8SStanislav Sedov 		snprintf(cmdbuf, cmdlengthdelta, "[%s]", pp->ki_comm);
741faac60c8SStanislav Sedov 	else {
742faac60c8SStanislav Sedov 		char *src, *dst, *argbuf;
743faac60c8SStanislav Sedov 		char *cmd;
744faac60c8SStanislav Sedov 		size_t argbuflen;
745faac60c8SStanislav Sedov 		size_t len;
746faac60c8SStanislav Sedov 
747faac60c8SStanislav Sedov 		argbuflen = cmdlengthdelta * 4;
748faac60c8SStanislav Sedov 		argbuf = (char *)malloc(argbuflen + 1);
749faac60c8SStanislav Sedov 		if (argbuf == NULL) {
750faac60c8SStanislav Sedov 			warn("malloc(%d)", argbuflen + 1);
751faac60c8SStanislav Sedov 			free(cmdbuf);
752faac60c8SStanislav Sedov 			return NULL;
753faac60c8SStanislav Sedov 		}
754faac60c8SStanislav Sedov 
755faac60c8SStanislav Sedov 		dst = argbuf;
756faac60c8SStanislav Sedov 
757faac60c8SStanislav Sedov 		/* Extract cmd name from argv */
758faac60c8SStanislav Sedov 		cmd = strrchr(*args, '/');
759faac60c8SStanislav Sedov 		if (cmd == NULL)
760faac60c8SStanislav Sedov 			cmd = *args;
761faac60c8SStanislav Sedov 		else
762faac60c8SStanislav Sedov 			cmd++;
763faac60c8SStanislav Sedov 
764faac60c8SStanislav Sedov 		for (; (src = *args++) != NULL; ) {
765faac60c8SStanislav Sedov 			if (*src == '\0')
766faac60c8SStanislav Sedov 				continue;
767faac60c8SStanislav Sedov 			len = (argbuflen - (dst - argbuf) - 1) / 4;
768faac60c8SStanislav Sedov 			strvisx(dst, src, strlen(src) < len ? strlen(src) : len,
769faac60c8SStanislav Sedov 			    VIS_NL | VIS_CSTYLE);
770faac60c8SStanislav Sedov 			while (*dst != '\0')
771faac60c8SStanislav Sedov 				dst++;
772faac60c8SStanislav Sedov 			if ((argbuflen - (dst - argbuf) - 1) / 4 > 0)
773faac60c8SStanislav Sedov 				*dst++ = ' '; /* add delimiting space */
774faac60c8SStanislav Sedov 		}
775faac60c8SStanislav Sedov 		if (dst != argbuf && dst[-1] == ' ')
776faac60c8SStanislav Sedov 			dst--;
777faac60c8SStanislav Sedov 		*dst = '\0';
778faac60c8SStanislav Sedov 
779faac60c8SStanislav Sedov 		if (strcmp(cmd, pp->ki_comm) != 0 )
780faac60c8SStanislav Sedov 			snprintf(cmdbuf, cmdlengthdelta, "%s (%s)",argbuf, \
781faac60c8SStanislav Sedov 				 pp->ki_comm);
782faac60c8SStanislav Sedov 		else
783faac60c8SStanislav Sedov 			strlcpy(cmdbuf, argbuf, cmdlengthdelta);
784faac60c8SStanislav Sedov 
785faac60c8SStanislav Sedov 		free(argbuf);
786faac60c8SStanislav Sedov 	}
787faac60c8SStanislav Sedov 
788db6bb7fcSAlfred Perlstein 	if (displaymode == DISP_IO) {
789db6bb7fcSAlfred Perlstein 		oldp = get_old_proc(pp);
790db6bb7fcSAlfred Perlstein 		if (oldp != NULL) {
791789e3877SBruce Evans 			ru.ru_inblock = RU(pp)->ru_inblock -
792789e3877SBruce Evans 			    RU(oldp)->ru_inblock;
793789e3877SBruce Evans 			ru.ru_oublock = RU(pp)->ru_oublock -
794789e3877SBruce Evans 			    RU(oldp)->ru_oublock;
795db6bb7fcSAlfred Perlstein 			ru.ru_majflt = RU(pp)->ru_majflt - RU(oldp)->ru_majflt;
7965d320d4bSAlfred Perlstein 			ru.ru_nvcsw = RU(pp)->ru_nvcsw - RU(oldp)->ru_nvcsw;
7975d320d4bSAlfred Perlstein 			ru.ru_nivcsw = RU(pp)->ru_nivcsw - RU(oldp)->ru_nivcsw;
798db6bb7fcSAlfred Perlstein 			rup = &ru;
799db6bb7fcSAlfred Perlstein 		} else {
800db6bb7fcSAlfred Perlstein 			rup = RU(pp);
801db6bb7fcSAlfred Perlstein 		}
8027fe9a86aSAlfred Perlstein 		p_tot = rup->ru_inblock + rup->ru_oublock + rup->ru_majflt;
8037fe9a86aSAlfred Perlstein 		s_tot = total_inblock + total_oublock + total_majflt;
804db6bb7fcSAlfred Perlstein 
805db6bb7fcSAlfred Perlstein 		sprintf(fmt, io_Proc_format,
806db6bb7fcSAlfred Perlstein 		    pp->ki_pid,
807789e3877SBruce Evans 		    namelength, namelength, (*get_userid)(pp->ki_ruid),
8085d320d4bSAlfred Perlstein 		    rup->ru_nvcsw,
8095d320d4bSAlfred Perlstein 		    rup->ru_nivcsw,
8104946a00bSDag-Erling Smørgrav 		    rup->ru_inblock,
8114946a00bSDag-Erling Smørgrav 		    rup->ru_oublock,
8124946a00bSDag-Erling Smørgrav 		    rup->ru_majflt,
8134946a00bSDag-Erling Smørgrav 		    p_tot,
8144946a00bSDag-Erling Smørgrav 		    s_tot == 0 ? 0.0 : (p_tot * 100.0 / s_tot),
815db6bb7fcSAlfred Perlstein 		    screen_width > cmdlengthdelta ?
816db6bb7fcSAlfred Perlstein 		    screen_width - cmdlengthdelta : 0,
817faac60c8SStanislav Sedov 		    printable(cmdbuf));
818faac60c8SStanislav Sedov 
819faac60c8SStanislav Sedov 		free(cmdbuf);
820faac60c8SStanislav Sedov 
821db6bb7fcSAlfred Perlstein 		return (fmt);
822db6bb7fcSAlfred Perlstein 	}
82332efd263SGiorgos Keramidas 
824511d9c65SJoerg Wunsch 	/* format this entry */
82532efd263SGiorgos Keramidas 	proc_fmt = smpmode ? smp_Proc_format : up_Proc_format;
82632efd263SGiorgos Keramidas 	if (ps.thread != 0)
82732efd263SGiorgos Keramidas 		thr_buf[0] = '\0';
82832efd263SGiorgos Keramidas 	else
82932efd263SGiorgos Keramidas 		snprintf(thr_buf, sizeof(thr_buf), "%*d ",
83032efd263SGiorgos Keramidas 		    sizeof(thr_buf) - 2, pp->ki_numthreads);
83132efd263SGiorgos Keramidas 
83232efd263SGiorgos Keramidas 	sprintf(fmt, proc_fmt,
8331f7d2501SKirk McKusick 	    pp->ki_pid,
834789e3877SBruce Evans 	    namelength, namelength, (*get_userid)(pp->ki_ruid),
83532efd263SGiorgos Keramidas 	    thr_buf,
8364c85452bSJake Burkholder 	    pp->ki_pri.pri_level - PZERO,
837de916c8bSBruce Evans 	    format_nice(pp),
8388fbaa58aSDmitrij Tejblum 	    format_k2(PROCSIZE(pp)),
8391f7d2501SKirk McKusick 	    format_k2(pagetok(pp->ki_rssize)),
840511d9c65SJoerg Wunsch 	    status,
8411f7d2501SKirk McKusick 	    smpmode ? pp->ki_lastcpu : 0,
842511d9c65SJoerg Wunsch 	    format_time(cputime),
843bbf750fbSGiorgos Keramidas 	    ps.wcpu ? 100.0 * weighted_cpu(pct, pp) : 100.0 * pct,
844789e3877SBruce Evans 	    screen_width > cmdlengthdelta ? screen_width - cmdlengthdelta : 0,
845faac60c8SStanislav Sedov 	    printable(cmdbuf));
846faac60c8SStanislav Sedov 
847faac60c8SStanislav Sedov 	free(cmdbuf);
848511d9c65SJoerg Wunsch 
849511d9c65SJoerg Wunsch 	/* return the result */
850511d9c65SJoerg Wunsch 	return (fmt);
851511d9c65SJoerg Wunsch }
852511d9c65SJoerg Wunsch 
853970636e9SAlfred Perlstein static void
854de916c8bSBruce Evans getsysctl(const char *name, void *ptr, size_t len)
855511d9c65SJoerg Wunsch {
85698e53e5bSAndrew Gallatin 	size_t nlen = len;
857970636e9SAlfred Perlstein 
85839d513ecSRobert Watson 	if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
85939d513ecSRobert Watson 		fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name,
86039d513ecSRobert Watson 		    strerror(errno));
861511d9c65SJoerg Wunsch 		quit(23);
862511d9c65SJoerg Wunsch 	}
86339d513ecSRobert Watson 	if (nlen != len) {
864789e3877SBruce Evans 		fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n",
865789e3877SBruce Evans 		    name, (unsigned long)len, (unsigned long)nlen);
86639d513ecSRobert Watson 		quit(23);
867511d9c65SJoerg Wunsch 	}
868511d9c65SJoerg Wunsch }
869511d9c65SJoerg Wunsch 
8708dbbff5bSBruce Evans static const char *
8718dbbff5bSBruce Evans format_nice(const struct kinfo_proc *pp)
872de916c8bSBruce Evans {
8738dbbff5bSBruce Evans 	const char *fifo, *kthread;
8748dbbff5bSBruce Evans 	int rtpri;
8758dbbff5bSBruce Evans 	static char nicebuf[4 + 1];
876de916c8bSBruce Evans 
8778dbbff5bSBruce Evans 	fifo = PRI_NEED_RR(pp->ki_pri.pri_class) ? "" : "F";
8788dbbff5bSBruce Evans 	kthread = (pp->ki_flag & P_KTHREAD) ? "k" : "";
8798dbbff5bSBruce Evans 	switch (PRI_BASE(pp->ki_pri.pri_class)) {
8808dbbff5bSBruce Evans 	case PRI_ITHD:
8818dbbff5bSBruce Evans 		return ("-");
8828dbbff5bSBruce Evans 	case PRI_REALTIME:
8838dbbff5bSBruce Evans 		rtpri = pp->ki_pri.pri_level - PRI_MIN_REALTIME;
8848dbbff5bSBruce Evans 		snprintf(nicebuf, sizeof(nicebuf), "%sr%d%s",
8858dbbff5bSBruce Evans 		    kthread, rtpri, fifo);
8868dbbff5bSBruce Evans 		break;
8878dbbff5bSBruce Evans 	case PRI_TIMESHARE:
8888dbbff5bSBruce Evans 		if (pp->ki_flag & P_KTHREAD)
8898dbbff5bSBruce Evans 			return ("-");
8908dbbff5bSBruce Evans 		snprintf(nicebuf, sizeof(nicebuf), "%d", pp->ki_nice - NZERO);
8918dbbff5bSBruce Evans 		break;
8928dbbff5bSBruce Evans 	case PRI_IDLE:
8938dbbff5bSBruce Evans 		rtpri = pp->ki_pri.pri_level - PRI_MIN_IDLE;
8948dbbff5bSBruce Evans 		snprintf(nicebuf, sizeof(nicebuf), "%si%d%s",
8958dbbff5bSBruce Evans 		    kthread, rtpri, fifo);
8968dbbff5bSBruce Evans 		break;
8978dbbff5bSBruce Evans 	default:
8988dbbff5bSBruce Evans 		return ("?");
8998dbbff5bSBruce Evans 	}
900de916c8bSBruce Evans 	return (nicebuf);
901de916c8bSBruce Evans }
902de916c8bSBruce Evans 
903f3b2c2d1SWolfram Schneider /* comparison routines for qsort */
904511d9c65SJoerg Wunsch 
905de916c8bSBruce Evans static int
906f6a10feaSDag-Erling Smørgrav compare_pid(const void *p1, const void *p2)
907db6bb7fcSAlfred Perlstein {
908db6bb7fcSAlfred Perlstein 	const struct kinfo_proc * const *pp1 = p1;
909db6bb7fcSAlfred Perlstein 	const struct kinfo_proc * const *pp2 = p2;
910db6bb7fcSAlfred Perlstein 
911db6bb7fcSAlfred Perlstein 	if ((*pp2)->ki_pid < 0 || (*pp1)->ki_pid < 0)
912db6bb7fcSAlfred Perlstein 		abort();
913db6bb7fcSAlfred Perlstein 
914db6bb7fcSAlfred Perlstein 	return ((*pp1)->ki_pid - (*pp2)->ki_pid);
915db6bb7fcSAlfred Perlstein }
916db6bb7fcSAlfred Perlstein 
917511d9c65SJoerg Wunsch /*
918511d9c65SJoerg Wunsch  *  proc_compare - comparison function for "qsort"
919511d9c65SJoerg Wunsch  *	Compares the resource consumption of two processes using five
920511d9c65SJoerg Wunsch  *	distinct keys.  The keys (in descending order of importance) are:
921511d9c65SJoerg Wunsch  *	percent cpu, cpu ticks, state, resident set size, total virtual
922511d9c65SJoerg Wunsch  *	memory usage.  The process states are ordered as follows (from least
923511d9c65SJoerg Wunsch  *	to most important):  WAIT, zombie, sleep, stop, start, run.  The
924511d9c65SJoerg Wunsch  *	array declaration below maps a process state index into a number
925511d9c65SJoerg Wunsch  *	that reflects this ordering.
926511d9c65SJoerg Wunsch  */
927511d9c65SJoerg Wunsch 
928789e3877SBruce Evans static int sorted_state[] = {
929511d9c65SJoerg Wunsch 	0,	/* not used		*/
930511d9c65SJoerg Wunsch 	3,	/* sleep		*/
931511d9c65SJoerg Wunsch 	1,	/* ABANDONED (WAIT)	*/
932511d9c65SJoerg Wunsch 	6,	/* run			*/
933511d9c65SJoerg Wunsch 	5,	/* start		*/
934511d9c65SJoerg Wunsch 	2,	/* zombie		*/
935511d9c65SJoerg Wunsch 	4	/* stop			*/
936511d9c65SJoerg Wunsch };
937511d9c65SJoerg Wunsch 
938f3b2c2d1SWolfram Schneider 
9394946a00bSDag-Erling Smørgrav #define ORDERKEY_PCTCPU(a, b) do { \
940bbf750fbSGiorgos Keramidas 	long diff; \
941bbf750fbSGiorgos Keramidas 	if (ps.wcpu) \
942789e3877SBruce Evans 		diff = floor(1.0E6 * weighted_cpu(pctdouble((b)->ki_pctcpu), \
943789e3877SBruce Evans 		    (b))) - \
944789e3877SBruce Evans 		    floor(1.0E6 * weighted_cpu(pctdouble((a)->ki_pctcpu), \
945789e3877SBruce Evans 		    (a))); \
946bbf750fbSGiorgos Keramidas 	else \
947bbf750fbSGiorgos Keramidas 		diff = (long)(b)->ki_pctcpu - (long)(a)->ki_pctcpu; \
9484946a00bSDag-Erling Smørgrav 	if (diff != 0) \
9494946a00bSDag-Erling Smørgrav 		return (diff > 0 ? 1 : -1); \
9504946a00bSDag-Erling Smørgrav } while (0)
951f3b2c2d1SWolfram Schneider 
9524946a00bSDag-Erling Smørgrav #define ORDERKEY_CPTICKS(a, b) do { \
953e38035a5SDag-Erling Smørgrav 	int64_t diff = (int64_t)(b)->ki_runtime - (int64_t)(a)->ki_runtime; \
9544946a00bSDag-Erling Smørgrav 	if (diff != 0) \
9554946a00bSDag-Erling Smørgrav 		return (diff > 0 ? 1 : -1); \
9564946a00bSDag-Erling Smørgrav } while (0)
957f3b2c2d1SWolfram Schneider 
9584946a00bSDag-Erling Smørgrav #define ORDERKEY_STATE(a, b) do { \
9594946a00bSDag-Erling Smørgrav 	int diff = sorted_state[(b)->ki_stat] - sorted_state[(a)->ki_stat]; \
9604946a00bSDag-Erling Smørgrav 	if (diff != 0) \
9614946a00bSDag-Erling Smørgrav 		return (diff > 0 ? 1 : -1); \
9624946a00bSDag-Erling Smørgrav } while (0)
963f3b2c2d1SWolfram Schneider 
9644946a00bSDag-Erling Smørgrav #define ORDERKEY_PRIO(a, b) do { \
965e38035a5SDag-Erling Smørgrav 	int diff = (int)(b)->ki_pri.pri_level - (int)(a)->ki_pri.pri_level; \
9664946a00bSDag-Erling Smørgrav 	if (diff != 0) \
9674946a00bSDag-Erling Smørgrav 		return (diff > 0 ? 1 : -1); \
9684946a00bSDag-Erling Smørgrav } while (0)
969f3b2c2d1SWolfram Schneider 
97032efd263SGiorgos Keramidas #define	ORDERKEY_THREADS(a, b) do { \
97132efd263SGiorgos Keramidas 	int diff = (int)(b)->ki_numthreads - (int)(a)->ki_numthreads; \
97232efd263SGiorgos Keramidas 	if (diff != 0) \
97332efd263SGiorgos Keramidas 		return (diff > 0 ? 1 : -1); \
97432efd263SGiorgos Keramidas } while (0)
97532efd263SGiorgos Keramidas 
9764946a00bSDag-Erling Smørgrav #define ORDERKEY_RSSIZE(a, b) do { \
977e38035a5SDag-Erling Smørgrav 	long diff = (long)(b)->ki_rssize - (long)(a)->ki_rssize; \
9784946a00bSDag-Erling Smørgrav 	if (diff != 0) \
9794946a00bSDag-Erling Smørgrav 		return (diff > 0 ? 1 : -1); \
9804946a00bSDag-Erling Smørgrav } while (0)
981f3b2c2d1SWolfram Schneider 
9824946a00bSDag-Erling Smørgrav #define ORDERKEY_MEM(a, b) do { \
983e38035a5SDag-Erling Smørgrav 	long diff = (long)PROCSIZE((b)) - (long)PROCSIZE((a)); \
9844946a00bSDag-Erling Smørgrav 	if (diff != 0) \
9854946a00bSDag-Erling Smørgrav 		return (diff > 0 ? 1 : -1); \
9864946a00bSDag-Erling Smørgrav } while (0)
987f3b2c2d1SWolfram Schneider 
988f3b2c2d1SWolfram Schneider /* compare_cpu - the comparison function for sorting by cpu percentage */
989f3b2c2d1SWolfram Schneider 
990511d9c65SJoerg Wunsch int
991f3b2c2d1SWolfram Schneider #ifdef ORDER
9924946a00bSDag-Erling Smørgrav compare_cpu(void *arg1, void *arg2)
993f3b2c2d1SWolfram Schneider #else
9944946a00bSDag-Erling Smørgrav proc_compare(void *arg1, void *arg2)
995f3b2c2d1SWolfram Schneider #endif
996511d9c65SJoerg Wunsch {
9974946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
9984946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
999511d9c65SJoerg Wunsch 
10004946a00bSDag-Erling Smørgrav 	ORDERKEY_PCTCPU(p1, p2);
10014946a00bSDag-Erling Smørgrav 	ORDERKEY_CPTICKS(p1, p2);
10024946a00bSDag-Erling Smørgrav 	ORDERKEY_STATE(p1, p2);
10034946a00bSDag-Erling Smørgrav 	ORDERKEY_PRIO(p1, p2);
10044946a00bSDag-Erling Smørgrav 	ORDERKEY_RSSIZE(p1, p2);
10054946a00bSDag-Erling Smørgrav 	ORDERKEY_MEM(p1, p2);
1006511d9c65SJoerg Wunsch 
10074946a00bSDag-Erling Smørgrav 	return (0);
1008511d9c65SJoerg Wunsch }
1009511d9c65SJoerg Wunsch 
1010f3b2c2d1SWolfram Schneider #ifdef ORDER
1011789e3877SBruce Evans /* "cpu" compare routines */
1012789e3877SBruce Evans int compare_size(), compare_res(), compare_time(), compare_prio(),
1013789e3877SBruce Evans     compare_threads();
1014789e3877SBruce Evans 
1015789e3877SBruce Evans /*
1016789e3877SBruce Evans  * "io" compare routines.  Context switches aren't i/o, but are displayed
1017789e3877SBruce Evans  * on the "io" display.
1018789e3877SBruce Evans  */
1019789e3877SBruce Evans int compare_iototal(), compare_ioread(), compare_iowrite(), compare_iofault(),
1020789e3877SBruce Evans     compare_vcsw(), compare_ivcsw();
1021f3b2c2d1SWolfram Schneider 
10225d320d4bSAlfred Perlstein int (*compares[])() = {
1023f3b2c2d1SWolfram Schneider 	compare_cpu,
1024f3b2c2d1SWolfram Schneider 	compare_size,
1025f3b2c2d1SWolfram Schneider 	compare_res,
1026f3b2c2d1SWolfram Schneider 	compare_time,
1027f3b2c2d1SWolfram Schneider 	compare_prio,
102832efd263SGiorgos Keramidas 	compare_threads,
10295d320d4bSAlfred Perlstein 	compare_iototal,
10305d320d4bSAlfred Perlstein 	compare_ioread,
10315d320d4bSAlfred Perlstein 	compare_iowrite,
10325d320d4bSAlfred Perlstein 	compare_iofault,
10335d320d4bSAlfred Perlstein 	compare_vcsw,
10345d320d4bSAlfred Perlstein 	compare_ivcsw,
1035f3b2c2d1SWolfram Schneider 	NULL
1036f3b2c2d1SWolfram Schneider };
1037f3b2c2d1SWolfram Schneider 
1038f3b2c2d1SWolfram Schneider /* compare_size - the comparison function for sorting by total memory usage */
1039f3b2c2d1SWolfram Schneider 
1040f3b2c2d1SWolfram Schneider int
10414946a00bSDag-Erling Smørgrav compare_size(void *arg1, void *arg2)
1042f3b2c2d1SWolfram Schneider {
10434946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
10444946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
1045f3b2c2d1SWolfram Schneider 
10464946a00bSDag-Erling Smørgrav 	ORDERKEY_MEM(p1, p2);
10474946a00bSDag-Erling Smørgrav 	ORDERKEY_RSSIZE(p1, p2);
10484946a00bSDag-Erling Smørgrav 	ORDERKEY_PCTCPU(p1, p2);
10494946a00bSDag-Erling Smørgrav 	ORDERKEY_CPTICKS(p1, p2);
10504946a00bSDag-Erling Smørgrav 	ORDERKEY_STATE(p1, p2);
10514946a00bSDag-Erling Smørgrav 	ORDERKEY_PRIO(p1, p2);
1052f3b2c2d1SWolfram Schneider 
10534946a00bSDag-Erling Smørgrav 	return (0);
1054f3b2c2d1SWolfram Schneider }
1055f3b2c2d1SWolfram Schneider 
1056f3b2c2d1SWolfram Schneider /* compare_res - the comparison function for sorting by resident set size */
1057f3b2c2d1SWolfram Schneider 
1058f3b2c2d1SWolfram Schneider int
10594946a00bSDag-Erling Smørgrav compare_res(void *arg1, void *arg2)
1060f3b2c2d1SWolfram Schneider {
10614946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
10624946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
1063f3b2c2d1SWolfram Schneider 
10644946a00bSDag-Erling Smørgrav 	ORDERKEY_RSSIZE(p1, p2);
10654946a00bSDag-Erling Smørgrav 	ORDERKEY_MEM(p1, p2);
10664946a00bSDag-Erling Smørgrav 	ORDERKEY_PCTCPU(p1, p2);
10674946a00bSDag-Erling Smørgrav 	ORDERKEY_CPTICKS(p1, p2);
10684946a00bSDag-Erling Smørgrav 	ORDERKEY_STATE(p1, p2);
10694946a00bSDag-Erling Smørgrav 	ORDERKEY_PRIO(p1, p2);
1070f3b2c2d1SWolfram Schneider 
10714946a00bSDag-Erling Smørgrav 	return (0);
1072f3b2c2d1SWolfram Schneider }
1073f3b2c2d1SWolfram Schneider 
1074f3b2c2d1SWolfram Schneider /* compare_time - the comparison function for sorting by total cpu time */
1075f3b2c2d1SWolfram Schneider 
1076f3b2c2d1SWolfram Schneider int
10774946a00bSDag-Erling Smørgrav compare_time(void *arg1, void *arg2)
1078f3b2c2d1SWolfram Schneider {
10794946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
10804946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
1081f3b2c2d1SWolfram Schneider 
10824946a00bSDag-Erling Smørgrav 	ORDERKEY_CPTICKS(p1, p2);
10834946a00bSDag-Erling Smørgrav 	ORDERKEY_PCTCPU(p1, p2);
10844946a00bSDag-Erling Smørgrav 	ORDERKEY_STATE(p1, p2);
10854946a00bSDag-Erling Smørgrav 	ORDERKEY_PRIO(p1, p2);
10864946a00bSDag-Erling Smørgrav 	ORDERKEY_RSSIZE(p1, p2);
10874946a00bSDag-Erling Smørgrav 	ORDERKEY_MEM(p1, p2);
1088f3b2c2d1SWolfram Schneider 
10894946a00bSDag-Erling Smørgrav 	return (0);
1090f3b2c2d1SWolfram Schneider }
1091f3b2c2d1SWolfram Schneider 
10924946a00bSDag-Erling Smørgrav /* compare_prio - the comparison function for sorting by priority */
1093f3b2c2d1SWolfram Schneider 
1094f3b2c2d1SWolfram Schneider int
10954946a00bSDag-Erling Smørgrav compare_prio(void *arg1, void *arg2)
1096f3b2c2d1SWolfram Schneider {
10974946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
10984946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
1099f3b2c2d1SWolfram Schneider 
11004946a00bSDag-Erling Smørgrav 	ORDERKEY_PRIO(p1, p2);
11014946a00bSDag-Erling Smørgrav 	ORDERKEY_CPTICKS(p1, p2);
11024946a00bSDag-Erling Smørgrav 	ORDERKEY_PCTCPU(p1, p2);
11034946a00bSDag-Erling Smørgrav 	ORDERKEY_STATE(p1, p2);
11044946a00bSDag-Erling Smørgrav 	ORDERKEY_RSSIZE(p1, p2);
11054946a00bSDag-Erling Smørgrav 	ORDERKEY_MEM(p1, p2);
1106f3b2c2d1SWolfram Schneider 
11074946a00bSDag-Erling Smørgrav 	return (0);
1108f3b2c2d1SWolfram Schneider }
110932efd263SGiorgos Keramidas 
111032efd263SGiorgos Keramidas /* compare_threads - the comparison function for sorting by threads */
111132efd263SGiorgos Keramidas int
111232efd263SGiorgos Keramidas compare_threads(void *arg1, void *arg2)
111332efd263SGiorgos Keramidas {
111432efd263SGiorgos Keramidas 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
111532efd263SGiorgos Keramidas 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
111632efd263SGiorgos Keramidas 
111732efd263SGiorgos Keramidas 	ORDERKEY_THREADS(p1, p2);
111832efd263SGiorgos Keramidas 	ORDERKEY_PCTCPU(p1, p2);
111932efd263SGiorgos Keramidas 	ORDERKEY_CPTICKS(p1, p2);
112032efd263SGiorgos Keramidas 	ORDERKEY_STATE(p1, p2);
112132efd263SGiorgos Keramidas 	ORDERKEY_PRIO(p1, p2);
112232efd263SGiorgos Keramidas 	ORDERKEY_RSSIZE(p1, p2);
112332efd263SGiorgos Keramidas 	ORDERKEY_MEM(p1, p2);
112432efd263SGiorgos Keramidas 
112532efd263SGiorgos Keramidas 	return (0);
112632efd263SGiorgos Keramidas }
1127789e3877SBruce Evans #endif /* ORDER */
1128511d9c65SJoerg Wunsch 
1129789e3877SBruce Evans /* assorted comparison functions for sorting by i/o */
113026b2243aSGiorgos Keramidas 
1131db6bb7fcSAlfred Perlstein int
113226b2243aSGiorgos Keramidas #ifdef ORDER
113326b2243aSGiorgos Keramidas compare_iototal(void *arg1, void *arg2)
113426b2243aSGiorgos Keramidas #else
11354946a00bSDag-Erling Smørgrav io_compare(void *arg1, void *arg2)
113626b2243aSGiorgos Keramidas #endif
1137db6bb7fcSAlfred Perlstein {
11384946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
11394946a00bSDag-Erling Smørgrav 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
1140db6bb7fcSAlfred Perlstein 
11414946a00bSDag-Erling Smørgrav 	return (get_io_total(p2) - get_io_total(p1));
1142db6bb7fcSAlfred Perlstein }
114326b2243aSGiorgos Keramidas 
114426b2243aSGiorgos Keramidas #ifdef ORDER
114526b2243aSGiorgos Keramidas int
114626b2243aSGiorgos Keramidas compare_ioread(void *arg1, void *arg2)
114726b2243aSGiorgos Keramidas {
114826b2243aSGiorgos Keramidas 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
114926b2243aSGiorgos Keramidas 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
115026b2243aSGiorgos Keramidas 	long dummy, inp1, inp2;
115126b2243aSGiorgos Keramidas 
11525d320d4bSAlfred Perlstein 	(void) get_io_stats(p1, &inp1, &dummy, &dummy, &dummy, &dummy);
11535d320d4bSAlfred Perlstein 	(void) get_io_stats(p2, &inp2, &dummy, &dummy, &dummy, &dummy);
115426b2243aSGiorgos Keramidas 
115526b2243aSGiorgos Keramidas 	return (inp2 - inp1);
115626b2243aSGiorgos Keramidas }
115726b2243aSGiorgos Keramidas 
115826b2243aSGiorgos Keramidas int
115926b2243aSGiorgos Keramidas compare_iowrite(void *arg1, void *arg2)
116026b2243aSGiorgos Keramidas {
116126b2243aSGiorgos Keramidas 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
116226b2243aSGiorgos Keramidas 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
116326b2243aSGiorgos Keramidas 	long dummy, oup1, oup2;
116426b2243aSGiorgos Keramidas 
11655d320d4bSAlfred Perlstein 	(void) get_io_stats(p1, &dummy, &oup1, &dummy, &dummy, &dummy);
11665d320d4bSAlfred Perlstein 	(void) get_io_stats(p2, &dummy, &oup2, &dummy, &dummy, &dummy);
116726b2243aSGiorgos Keramidas 
116826b2243aSGiorgos Keramidas 	return (oup2 - oup1);
116926b2243aSGiorgos Keramidas }
117026b2243aSGiorgos Keramidas 
117126b2243aSGiorgos Keramidas int
117226b2243aSGiorgos Keramidas compare_iofault(void *arg1, void *arg2)
117326b2243aSGiorgos Keramidas {
117426b2243aSGiorgos Keramidas 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
117526b2243aSGiorgos Keramidas 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
117626b2243aSGiorgos Keramidas 	long dummy, flp1, flp2;
117726b2243aSGiorgos Keramidas 
11785d320d4bSAlfred Perlstein 	(void) get_io_stats(p1, &dummy, &dummy, &flp1, &dummy, &dummy);
11795d320d4bSAlfred Perlstein 	(void) get_io_stats(p2, &dummy, &dummy, &flp2, &dummy, &dummy);
11805d320d4bSAlfred Perlstein 
11815d320d4bSAlfred Perlstein 	return (flp2 - flp1);
11825d320d4bSAlfred Perlstein }
11835d320d4bSAlfred Perlstein 
11845d320d4bSAlfred Perlstein int
11855d320d4bSAlfred Perlstein compare_vcsw(void *arg1, void *arg2)
11865d320d4bSAlfred Perlstein {
11875d320d4bSAlfred Perlstein 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
11885d320d4bSAlfred Perlstein 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
11895d320d4bSAlfred Perlstein 	long dummy, flp1, flp2;
11905d320d4bSAlfred Perlstein 
11915d320d4bSAlfred Perlstein 	(void) get_io_stats(p1, &dummy, &dummy, &dummy, &flp1, &dummy);
11925d320d4bSAlfred Perlstein 	(void) get_io_stats(p2, &dummy, &dummy, &dummy, &flp2, &dummy);
11935d320d4bSAlfred Perlstein 
11945d320d4bSAlfred Perlstein 	return (flp2 - flp1);
11955d320d4bSAlfred Perlstein }
11965d320d4bSAlfred Perlstein 
11975d320d4bSAlfred Perlstein int
11985d320d4bSAlfred Perlstein compare_ivcsw(void *arg1, void *arg2)
11995d320d4bSAlfred Perlstein {
12005d320d4bSAlfred Perlstein 	struct kinfo_proc *p1 = *(struct kinfo_proc **)arg1;
12015d320d4bSAlfred Perlstein 	struct kinfo_proc *p2 = *(struct kinfo_proc **)arg2;
12025d320d4bSAlfred Perlstein 	long dummy, flp1, flp2;
12035d320d4bSAlfred Perlstein 
12045d320d4bSAlfred Perlstein 	(void) get_io_stats(p1, &dummy, &dummy, &dummy, &dummy, &flp1);
12055d320d4bSAlfred Perlstein 	(void) get_io_stats(p2, &dummy, &dummy, &dummy, &dummy, &flp2);
120626b2243aSGiorgos Keramidas 
120726b2243aSGiorgos Keramidas 	return (flp2 - flp1);
120826b2243aSGiorgos Keramidas }
120926b2243aSGiorgos Keramidas #endif /* ORDER */
121026b2243aSGiorgos Keramidas 
1211511d9c65SJoerg Wunsch /*
1212511d9c65SJoerg Wunsch  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
1213511d9c65SJoerg Wunsch  *		the process does not exist.
1214511d9c65SJoerg Wunsch  *		It is EXTREMLY IMPORTANT that this function work correctly.
1215511d9c65SJoerg Wunsch  *		If top runs setuid root (as in SVR4), then this function
1216511d9c65SJoerg Wunsch  *		is the only thing that stands in the way of a serious
1217511d9c65SJoerg Wunsch  *		security problem.  It validates requests for the "kill"
1218511d9c65SJoerg Wunsch  *		and "renice" commands.
1219511d9c65SJoerg Wunsch  */
1220511d9c65SJoerg Wunsch 
1221970636e9SAlfred Perlstein int
1222f6a10feaSDag-Erling Smørgrav proc_owner(int pid)
1223511d9c65SJoerg Wunsch {
1224970636e9SAlfred Perlstein 	int cnt;
1225970636e9SAlfred Perlstein 	struct kinfo_proc **prefp;
1226970636e9SAlfred Perlstein 	struct kinfo_proc *pp;
1227511d9c65SJoerg Wunsch 
1228511d9c65SJoerg Wunsch 	prefp = pref;
1229511d9c65SJoerg Wunsch 	cnt = pref_len;
12304946a00bSDag-Erling Smørgrav 	while (--cnt >= 0) {
1231511d9c65SJoerg Wunsch 		pp = *prefp++;
12321f7d2501SKirk McKusick 		if (pp->ki_pid == (pid_t)pid)
12331f7d2501SKirk McKusick 			return ((int)pp->ki_ruid);
1234511d9c65SJoerg Wunsch 	}
1235511d9c65SJoerg Wunsch 	return (-1);
1236511d9c65SJoerg Wunsch }
1237511d9c65SJoerg Wunsch 
1238de916c8bSBruce Evans static int
1239f6a10feaSDag-Erling Smørgrav swapmode(int *retavail, int *retfree)
1240511d9c65SJoerg Wunsch {
12417bb42db9SMatthew Dillon 	int n;
12427bb42db9SMatthew Dillon 	int pagesize = getpagesize();
12437bb42db9SMatthew Dillon 	struct kvm_swap swapary[1];
1244511d9c65SJoerg Wunsch 
12457bb42db9SMatthew Dillon 	*retavail = 0;
12467bb42db9SMatthew Dillon 	*retfree = 0;
1247511d9c65SJoerg Wunsch 
12487bb42db9SMatthew Dillon #define CONVERT(v)	((quad_t)(v) * pagesize / 1024)
12497bb42db9SMatthew Dillon 
12507bb42db9SMatthew Dillon 	n = kvm_getswapinfo(kd, swapary, 1, 0);
125147b370f5SMatthew Dillon 	if (n < 0 || swapary[0].ksw_total == 0)
1252511d9c65SJoerg Wunsch 		return (0);
1253511d9c65SJoerg Wunsch 
12547bb42db9SMatthew Dillon 	*retavail = CONVERT(swapary[0].ksw_total);
12557bb42db9SMatthew Dillon 	*retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);
12567bb42db9SMatthew Dillon 
12574946a00bSDag-Erling Smørgrav 	n = (int)(swapary[0].ksw_used * 100.0 / swapary[0].ksw_total);
12587bb42db9SMatthew Dillon 	return (n);
1259511d9c65SJoerg Wunsch }
1260