xref: /dragonfly/usr.bin/top/m_dragonfly.c (revision bcd4a7c1)
17af1b2bcSJan Lentfer /*
27af1b2bcSJan Lentfer  * top - a top users display for Unix
37af1b2bcSJan Lentfer  *
47af1b2bcSJan Lentfer  * SYNOPSIS:  For DragonFly 2.x and later
57af1b2bcSJan Lentfer  *
67af1b2bcSJan Lentfer  * DESCRIPTION:
77af1b2bcSJan Lentfer  * Originally written for BSD4.4 system by Christos Zoulas.
87af1b2bcSJan Lentfer  * Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider
97af1b2bcSJan Lentfer  * Order support hacked in from top-3.5beta6/machine/m_aix41.c
107af1b2bcSJan Lentfer  *   by Monte Mitzelfelt (for latest top see http://www.groupsys.com/topinfo/)
117af1b2bcSJan Lentfer  *
127af1b2bcSJan Lentfer  * This is the machine-dependent module for DragonFly 2.5.1
137af1b2bcSJan Lentfer  * Should work for:
147af1b2bcSJan Lentfer  *	DragonFly 2.x and above
157af1b2bcSJan Lentfer  *
167af1b2bcSJan Lentfer  * LIBS: -lkvm
177af1b2bcSJan Lentfer  *
187af1b2bcSJan Lentfer  * AUTHOR: Jan Lentfer <Jan.Lentfer@web.de>
197af1b2bcSJan Lentfer  * This module has been put together from different sources and is based on the
207af1b2bcSJan Lentfer  * work of many other people, e.g. Matthew Dillon, Simon Schubert, Jordan Gordeev.
217af1b2bcSJan Lentfer  *
227af1b2bcSJan Lentfer  * $FreeBSD: src/usr.bin/top/machine.c,v 1.29.2.2 2001/07/31 20:27:05 tmm Exp $
237af1b2bcSJan Lentfer  * $DragonFly: src/usr.bin/top/machine.c,v 1.26 2008/10/16 01:52:33 swildner Exp $
247af1b2bcSJan Lentfer  */
257af1b2bcSJan Lentfer 
267af1b2bcSJan Lentfer #include <sys/time.h>
277af1b2bcSJan Lentfer #include <sys/types.h>
287af1b2bcSJan Lentfer #include <sys/signal.h>
297af1b2bcSJan Lentfer #include <sys/param.h>
307af1b2bcSJan Lentfer 
317af1b2bcSJan Lentfer #include "os.h"
327af1b2bcSJan Lentfer #include <err.h>
337af1b2bcSJan Lentfer #include <kvm.h>
347af1b2bcSJan Lentfer #include <stdio.h>
357af1b2bcSJan Lentfer #include <unistd.h>
367af1b2bcSJan Lentfer #include <math.h>
377af1b2bcSJan Lentfer #include <pwd.h>
387af1b2bcSJan Lentfer #include <sys/errno.h>
397af1b2bcSJan Lentfer #include <sys/sysctl.h>
407af1b2bcSJan Lentfer #include <sys/file.h>
417af1b2bcSJan Lentfer #include <sys/time.h>
427af1b2bcSJan Lentfer #include <sys/user.h>
437af1b2bcSJan Lentfer #include <sys/vmmeter.h>
447af1b2bcSJan Lentfer #include <sys/resource.h>
457af1b2bcSJan Lentfer #include <sys/rtprio.h>
467af1b2bcSJan Lentfer 
477af1b2bcSJan Lentfer /* Swap */
487af1b2bcSJan Lentfer #include <stdlib.h>
497af1b2bcSJan Lentfer #include <stdio.h>
507af1b2bcSJan Lentfer #include <sys/conf.h>
517af1b2bcSJan Lentfer 
527af1b2bcSJan Lentfer #include <osreldate.h>		/* for changes in kernel structures */
537af1b2bcSJan Lentfer 
547af1b2bcSJan Lentfer #include <sys/kinfo.h>
557af1b2bcSJan Lentfer #include <kinfo.h>
567af1b2bcSJan Lentfer #include "top.h"
577af1b2bcSJan Lentfer #include "display.h"
587af1b2bcSJan Lentfer #include "machine.h"
597af1b2bcSJan Lentfer #include "screen.h"
607af1b2bcSJan Lentfer #include "utils.h"
617af1b2bcSJan Lentfer 
627af1b2bcSJan Lentfer int swapmode(int *retavail, int *retfree);
637af1b2bcSJan Lentfer static int smpmode;
647af1b2bcSJan Lentfer static int namelength;
657af1b2bcSJan Lentfer static int cmdlength;
66efde5811SJan Lentfer static int show_fullcmd;
677af1b2bcSJan Lentfer 
687af1b2bcSJan Lentfer int n_cpus = 0;
697af1b2bcSJan Lentfer 
707af1b2bcSJan Lentfer /*
71961f1f09SJan Lentfer  * needs to be a global symbol, so wrapper can be modified accordingly.
727af1b2bcSJan Lentfer  */
737af1b2bcSJan Lentfer static int show_threads = 0;
747af1b2bcSJan Lentfer 
757af1b2bcSJan Lentfer /* get_process_info passes back a handle.  This is what it looks like: */
767af1b2bcSJan Lentfer 
77961f1f09SJan Lentfer struct handle {
787af1b2bcSJan Lentfer 	struct kinfo_proc **next_proc;	/* points to next valid proc pointer */
797af1b2bcSJan Lentfer 	int remaining;		/* number of pointers remaining */
807af1b2bcSJan Lentfer };
817af1b2bcSJan Lentfer 
827af1b2bcSJan Lentfer /* declarations for load_avg */
837af1b2bcSJan Lentfer #include "loadavg.h"
847af1b2bcSJan Lentfer 
857af1b2bcSJan Lentfer #define PP(pp, field) ((pp)->kp_ ## field)
867af1b2bcSJan Lentfer #define LP(pp, field) ((pp)->kp_lwp.kl_ ## field)
877af1b2bcSJan Lentfer #define VP(pp, field) ((pp)->kp_vm_ ## field)
887af1b2bcSJan Lentfer 
897af1b2bcSJan Lentfer /* define what weighted cpu is.  */
907af1b2bcSJan Lentfer #define weighted_cpu(pct, pp) (PP((pp), swtime) == 0 ? 0.0 : \
917af1b2bcSJan Lentfer 			 ((pct) / (1.0 - exp(PP((pp), swtime) * logcpu))))
927af1b2bcSJan Lentfer 
937af1b2bcSJan Lentfer /* what we consider to be process size: */
947af1b2bcSJan Lentfer #define PROCSIZE(pp) (VP((pp), map_size) / 1024)
957af1b2bcSJan Lentfer 
967af1b2bcSJan Lentfer /*
977af1b2bcSJan Lentfer  * These definitions control the format of the per-process area
987af1b2bcSJan Lentfer  */
997af1b2bcSJan Lentfer 
1007af1b2bcSJan Lentfer static char smp_header[] =
101*bcd4a7c1SJan Lentfer "  PID %-*.*s PRI NICE  SIZE    RES STATE  C   TIME   CTIME   CPU COMMAND";
1027af1b2bcSJan Lentfer 
1037af1b2bcSJan Lentfer #define smp_Proc_format \
104*bcd4a7c1SJan Lentfer 	"%5d %-*.*s %3d %3d%7s %6s %-6.6s %1x%7s %7s %5.2f%% %.*s"
1057af1b2bcSJan Lentfer 
1067af1b2bcSJan Lentfer static char up_header[] =
107*bcd4a7c1SJan Lentfer "  PID %-*.*s PRI NICE  SIZE    RES STATE    TIME   CTIME   CPU COMMAND";
1087af1b2bcSJan Lentfer 
1097af1b2bcSJan Lentfer #define up_Proc_format \
110*bcd4a7c1SJan Lentfer 	"%5d %-*.*s %3d %3d%7s %6s %-6.6s%.0d%7s %7s %5.2f%% %.*s"
1117af1b2bcSJan Lentfer 
1127af1b2bcSJan Lentfer 
1137af1b2bcSJan Lentfer 
1147af1b2bcSJan Lentfer /* process state names for the "STATE" column of the display */
115961f1f09SJan Lentfer /*
116961f1f09SJan Lentfer  * the extra nulls in the string "run" are for adding a slash and the
117961f1f09SJan Lentfer  * processor number when needed
118961f1f09SJan Lentfer  */
1197af1b2bcSJan Lentfer 
120961f1f09SJan Lentfer const char *state_abbrev[] = {
1217af1b2bcSJan Lentfer 	"", "RUN\0\0\0", "STOP", "SLEEP",
1227af1b2bcSJan Lentfer };
1237af1b2bcSJan Lentfer 
1247af1b2bcSJan Lentfer 
1257af1b2bcSJan Lentfer static kvm_t *kd;
1267af1b2bcSJan Lentfer 
1277af1b2bcSJan Lentfer /* values that we stash away in _init and use in later routines */
1287af1b2bcSJan Lentfer 
1297af1b2bcSJan Lentfer static double logcpu;
1307af1b2bcSJan Lentfer 
1317af1b2bcSJan Lentfer static long lastpid;
1327af1b2bcSJan Lentfer static int ccpu;
1337af1b2bcSJan Lentfer 
1347af1b2bcSJan Lentfer /* these are for calculating cpu state percentages */
1357af1b2bcSJan Lentfer 
1367af1b2bcSJan Lentfer static struct kinfo_cputime *cp_time, *cp_old;
1377af1b2bcSJan Lentfer 
1387af1b2bcSJan Lentfer /* these are for detailing the process states */
1397af1b2bcSJan Lentfer 
1407af1b2bcSJan Lentfer int process_states[6];
1417af1b2bcSJan Lentfer char *procstatenames[] = {
1427af1b2bcSJan Lentfer 	"", " starting, ", " running, ", " sleeping, ", " stopped, ",
1437af1b2bcSJan Lentfer 	" zombie, ",
1447af1b2bcSJan Lentfer 	NULL
1457af1b2bcSJan Lentfer };
1467af1b2bcSJan Lentfer 
1477af1b2bcSJan Lentfer /* these are for detailing the cpu states */
1487af1b2bcSJan Lentfer #define CPU_STATES 5
1497af1b2bcSJan Lentfer int *cpu_states;
1507af1b2bcSJan Lentfer char *cpustatenames[CPU_STATES + 1] = {
1517af1b2bcSJan Lentfer 	"user", "nice", "system", "interrupt", "idle", NULL
1527af1b2bcSJan Lentfer };
1537af1b2bcSJan Lentfer 
1547af1b2bcSJan Lentfer /* these are for detailing the memory statistics */
1557af1b2bcSJan Lentfer 
1567af1b2bcSJan Lentfer long memory_stats[7];
1577af1b2bcSJan Lentfer char *memorynames[] = {
1587af1b2bcSJan Lentfer 	"K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ", "K Free",
1597af1b2bcSJan Lentfer 	NULL
1607af1b2bcSJan Lentfer };
1617af1b2bcSJan Lentfer 
1627af1b2bcSJan Lentfer long swap_stats[7];
1637af1b2bcSJan Lentfer char *swapnames[] = {
1647af1b2bcSJan Lentfer 	/* 0           1            2           3            4       5 */
1657af1b2bcSJan Lentfer 	"K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
1667af1b2bcSJan Lentfer 	NULL
1677af1b2bcSJan Lentfer };
1687af1b2bcSJan Lentfer 
1697af1b2bcSJan Lentfer 
1707af1b2bcSJan Lentfer /* these are for keeping track of the proc array */
1717af1b2bcSJan Lentfer 
1727af1b2bcSJan Lentfer static int nproc;
1737af1b2bcSJan Lentfer static int onproc = -1;
1747af1b2bcSJan Lentfer static int pref_len;
1757af1b2bcSJan Lentfer static struct kinfo_proc *pbase;
1767af1b2bcSJan Lentfer static struct kinfo_proc **pref;
1777af1b2bcSJan Lentfer 
1787af1b2bcSJan Lentfer /* these are for getting the memory statistics */
1797af1b2bcSJan Lentfer 
1807af1b2bcSJan Lentfer static int pageshift;		/* log base 2 of the pagesize */
1817af1b2bcSJan Lentfer 
1827af1b2bcSJan Lentfer /* define pagetok in terms of pageshift */
1837af1b2bcSJan Lentfer 
1847af1b2bcSJan Lentfer #define pagetok(size) ((size) << pageshift)
1857af1b2bcSJan Lentfer 
1867af1b2bcSJan Lentfer /* sorting orders. first is default */
1877af1b2bcSJan Lentfer char *ordernames[] = {
188*bcd4a7c1SJan Lentfer 	"cpu", "size", "res", "time", "pri", "thr", "pid", "ctime",  NULL
1897af1b2bcSJan Lentfer };
1907af1b2bcSJan Lentfer 
1917af1b2bcSJan Lentfer /* compare routines */
1928b72b421SJan Lentfer int proc_compare (struct kinfo_proc **, struct kinfo_proc **);
1938b72b421SJan Lentfer int compare_size (struct kinfo_proc **, struct kinfo_proc **);
1948b72b421SJan Lentfer int compare_res (struct kinfo_proc **, struct kinfo_proc **);
1958b72b421SJan Lentfer int compare_time (struct kinfo_proc **, struct kinfo_proc **);
196*bcd4a7c1SJan Lentfer int compare_ctime (struct kinfo_proc **, struct kinfo_proc **);
1978b72b421SJan Lentfer int compare_prio(struct kinfo_proc **, struct kinfo_proc **);
1988b72b421SJan Lentfer int compare_thr (struct kinfo_proc **, struct kinfo_proc **);
1998b72b421SJan Lentfer int compare_pid (struct kinfo_proc **, struct kinfo_proc **);
2007af1b2bcSJan Lentfer 
2018b72b421SJan Lentfer int (*proc_compares[]) (struct kinfo_proc **,struct kinfo_proc **) = {
2027af1b2bcSJan Lentfer 	proc_compare,
2037af1b2bcSJan Lentfer 	compare_size,
2047af1b2bcSJan Lentfer 	compare_res,
2057af1b2bcSJan Lentfer 	compare_time,
2067af1b2bcSJan Lentfer 	compare_prio,
2078b72b421SJan Lentfer 	compare_thr,
2088b72b421SJan Lentfer 	compare_pid,
209*bcd4a7c1SJan Lentfer 	compare_ctime,
2107af1b2bcSJan Lentfer 	NULL
2117af1b2bcSJan Lentfer };
2127af1b2bcSJan Lentfer 
2137af1b2bcSJan Lentfer static void
2147af1b2bcSJan Lentfer cputime_percentages(int out[CPU_STATES], struct kinfo_cputime *new,
2157af1b2bcSJan Lentfer     struct kinfo_cputime *old)
2167af1b2bcSJan Lentfer {
2177af1b2bcSJan Lentfer 	struct kinfo_cputime diffs;
2187af1b2bcSJan Lentfer 	uint64_t total_change, half_total;
2197af1b2bcSJan Lentfer 
2207af1b2bcSJan Lentfer 	/* initialization */
2217af1b2bcSJan Lentfer 	total_change = 0;
2227af1b2bcSJan Lentfer 
2237af1b2bcSJan Lentfer 	diffs.cp_user = new->cp_user - old->cp_user;
2247af1b2bcSJan Lentfer 	diffs.cp_nice = new->cp_nice - old->cp_nice;
2257af1b2bcSJan Lentfer 	diffs.cp_sys = new->cp_sys - old->cp_sys;
2267af1b2bcSJan Lentfer 	diffs.cp_intr = new->cp_intr - old->cp_intr;
2277af1b2bcSJan Lentfer 	diffs.cp_idle = new->cp_idle - old->cp_idle;
2287af1b2bcSJan Lentfer 	total_change = diffs.cp_user + diffs.cp_nice + diffs.cp_sys +
2297af1b2bcSJan Lentfer 	    diffs.cp_intr + diffs.cp_idle;
2307af1b2bcSJan Lentfer 	old->cp_user = new->cp_user;
2317af1b2bcSJan Lentfer 	old->cp_nice = new->cp_nice;
2327af1b2bcSJan Lentfer 	old->cp_sys = new->cp_sys;
2337af1b2bcSJan Lentfer 	old->cp_intr = new->cp_intr;
2347af1b2bcSJan Lentfer 	old->cp_idle = new->cp_idle;
2357af1b2bcSJan Lentfer 
2367af1b2bcSJan Lentfer 	/* avoid divide by zero potential */
2377af1b2bcSJan Lentfer 	if (total_change == 0)
2387af1b2bcSJan Lentfer 		total_change = 1;
2397af1b2bcSJan Lentfer 
2407af1b2bcSJan Lentfer 	/* calculate percentages based on overall change, rounding up */
2417af1b2bcSJan Lentfer 	half_total = total_change >> 1;
2427af1b2bcSJan Lentfer 
2437af1b2bcSJan Lentfer 	out[0] = ((diffs.cp_user * 1000LL + half_total) / total_change);
2447af1b2bcSJan Lentfer 	out[1] = ((diffs.cp_nice * 1000LL + half_total) / total_change);
2457af1b2bcSJan Lentfer 	out[2] = ((diffs.cp_sys * 1000LL + half_total) / total_change);
2467af1b2bcSJan Lentfer 	out[3] = ((diffs.cp_intr * 1000LL + half_total) / total_change);
2477af1b2bcSJan Lentfer 	out[4] = ((diffs.cp_idle * 1000LL + half_total) / total_change);
2487af1b2bcSJan Lentfer }
2497af1b2bcSJan Lentfer 
2507af1b2bcSJan Lentfer int
2517af1b2bcSJan Lentfer machine_init(struct statics *statics)
2527af1b2bcSJan Lentfer {
2537af1b2bcSJan Lentfer 	int pagesize;
2547af1b2bcSJan Lentfer 	size_t modelen;
2557af1b2bcSJan Lentfer 	struct passwd *pw;
2567af1b2bcSJan Lentfer 	struct timeval boottime;
2577af1b2bcSJan Lentfer 
2587af1b2bcSJan Lentfer 	if (n_cpus < 1) {
2597af1b2bcSJan Lentfer 		if (kinfo_get_cpus(&n_cpus))
2607af1b2bcSJan Lentfer 			err(1, "kinfo_get_cpus failed");
2617af1b2bcSJan Lentfer 	}
2627af1b2bcSJan Lentfer 	/* get boot time */
2637af1b2bcSJan Lentfer 	modelen = sizeof(boottime);
2647af1b2bcSJan Lentfer 	if (sysctlbyname("kern.boottime", &boottime, &modelen, NULL, 0) == -1) {
2657af1b2bcSJan Lentfer 		/* we have no boottime to report */
2667af1b2bcSJan Lentfer 		boottime.tv_sec = -1;
2677af1b2bcSJan Lentfer 	}
2687af1b2bcSJan Lentfer 	modelen = sizeof(smpmode);
2697af1b2bcSJan Lentfer 	if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, NULL, 0) < 0 &&
2707af1b2bcSJan Lentfer 	    sysctlbyname("smp.smp_active", &smpmode, &modelen, NULL, 0) < 0) ||
2717af1b2bcSJan Lentfer 	    modelen != sizeof(smpmode))
2727af1b2bcSJan Lentfer 		smpmode = 0;
2737af1b2bcSJan Lentfer 
2747af1b2bcSJan Lentfer 	while ((pw = getpwent()) != NULL) {
2757af1b2bcSJan Lentfer 		if ((int)strlen(pw->pw_name) > namelength)
2767af1b2bcSJan Lentfer 			namelength = strlen(pw->pw_name);
2777af1b2bcSJan Lentfer 	}
2787af1b2bcSJan Lentfer 	if (namelength < 8)
2797af1b2bcSJan Lentfer 		namelength = 8;
2807af1b2bcSJan Lentfer 	if (smpmode && namelength > 13)
2817af1b2bcSJan Lentfer 		namelength = 13;
2827af1b2bcSJan Lentfer 	else if (namelength > 15)
2837af1b2bcSJan Lentfer 		namelength = 15;
2847af1b2bcSJan Lentfer 
285efde5811SJan Lentfer 	if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
2867af1b2bcSJan Lentfer 		return -1;
2877af1b2bcSJan Lentfer 
2887af1b2bcSJan Lentfer 	if (kinfo_get_sched_ccpu(&ccpu)) {
2897af1b2bcSJan Lentfer 		fprintf(stderr, "top: kinfo_get_sched_ccpu failed\n");
2907af1b2bcSJan Lentfer 		return (-1);
2917af1b2bcSJan Lentfer 	}
2927af1b2bcSJan Lentfer 	/* this is used in calculating WCPU -- calculate it ahead of time */
2937af1b2bcSJan Lentfer 	logcpu = log(loaddouble(ccpu));
2947af1b2bcSJan Lentfer 
2957af1b2bcSJan Lentfer 	pbase = NULL;
2967af1b2bcSJan Lentfer 	pref = NULL;
2977af1b2bcSJan Lentfer 	nproc = 0;
2987af1b2bcSJan Lentfer 	onproc = -1;
299961f1f09SJan Lentfer 	/*
300961f1f09SJan Lentfer 	 * get the page size with "getpagesize" and calculate pageshift from
301961f1f09SJan Lentfer 	 * it
302961f1f09SJan Lentfer 	 */
3037af1b2bcSJan Lentfer 	pagesize = getpagesize();
3047af1b2bcSJan Lentfer 	pageshift = 0;
305961f1f09SJan Lentfer 	while (pagesize > 1) {
3067af1b2bcSJan Lentfer 		pageshift++;
3077af1b2bcSJan Lentfer 		pagesize >>= 1;
3087af1b2bcSJan Lentfer 	}
3097af1b2bcSJan Lentfer 
3107af1b2bcSJan Lentfer 	/* we only need the amount of log(2)1024 for our conversion */
3117af1b2bcSJan Lentfer 	pageshift -= LOG1024;
3127af1b2bcSJan Lentfer 
3137af1b2bcSJan Lentfer 	/* fill in the statics information */
3147af1b2bcSJan Lentfer 	statics->procstate_names = procstatenames;
3157af1b2bcSJan Lentfer 	statics->cpustate_names = cpustatenames;
3167af1b2bcSJan Lentfer 	statics->memory_names = memorynames;
3177af1b2bcSJan Lentfer 	statics->boottime = boottime.tv_sec;
3187af1b2bcSJan Lentfer 	statics->swap_names = swapnames;
3197af1b2bcSJan Lentfer 	statics->order_names = ordernames;
320efde5811SJan Lentfer 	/* we need kvm descriptor in order to show full commands */
321efde5811SJan Lentfer 	statics->flags.fullcmds = kd != NULL;
3227af1b2bcSJan Lentfer 
3237af1b2bcSJan Lentfer 	/* all done! */
3247af1b2bcSJan Lentfer 	return (0);
3257af1b2bcSJan Lentfer }
3267af1b2bcSJan Lentfer 
3277af1b2bcSJan Lentfer char *
3287af1b2bcSJan Lentfer format_header(char *uname_field)
3297af1b2bcSJan Lentfer {
3307af1b2bcSJan Lentfer 	static char Header[128];
3317af1b2bcSJan Lentfer 
3327af1b2bcSJan Lentfer 	snprintf(Header, sizeof(Header), smpmode ? smp_header : up_header,
3337af1b2bcSJan Lentfer 	    namelength, namelength, uname_field);
3347af1b2bcSJan Lentfer 
3357af1b2bcSJan Lentfer 	if (screen_width <= 79)
3367af1b2bcSJan Lentfer 		cmdlength = 80;
3377af1b2bcSJan Lentfer 	else
3388b72b421SJan Lentfer 		cmdlength = screen_width;
3397af1b2bcSJan Lentfer 
3407af1b2bcSJan Lentfer 	cmdlength = cmdlength - strlen(Header) + 6;
3417af1b2bcSJan Lentfer 
3427af1b2bcSJan Lentfer 	return Header;
3437af1b2bcSJan Lentfer }
3447af1b2bcSJan Lentfer 
3457af1b2bcSJan Lentfer static int swappgsin = -1;
3467af1b2bcSJan Lentfer static int swappgsout = -1;
3477af1b2bcSJan Lentfer extern struct timeval timeout;
3487af1b2bcSJan Lentfer 
3497af1b2bcSJan Lentfer void
3507af1b2bcSJan Lentfer get_system_info(struct system_info *si)
3517af1b2bcSJan Lentfer {
3527af1b2bcSJan Lentfer 	size_t len;
3537af1b2bcSJan Lentfer 	int cpu;
3547af1b2bcSJan Lentfer 
3557af1b2bcSJan Lentfer 	if (cpu_states == NULL) {
3567af1b2bcSJan Lentfer 		cpu_states = malloc(sizeof(*cpu_states) * CPU_STATES * n_cpus);
3577af1b2bcSJan Lentfer 		if (cpu_states == NULL)
3587af1b2bcSJan Lentfer 			err(1, "malloc");
3597af1b2bcSJan Lentfer 		bzero(cpu_states, sizeof(*cpu_states) * CPU_STATES * n_cpus);
3607af1b2bcSJan Lentfer 	}
3617af1b2bcSJan Lentfer 	if (cp_time == NULL) {
3627af1b2bcSJan Lentfer 		cp_time = malloc(2 * n_cpus * sizeof(cp_time[0]));
3637af1b2bcSJan Lentfer 		if (cp_time == NULL)
3647af1b2bcSJan Lentfer 			err(1, "cp_time");
3657af1b2bcSJan Lentfer 		cp_old = cp_time + n_cpus;
3667af1b2bcSJan Lentfer 
3677af1b2bcSJan Lentfer 		len = n_cpus * sizeof(cp_old[0]);
3687af1b2bcSJan Lentfer 		bzero(cp_time, len);
3697af1b2bcSJan Lentfer 		if (sysctlbyname("kern.cputime", cp_old, &len, NULL, 0))
3707af1b2bcSJan Lentfer 			err(1, "kern.cputime");
3717af1b2bcSJan Lentfer 	}
3727af1b2bcSJan Lentfer 	len = n_cpus * sizeof(cp_time[0]);
3737af1b2bcSJan Lentfer 	bzero(cp_time, len);
3747af1b2bcSJan Lentfer 	if (sysctlbyname("kern.cputime", cp_time, &len, NULL, 0))
3757af1b2bcSJan Lentfer 		err(1, "kern.cputime");
3767af1b2bcSJan Lentfer 
3777af1b2bcSJan Lentfer 	getloadavg(si->load_avg, 3);
3787af1b2bcSJan Lentfer 
3797af1b2bcSJan Lentfer 	lastpid = 0;
3807af1b2bcSJan Lentfer 
3817af1b2bcSJan Lentfer 	/* convert cp_time counts to percentages */
3827af1b2bcSJan Lentfer 	for (cpu = 0; cpu < n_cpus; ++cpu) {
3837af1b2bcSJan Lentfer 		cputime_percentages(cpu_states + cpu * CPU_STATES,
3847af1b2bcSJan Lentfer 		    &cp_time[cpu], &cp_old[cpu]);
3857af1b2bcSJan Lentfer 	}
3867af1b2bcSJan Lentfer 
3877af1b2bcSJan Lentfer 	/* sum memory & swap statistics */
3887af1b2bcSJan Lentfer 	{
3897af1b2bcSJan Lentfer 		struct vmmeter vmm;
3907af1b2bcSJan Lentfer 		struct vmstats vms;
3917af1b2bcSJan Lentfer 		size_t vms_size = sizeof(vms);
3927af1b2bcSJan Lentfer 		size_t vmm_size = sizeof(vmm);
3937af1b2bcSJan Lentfer 		static unsigned int swap_delay = 0;
3947af1b2bcSJan Lentfer 		static int swapavail = 0;
3957af1b2bcSJan Lentfer 		static int swapfree = 0;
3967af1b2bcSJan Lentfer 		static int bufspace = 0;
3977af1b2bcSJan Lentfer 
3987af1b2bcSJan Lentfer 		if (sysctlbyname("vm.vmstats", &vms, &vms_size, NULL, 0))
3997af1b2bcSJan Lentfer 			err(1, "sysctlbyname: vm.vmstats");
4007af1b2bcSJan Lentfer 
4017af1b2bcSJan Lentfer 		if (sysctlbyname("vm.vmmeter", &vmm, &vmm_size, NULL, 0))
4027af1b2bcSJan Lentfer 			err(1, "sysctlbyname: vm.vmmeter");
4037af1b2bcSJan Lentfer 
4047af1b2bcSJan Lentfer 		if (kinfo_get_vfs_bufspace(&bufspace))
4057af1b2bcSJan Lentfer 			err(1, "kinfo_get_vfs_bufspace");
4067af1b2bcSJan Lentfer 
4077af1b2bcSJan Lentfer 		/* convert memory stats to Kbytes */
4087af1b2bcSJan Lentfer 		memory_stats[0] = pagetok(vms.v_active_count);
4097af1b2bcSJan Lentfer 		memory_stats[1] = pagetok(vms.v_inactive_count);
4107af1b2bcSJan Lentfer 		memory_stats[2] = pagetok(vms.v_wire_count);
4117af1b2bcSJan Lentfer 		memory_stats[3] = pagetok(vms.v_cache_count);
4127af1b2bcSJan Lentfer 		memory_stats[4] = bufspace / 1024;
4137af1b2bcSJan Lentfer 		memory_stats[5] = pagetok(vms.v_free_count);
4147af1b2bcSJan Lentfer 		memory_stats[6] = -1;
4157af1b2bcSJan Lentfer 
4167af1b2bcSJan Lentfer 		/* first interval */
4177af1b2bcSJan Lentfer 		if (swappgsin < 0) {
4187af1b2bcSJan Lentfer 			swap_stats[4] = 0;
4197af1b2bcSJan Lentfer 			swap_stats[5] = 0;
4207af1b2bcSJan Lentfer 		}
4217af1b2bcSJan Lentfer 		/* compute differences between old and new swap statistic */
4227af1b2bcSJan Lentfer 		else {
4237af1b2bcSJan Lentfer 			swap_stats[4] = pagetok(((vmm.v_swappgsin - swappgsin)));
4247af1b2bcSJan Lentfer 			swap_stats[5] = pagetok(((vmm.v_swappgsout - swappgsout)));
4257af1b2bcSJan Lentfer 		}
4267af1b2bcSJan Lentfer 
4277af1b2bcSJan Lentfer 		swappgsin = vmm.v_swappgsin;
4287af1b2bcSJan Lentfer 		swappgsout = vmm.v_swappgsout;
4297af1b2bcSJan Lentfer 
4307af1b2bcSJan Lentfer 		/* call CPU heavy swapmode() only for changes */
4317af1b2bcSJan Lentfer 		if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) {
4327af1b2bcSJan Lentfer 			swap_stats[3] = swapmode(&swapavail, &swapfree);
4337af1b2bcSJan Lentfer 			swap_stats[0] = swapavail;
4347af1b2bcSJan Lentfer 			swap_stats[1] = swapavail - swapfree;
4357af1b2bcSJan Lentfer 			swap_stats[2] = swapfree;
4367af1b2bcSJan Lentfer 		}
4377af1b2bcSJan Lentfer 		swap_delay = 1;
4387af1b2bcSJan Lentfer 		swap_stats[6] = -1;
4397af1b2bcSJan Lentfer 	}
4407af1b2bcSJan Lentfer 
4417af1b2bcSJan Lentfer 	/* set arrays and strings */
4427af1b2bcSJan Lentfer 	si->cpustates = cpu_states;
4437af1b2bcSJan Lentfer 	si->memory = memory_stats;
4447af1b2bcSJan Lentfer 	si->swap = swap_stats;
4457af1b2bcSJan Lentfer 
4467af1b2bcSJan Lentfer 
4477af1b2bcSJan Lentfer 	if (lastpid > 0) {
4487af1b2bcSJan Lentfer 		si->last_pid = lastpid;
4497af1b2bcSJan Lentfer 	} else {
4507af1b2bcSJan Lentfer 		si->last_pid = -1;
4517af1b2bcSJan Lentfer 	}
4527af1b2bcSJan Lentfer }
4537af1b2bcSJan Lentfer 
4547af1b2bcSJan Lentfer 
4557af1b2bcSJan Lentfer static struct handle handle;
4567af1b2bcSJan Lentfer 
457961f1f09SJan Lentfer caddr_t
458961f1f09SJan Lentfer get_process_info(struct system_info *si, struct process_select *sel,
4597af1b2bcSJan Lentfer     int compare_index)
4607af1b2bcSJan Lentfer {
4617af1b2bcSJan Lentfer 	int i;
4627af1b2bcSJan Lentfer 	int total_procs;
4637af1b2bcSJan Lentfer 	int active_procs;
4647af1b2bcSJan Lentfer 	struct kinfo_proc **prefp;
4657af1b2bcSJan Lentfer 	struct kinfo_proc *pp;
4667af1b2bcSJan Lentfer 
4677af1b2bcSJan Lentfer 	/* these are copied out of sel for speed */
4687af1b2bcSJan Lentfer 	int show_idle;
4697af1b2bcSJan Lentfer 	int show_system;
4707af1b2bcSJan Lentfer 	int show_uid;
4717af1b2bcSJan Lentfer 
4727af1b2bcSJan Lentfer 
4737af1b2bcSJan Lentfer 	pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
4747af1b2bcSJan Lentfer 	if (nproc > onproc)
4757af1b2bcSJan Lentfer 		pref = (struct kinfo_proc **)realloc(pref, sizeof(struct kinfo_proc *)
4767af1b2bcSJan Lentfer 		    * (onproc = nproc));
4777af1b2bcSJan Lentfer 	if (pref == NULL || pbase == NULL) {
4787af1b2bcSJan Lentfer 		(void)fprintf(stderr, "top: Out of memory.\n");
4797af1b2bcSJan Lentfer 		quit(23);
4807af1b2bcSJan Lentfer 	}
4817af1b2bcSJan Lentfer 	/* get a pointer to the states summary array */
4827af1b2bcSJan Lentfer 	si->procstates = process_states;
4837af1b2bcSJan Lentfer 
4847af1b2bcSJan Lentfer 	/* set up flags which define what we are going to select */
4857af1b2bcSJan Lentfer 	show_idle = sel->idle;
4867af1b2bcSJan Lentfer 	show_system = sel->system;
4877af1b2bcSJan Lentfer 	show_uid = sel->uid != -1;
488efde5811SJan Lentfer 	show_fullcmd = sel->fullcmd;
4897af1b2bcSJan Lentfer 
4907af1b2bcSJan Lentfer 	/* count up process states and get pointers to interesting procs */
4917af1b2bcSJan Lentfer 	total_procs = 0;
4927af1b2bcSJan Lentfer 	active_procs = 0;
4937af1b2bcSJan Lentfer 	memset((char *)process_states, 0, sizeof(process_states));
4947af1b2bcSJan Lentfer 	prefp = pref;
495961f1f09SJan Lentfer 	for (pp = pbase, i = 0; i < nproc; pp++, i++) {
4967af1b2bcSJan Lentfer 		/*
4977af1b2bcSJan Lentfer 		 * Place pointers to each valid proc structure in pref[].
4987af1b2bcSJan Lentfer 		 * Process slots that are actually in use have a non-zero
4997af1b2bcSJan Lentfer 		 * status field.  Processes with P_SYSTEM set are system
5007af1b2bcSJan Lentfer 		 * processes---these get ignored unless show_sysprocs is set.
5017af1b2bcSJan Lentfer 		 */
5027af1b2bcSJan Lentfer 		if ((show_threads && (LP(pp, pid) == -1)) ||
503961f1f09SJan Lentfer 		    (show_system || ((PP(pp, flags) & P_SYSTEM) == 0))) {
5047af1b2bcSJan Lentfer 			total_procs++;
5057af1b2bcSJan Lentfer 			process_states[(unsigned char)PP(pp, stat)]++;
5067af1b2bcSJan Lentfer 			if ((show_threads && (LP(pp, pid) == -1)) ||
5077af1b2bcSJan Lentfer 			    (show_idle || (LP(pp, pctcpu) != 0) ||
5087af1b2bcSJan Lentfer 			    (LP(pp, stat) == LSRUN)) &&
509961f1f09SJan Lentfer 			    (!show_uid || PP(pp, ruid) == (uid_t) sel->uid)) {
5107af1b2bcSJan Lentfer 				*prefp++ = pp;
5117af1b2bcSJan Lentfer 				active_procs++;
5127af1b2bcSJan Lentfer 			}
5137af1b2bcSJan Lentfer 		}
5147af1b2bcSJan Lentfer 	}
5157af1b2bcSJan Lentfer 
5167af1b2bcSJan Lentfer 	qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *),
5178b72b421SJan Lentfer 	    (int (*)(const void *, const void *))proc_compares[compare_index]);
5187af1b2bcSJan Lentfer 
5197af1b2bcSJan Lentfer 	/* remember active and total counts */
5207af1b2bcSJan Lentfer 	si->p_total = total_procs;
5217af1b2bcSJan Lentfer 	si->p_active = pref_len = active_procs;
5227af1b2bcSJan Lentfer 
5237af1b2bcSJan Lentfer 	/* pass back a handle */
5247af1b2bcSJan Lentfer 	handle.next_proc = pref;
5257af1b2bcSJan Lentfer 	handle.remaining = active_procs;
5267af1b2bcSJan Lentfer 	return ((caddr_t) & handle);
5277af1b2bcSJan Lentfer }
5287af1b2bcSJan Lentfer 
5297af1b2bcSJan Lentfer char fmt[128];			/* static area where result is built */
5307af1b2bcSJan Lentfer 
5317af1b2bcSJan Lentfer char *
5327af1b2bcSJan Lentfer format_next_process(caddr_t xhandle, char *(*get_userid) (int))
5337af1b2bcSJan Lentfer {
5347af1b2bcSJan Lentfer 	struct kinfo_proc *pp;
5357af1b2bcSJan Lentfer 	long cputime;
536*bcd4a7c1SJan Lentfer 	long ccputime;
5377af1b2bcSJan Lentfer 	double pct;
5387af1b2bcSJan Lentfer 	struct handle *hp;
5397af1b2bcSJan Lentfer 	char status[16];
5407af1b2bcSJan Lentfer 	int state;
5417af1b2bcSJan Lentfer 	int xnice;
542efde5811SJan Lentfer 	char **comm_full;
543efde5811SJan Lentfer 	char *comm;
544*bcd4a7c1SJan Lentfer 	char cputime_fmt[10], ccputime_fmt[10];
5457af1b2bcSJan Lentfer 
5467af1b2bcSJan Lentfer 	/* find and remember the next proc structure */
5477af1b2bcSJan Lentfer 	hp = (struct handle *)xhandle;
5487af1b2bcSJan Lentfer 	pp = *(hp->next_proc++);
5497af1b2bcSJan Lentfer 	hp->remaining--;
5507af1b2bcSJan Lentfer 
5517af1b2bcSJan Lentfer 	/* get the process's command name */
552efde5811SJan Lentfer 	if (show_fullcmd) {
553efde5811SJan Lentfer 		if ((comm_full = kvm_getargv(kd, pp, 0)) == NULL) {
554efde5811SJan Lentfer 			return (fmt);
5557af1b2bcSJan Lentfer 		}
556efde5811SJan Lentfer 	}
557efde5811SJan Lentfer 	else {
558efde5811SJan Lentfer 		comm = PP(pp, comm);
559efde5811SJan Lentfer 	}
560efde5811SJan Lentfer 
5617af1b2bcSJan Lentfer 	/*
5627af1b2bcSJan Lentfer 	 * Convert the process's runtime from microseconds to seconds.  This
563*bcd4a7c1SJan Lentfer 	 * time includes the interrupt time to be in compliance with ps output.
5647af1b2bcSJan Lentfer 	*/
565*bcd4a7c1SJan Lentfer 	cputime = (LP(pp, uticks) + LP(pp, sticks) + LP(pp, iticks)) / 1000000;
566*bcd4a7c1SJan Lentfer 	ccputime = cputime + PP(pp, cru).ru_stime.tv_sec + PP(pp, cru).ru_utime.tv_sec;
567*bcd4a7c1SJan Lentfer 	format_time(cputime, cputime_fmt, sizeof(cputime_fmt));
568*bcd4a7c1SJan Lentfer 	format_time(ccputime, ccputime_fmt, sizeof(ccputime_fmt));
5697af1b2bcSJan Lentfer 
5707af1b2bcSJan Lentfer 	/* calculate the base for cpu percentages */
5717af1b2bcSJan Lentfer 	pct = pctdouble(LP(pp, pctcpu));
5727af1b2bcSJan Lentfer 
5737af1b2bcSJan Lentfer 	/* generate "STATE" field */
5747af1b2bcSJan Lentfer 	switch (state = LP(pp, stat)) {
5757af1b2bcSJan Lentfer 	case LSRUN:
5767af1b2bcSJan Lentfer 		if (smpmode && LP(pp, tdflags) & TDF_RUNNING)
5777af1b2bcSJan Lentfer 			sprintf(status, "CPU%d", LP(pp, cpuid));
5787af1b2bcSJan Lentfer 		else
5797af1b2bcSJan Lentfer 			strcpy(status, "RUN");
5807af1b2bcSJan Lentfer 		break;
5817af1b2bcSJan Lentfer 	case LSSLEEP:
5827af1b2bcSJan Lentfer 		if (LP(pp, wmesg) != NULL) {
5837af1b2bcSJan Lentfer 			sprintf(status, "%.6s", LP(pp, wmesg));
5847af1b2bcSJan Lentfer 			break;
5857af1b2bcSJan Lentfer 		}
5867af1b2bcSJan Lentfer 		/* fall through */
5877af1b2bcSJan Lentfer 	default:
5887af1b2bcSJan Lentfer 
5897af1b2bcSJan Lentfer 		if (state >= 0 &&
5907af1b2bcSJan Lentfer 		    (unsigned)state < sizeof(state_abbrev) / sizeof(*state_abbrev))
5917af1b2bcSJan Lentfer 			sprintf(status, "%.6s", state_abbrev[(unsigned char)state]);
5927af1b2bcSJan Lentfer 		else
5937af1b2bcSJan Lentfer 			sprintf(status, "?%5d", state);
5947af1b2bcSJan Lentfer 		break;
5957af1b2bcSJan Lentfer 	}
5967af1b2bcSJan Lentfer 
5977af1b2bcSJan Lentfer 	if (PP(pp, stat) == SZOMB)
5987af1b2bcSJan Lentfer 		strcpy(status, "ZOMB");
5997af1b2bcSJan Lentfer 
6007af1b2bcSJan Lentfer 	/*
601961f1f09SJan Lentfer 	 * idle time 0 - 31 -> nice value +21 - +52 normal time      -> nice
602961f1f09SJan Lentfer 	 * value -20 - +20 real time 0 - 31 -> nice value -52 - -21 thread
603961f1f09SJan Lentfer 	 * 0 - 31 -> nice value -53 -
6047af1b2bcSJan Lentfer 	 */
6057af1b2bcSJan Lentfer 	switch (LP(pp, rtprio.type)) {
6067af1b2bcSJan Lentfer 	case RTP_PRIO_REALTIME:
6077af1b2bcSJan Lentfer 		xnice = PRIO_MIN - 1 - RTP_PRIO_MAX + LP(pp, rtprio.prio);
6087af1b2bcSJan Lentfer 		break;
6097af1b2bcSJan Lentfer 	case RTP_PRIO_IDLE:
6107af1b2bcSJan Lentfer 		xnice = PRIO_MAX + 1 + LP(pp, rtprio.prio);
6117af1b2bcSJan Lentfer 		break;
6127af1b2bcSJan Lentfer 	case RTP_PRIO_THREAD:
6137af1b2bcSJan Lentfer 		xnice = PRIO_MIN - 1 - RTP_PRIO_MAX - LP(pp, rtprio.prio);
6147af1b2bcSJan Lentfer 		break;
6157af1b2bcSJan Lentfer 	default:
6167af1b2bcSJan Lentfer 		xnice = PP(pp, nice);
6177af1b2bcSJan Lentfer 		break;
6187af1b2bcSJan Lentfer 	}
6197af1b2bcSJan Lentfer 
6207af1b2bcSJan Lentfer 	/* format this entry */
6217af1b2bcSJan Lentfer 	snprintf(fmt, sizeof(fmt),
6227af1b2bcSJan Lentfer 	    smpmode ? smp_Proc_format : up_Proc_format,
6237af1b2bcSJan Lentfer 	    (int)PP(pp, pid),
6247af1b2bcSJan Lentfer 	    namelength, namelength,
6257af1b2bcSJan Lentfer 	    get_userid(PP(pp, ruid)),
6267af1b2bcSJan Lentfer 	    (int)((show_threads && (LP(pp, pid) == -1)) ?
6277af1b2bcSJan Lentfer 	    LP(pp, tdprio) : LP(pp, prio)),
6287af1b2bcSJan Lentfer 	    (int)xnice,
6297af1b2bcSJan Lentfer 	    format_k(PROCSIZE(pp)),
6307af1b2bcSJan Lentfer 	    format_k(pagetok(VP(pp, rssize))),
6317af1b2bcSJan Lentfer 	    status,
6327af1b2bcSJan Lentfer 	    (int)(smpmode ? LP(pp, cpuid) : 0),
633*bcd4a7c1SJan Lentfer 	    cputime_fmt,
634*bcd4a7c1SJan Lentfer 	    ccputime_fmt,
6357af1b2bcSJan Lentfer 	    100.0 * pct,
6367af1b2bcSJan Lentfer 	    cmdlength,
637efde5811SJan Lentfer 	    show_fullcmd ? *comm_full : comm);
6387af1b2bcSJan Lentfer 
6397af1b2bcSJan Lentfer 	/* return the result */
6407af1b2bcSJan Lentfer 	return (fmt);
6417af1b2bcSJan Lentfer }
6427af1b2bcSJan Lentfer 
6437af1b2bcSJan Lentfer /* comparison routines for qsort */
6447af1b2bcSJan Lentfer 
6457af1b2bcSJan Lentfer /*
6467af1b2bcSJan Lentfer  *  proc_compare - comparison function for "qsort"
6477af1b2bcSJan Lentfer  *	Compares the resource consumption of two processes using five
6487af1b2bcSJan Lentfer  *  	distinct keys.  The keys (in descending order of importance) are:
6497af1b2bcSJan Lentfer  *  	percent cpu, cpu ticks, state, resident set size, total virtual
6507af1b2bcSJan Lentfer  *  	memory usage.  The process states are ordered as follows (from least
6517af1b2bcSJan Lentfer  *  	to most important):  WAIT, zombie, sleep, stop, start, run.  The
6527af1b2bcSJan Lentfer  *  	array declaration below maps a process state index into a number
6537af1b2bcSJan Lentfer  *  	that reflects this ordering.
6547af1b2bcSJan Lentfer  */
6557af1b2bcSJan Lentfer 
6567af1b2bcSJan Lentfer static unsigned char sorted_state[] =
6577af1b2bcSJan Lentfer {
6587af1b2bcSJan Lentfer 	0,			/* not used		 */
6597af1b2bcSJan Lentfer 	3,			/* sleep		 */
6607af1b2bcSJan Lentfer 	1,			/* ABANDONED (WAIT)	 */
6617af1b2bcSJan Lentfer 	6,			/* run			 */
6627af1b2bcSJan Lentfer 	5,			/* start		 */
6637af1b2bcSJan Lentfer 	2,			/* zombie		 */
6647af1b2bcSJan Lentfer 	4			/* stop			 */
6657af1b2bcSJan Lentfer };
6667af1b2bcSJan Lentfer 
6677af1b2bcSJan Lentfer 
6687af1b2bcSJan Lentfer #define ORDERKEY_PCTCPU \
6697af1b2bcSJan Lentfer   if (lresult = (long) LP(p2, pctcpu) - (long) LP(p1, pctcpu), \
6707af1b2bcSJan Lentfer      (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
6717af1b2bcSJan Lentfer 
672*bcd4a7c1SJan Lentfer #define CPTICKS(p)	(LP(p, uticks) + LP(p, sticks) + LP(p, iticks))
6737af1b2bcSJan Lentfer 
6747af1b2bcSJan Lentfer #define ORDERKEY_CPTICKS \
6757af1b2bcSJan Lentfer   if ((result = CPTICKS(p2) > CPTICKS(p1) ? 1 : \
6767af1b2bcSJan Lentfer 		CPTICKS(p2) < CPTICKS(p1) ? -1 : 0) == 0)
6777af1b2bcSJan Lentfer 
678*bcd4a7c1SJan Lentfer #define CTIME(p)	(((LP(p, uticks) + LP(p, sticks) + LP(p, iticks))/1000000) + \
679*bcd4a7c1SJan Lentfer   PP(p, cru).ru_stime.tv_sec + PP(p, cru).ru_utime.tv_sec)
680*bcd4a7c1SJan Lentfer 
681*bcd4a7c1SJan Lentfer #define ORDERKEY_CTIME \
682*bcd4a7c1SJan Lentfer    if ((result = CTIME(p2) > CTIME(p1) ? 1 : \
683*bcd4a7c1SJan Lentfer 		CTIME(p2) < CTIME(p1) ? -1 : 0) == 0)
684*bcd4a7c1SJan Lentfer 
6857af1b2bcSJan Lentfer #define ORDERKEY_STATE \
6867af1b2bcSJan Lentfer   if ((result = sorted_state[(unsigned char) PP(p2, stat)] - \
6877af1b2bcSJan Lentfer                 sorted_state[(unsigned char) PP(p1, stat)]) == 0)
6887af1b2bcSJan Lentfer 
6897af1b2bcSJan Lentfer #define ORDERKEY_PRIO \
6907af1b2bcSJan Lentfer   if ((result = LP(p2, prio) - LP(p1, prio)) == 0)
6917af1b2bcSJan Lentfer 
6927af1b2bcSJan Lentfer #define ORDERKEY_KTHREADS \
6937af1b2bcSJan Lentfer   if ((result = (LP(p1, pid) == 0) - (LP(p2, pid) == 0)) == 0)
6947af1b2bcSJan Lentfer 
6957af1b2bcSJan Lentfer #define ORDERKEY_KTHREADS_PRIO \
6967af1b2bcSJan Lentfer   if ((result = LP(p2, tdprio) - LP(p1, tdprio)) == 0)
6977af1b2bcSJan Lentfer 
6987af1b2bcSJan Lentfer #define ORDERKEY_RSSIZE \
6997af1b2bcSJan Lentfer   if ((result = VP(p2, rssize) - VP(p1, rssize)) == 0)
7007af1b2bcSJan Lentfer 
7017af1b2bcSJan Lentfer #define ORDERKEY_MEM \
7027af1b2bcSJan Lentfer   if ( (result = PROCSIZE(p2) - PROCSIZE(p1)) == 0 )
7037af1b2bcSJan Lentfer 
7048b72b421SJan Lentfer #define ORDERKEY_PID \
7058b72b421SJan Lentfer   if ( (result = PP(p1, pid) - PP(p2, pid)) == 0)
7068b72b421SJan Lentfer 
7077af1b2bcSJan Lentfer /* compare_cpu - the comparison function for sorting by cpu percentage */
7087af1b2bcSJan Lentfer 
7097af1b2bcSJan Lentfer int
7108b72b421SJan Lentfer proc_compare(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
7117af1b2bcSJan Lentfer {
7128b72b421SJan Lentfer 	struct kinfo_proc *p1;
7138b72b421SJan Lentfer 	struct kinfo_proc *p2;
7147af1b2bcSJan Lentfer 	int result;
7157af1b2bcSJan Lentfer 	pctcpu lresult;
7167af1b2bcSJan Lentfer 
7177af1b2bcSJan Lentfer 	/* remove one level of indirection */
7188b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
7198b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
7207af1b2bcSJan Lentfer 
7217af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
7227af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
7237af1b2bcSJan Lentfer 	ORDERKEY_STATE
7247af1b2bcSJan Lentfer 	ORDERKEY_PRIO
7257af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
7267af1b2bcSJan Lentfer 	ORDERKEY_MEM
7277af1b2bcSJan Lentfer 	{}
7287af1b2bcSJan Lentfer 
7297af1b2bcSJan Lentfer 	return (result);
7307af1b2bcSJan Lentfer }
7317af1b2bcSJan Lentfer 
7327af1b2bcSJan Lentfer /* compare_size - the comparison function for sorting by total memory usage */
7337af1b2bcSJan Lentfer 
7347af1b2bcSJan Lentfer int
7358b72b421SJan Lentfer compare_size(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
7367af1b2bcSJan Lentfer {
7377af1b2bcSJan Lentfer 	struct kinfo_proc *p1;
7387af1b2bcSJan Lentfer 	struct kinfo_proc *p2;
7397af1b2bcSJan Lentfer 	int result;
7407af1b2bcSJan Lentfer 	pctcpu lresult;
7417af1b2bcSJan Lentfer 
7427af1b2bcSJan Lentfer 	/* remove one level of indirection */
7438b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
7448b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
7457af1b2bcSJan Lentfer 
7467af1b2bcSJan Lentfer 	ORDERKEY_MEM
7477af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
7487af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
7497af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
7507af1b2bcSJan Lentfer 	ORDERKEY_STATE
7517af1b2bcSJan Lentfer 	ORDERKEY_PRIO
7527af1b2bcSJan Lentfer 	{}
7537af1b2bcSJan Lentfer 
7547af1b2bcSJan Lentfer 	return (result);
7557af1b2bcSJan Lentfer }
7567af1b2bcSJan Lentfer 
7577af1b2bcSJan Lentfer /* compare_res - the comparison function for sorting by resident set size */
7587af1b2bcSJan Lentfer 
7597af1b2bcSJan Lentfer int
7608b72b421SJan Lentfer compare_res(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
7617af1b2bcSJan Lentfer {
7627af1b2bcSJan Lentfer 	struct kinfo_proc *p1;
7637af1b2bcSJan Lentfer 	struct kinfo_proc *p2;
7647af1b2bcSJan Lentfer 	int result;
7657af1b2bcSJan Lentfer 	pctcpu lresult;
7667af1b2bcSJan Lentfer 
7677af1b2bcSJan Lentfer 	/* remove one level of indirection */
7688b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
7698b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
7707af1b2bcSJan Lentfer 
7717af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
7727af1b2bcSJan Lentfer 	ORDERKEY_MEM
7737af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
7747af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
7757af1b2bcSJan Lentfer 	ORDERKEY_STATE
7767af1b2bcSJan Lentfer 	ORDERKEY_PRIO
7777af1b2bcSJan Lentfer 	{}
7787af1b2bcSJan Lentfer 
7797af1b2bcSJan Lentfer 	return (result);
7807af1b2bcSJan Lentfer }
7817af1b2bcSJan Lentfer 
7827af1b2bcSJan Lentfer /* compare_time - the comparison function for sorting by total cpu time */
7837af1b2bcSJan Lentfer 
7847af1b2bcSJan Lentfer int
7858b72b421SJan Lentfer compare_time(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
7867af1b2bcSJan Lentfer {
7878b72b421SJan Lentfer 	struct kinfo_proc *p1;
7888b72b421SJan Lentfer 	struct kinfo_proc *p2;
7897af1b2bcSJan Lentfer 	int result;
7907af1b2bcSJan Lentfer 	pctcpu lresult;
7917af1b2bcSJan Lentfer 
7927af1b2bcSJan Lentfer 	/* remove one level of indirection */
7938b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
7948b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
7957af1b2bcSJan Lentfer 
7967af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
7977af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
7987af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS
7997af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS_PRIO
8007af1b2bcSJan Lentfer 	ORDERKEY_STATE
8017af1b2bcSJan Lentfer 	ORDERKEY_PRIO
8027af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
8037af1b2bcSJan Lentfer 	ORDERKEY_MEM
8047af1b2bcSJan Lentfer 	{}
8057af1b2bcSJan Lentfer 
8067af1b2bcSJan Lentfer 	return (result);
8077af1b2bcSJan Lentfer }
8087af1b2bcSJan Lentfer 
809*bcd4a7c1SJan Lentfer int
810*bcd4a7c1SJan Lentfer compare_ctime(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
811*bcd4a7c1SJan Lentfer {
812*bcd4a7c1SJan Lentfer 	struct kinfo_proc *p1;
813*bcd4a7c1SJan Lentfer 	struct kinfo_proc *p2;
814*bcd4a7c1SJan Lentfer 	int result;
815*bcd4a7c1SJan Lentfer 	pctcpu lresult;
816*bcd4a7c1SJan Lentfer 
817*bcd4a7c1SJan Lentfer 	/* remove one level of indirection */
818*bcd4a7c1SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
819*bcd4a7c1SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
820*bcd4a7c1SJan Lentfer 
821*bcd4a7c1SJan Lentfer 	ORDERKEY_CTIME
822*bcd4a7c1SJan Lentfer 	ORDERKEY_PCTCPU
823*bcd4a7c1SJan Lentfer 	ORDERKEY_KTHREADS
824*bcd4a7c1SJan Lentfer 	ORDERKEY_KTHREADS_PRIO
825*bcd4a7c1SJan Lentfer 	ORDERKEY_STATE
826*bcd4a7c1SJan Lentfer 	ORDERKEY_PRIO
827*bcd4a7c1SJan Lentfer 	ORDERKEY_RSSIZE
828*bcd4a7c1SJan Lentfer 	ORDERKEY_MEM
829*bcd4a7c1SJan Lentfer 	{}
830*bcd4a7c1SJan Lentfer 
831*bcd4a7c1SJan Lentfer 	return (result);
832*bcd4a7c1SJan Lentfer }
833*bcd4a7c1SJan Lentfer 
8347af1b2bcSJan Lentfer /* compare_prio - the comparison function for sorting by cpu percentage */
8357af1b2bcSJan Lentfer 
8367af1b2bcSJan Lentfer int
8378b72b421SJan Lentfer compare_prio(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
8387af1b2bcSJan Lentfer {
8398b72b421SJan Lentfer 	struct kinfo_proc *p1;
8408b72b421SJan Lentfer 	struct kinfo_proc *p2;
8417af1b2bcSJan Lentfer 	int result;
8427af1b2bcSJan Lentfer 	pctcpu lresult;
8437af1b2bcSJan Lentfer 
8447af1b2bcSJan Lentfer 	/* remove one level of indirection */
8458b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
8468b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
8477af1b2bcSJan Lentfer 
8487af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS
8497af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS_PRIO
8507af1b2bcSJan Lentfer 	ORDERKEY_PRIO
8517af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
8527af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
8537af1b2bcSJan Lentfer 	ORDERKEY_STATE
8547af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
8557af1b2bcSJan Lentfer 	ORDERKEY_MEM
8567af1b2bcSJan Lentfer 	{}
8577af1b2bcSJan Lentfer 
8587af1b2bcSJan Lentfer 	return (result);
8597af1b2bcSJan Lentfer }
8607af1b2bcSJan Lentfer 
8617af1b2bcSJan Lentfer int
8628b72b421SJan Lentfer compare_thr(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
8637af1b2bcSJan Lentfer {
8648b72b421SJan Lentfer 	struct kinfo_proc *p1;
8658b72b421SJan Lentfer 	struct kinfo_proc *p2;
8667af1b2bcSJan Lentfer 	int result;
8677af1b2bcSJan Lentfer 	pctcpu lresult;
8687af1b2bcSJan Lentfer 
8697af1b2bcSJan Lentfer 	/* remove one level of indirection */
8708b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **)pp1;
8718b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **)pp2;
8727af1b2bcSJan Lentfer 
8737af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS
8747af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS_PRIO
8757af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
8767af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
8777af1b2bcSJan Lentfer 	ORDERKEY_STATE
8787af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
8797af1b2bcSJan Lentfer 	ORDERKEY_MEM
8807af1b2bcSJan Lentfer 	{}
8817af1b2bcSJan Lentfer 
8827af1b2bcSJan Lentfer 	return (result);
8837af1b2bcSJan Lentfer }
8847af1b2bcSJan Lentfer 
8858b72b421SJan Lentfer /* compare_pid - the comparison function for sorting by process id */
8868b72b421SJan Lentfer 
8878b72b421SJan Lentfer int
8888b72b421SJan Lentfer compare_pid(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
8898b72b421SJan Lentfer {
8908b72b421SJan Lentfer 	struct kinfo_proc *p1;
8918b72b421SJan Lentfer 	struct kinfo_proc *p2;
8928b72b421SJan Lentfer 	int result;
8938b72b421SJan Lentfer 
8948b72b421SJan Lentfer 	/* remove one level of indirection */
8958b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
8968b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
8978b72b421SJan Lentfer 
8988b72b421SJan Lentfer 	ORDERKEY_PID
8998b72b421SJan Lentfer 	;
9008b72b421SJan Lentfer 
9018b72b421SJan Lentfer 	return(result);
9028b72b421SJan Lentfer }
9038b72b421SJan Lentfer 
9047af1b2bcSJan Lentfer /*
9057af1b2bcSJan Lentfer  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
9067af1b2bcSJan Lentfer  *		the process does not exist.
9077af1b2bcSJan Lentfer  *		It is EXTREMLY IMPORTANT that this function work correctly.
9087af1b2bcSJan Lentfer  *		If top runs setuid root (as in SVR4), then this function
9097af1b2bcSJan Lentfer  *		is the only thing that stands in the way of a serious
9107af1b2bcSJan Lentfer  *		security problem.  It validates requests for the "kill"
9117af1b2bcSJan Lentfer  *		and "renice" commands.
9127af1b2bcSJan Lentfer  */
9137af1b2bcSJan Lentfer 
9147af1b2bcSJan Lentfer int
9157af1b2bcSJan Lentfer proc_owner(int pid)
9167af1b2bcSJan Lentfer {
9177af1b2bcSJan Lentfer 	int xcnt;
9187af1b2bcSJan Lentfer 	struct kinfo_proc **prefp;
9197af1b2bcSJan Lentfer 	struct kinfo_proc *pp;
9207af1b2bcSJan Lentfer 
9217af1b2bcSJan Lentfer 	prefp = pref;
9227af1b2bcSJan Lentfer 	xcnt = pref_len;
923961f1f09SJan Lentfer 	while (--xcnt >= 0) {
9247af1b2bcSJan Lentfer 		pp = *prefp++;
925961f1f09SJan Lentfer 		if (PP(pp, pid) == (pid_t) pid) {
9267af1b2bcSJan Lentfer 			return ((int)PP(pp, ruid));
9277af1b2bcSJan Lentfer 		}
9287af1b2bcSJan Lentfer 	}
9297af1b2bcSJan Lentfer 	return (-1);
9307af1b2bcSJan Lentfer }
9317af1b2bcSJan Lentfer 
9327af1b2bcSJan Lentfer 
9337af1b2bcSJan Lentfer /*
9347af1b2bcSJan Lentfer  * swapmode is based on a program called swapinfo written
9357af1b2bcSJan Lentfer  * by Kevin Lahey <kml@rokkaku.atl.ga.us>.
9367af1b2bcSJan Lentfer  */
9377af1b2bcSJan Lentfer int
9387af1b2bcSJan Lentfer swapmode(int *retavail, int *retfree)
9397af1b2bcSJan Lentfer {
9407af1b2bcSJan Lentfer 	int n;
9417af1b2bcSJan Lentfer 	int pagesize = getpagesize();
9427af1b2bcSJan Lentfer 	struct kvm_swap swapary[1];
9437af1b2bcSJan Lentfer 
9447af1b2bcSJan Lentfer 	*retavail = 0;
9457af1b2bcSJan Lentfer 	*retfree = 0;
9467af1b2bcSJan Lentfer 
9477af1b2bcSJan Lentfer #define CONVERT(v)	((quad_t)(v) * pagesize / 1024)
9487af1b2bcSJan Lentfer 
9497af1b2bcSJan Lentfer 	n = kvm_getswapinfo(kd, swapary, 1, 0);
9507af1b2bcSJan Lentfer 	if (n < 0 || swapary[0].ksw_total == 0)
9517af1b2bcSJan Lentfer 		return (0);
9527af1b2bcSJan Lentfer 
9537af1b2bcSJan Lentfer 	*retavail = CONVERT(swapary[0].ksw_total);
9547af1b2bcSJan Lentfer 	*retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);
9557af1b2bcSJan Lentfer 
9567af1b2bcSJan Lentfer 	n = (int)((double)swapary[0].ksw_used * 100.0 /
9577af1b2bcSJan Lentfer 	    (double)swapary[0].ksw_total);
9587af1b2bcSJan Lentfer 	return (n);
9597af1b2bcSJan Lentfer }
960