xref: /dragonfly/usr.bin/top/m_dragonfly.c (revision 3583bbb4)
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 
26e0ecab34SMatthew Dillon #include <sys/user.h>
277af1b2bcSJan Lentfer #include <sys/types.h>
28e0ecab34SMatthew Dillon #include <sys/time.h>
297af1b2bcSJan Lentfer #include <sys/signal.h>
307af1b2bcSJan Lentfer #include <sys/param.h>
317af1b2bcSJan Lentfer 
327af1b2bcSJan Lentfer #include "os.h"
337af1b2bcSJan Lentfer #include <err.h>
347af1b2bcSJan Lentfer #include <kvm.h>
357af1b2bcSJan Lentfer #include <stdio.h>
367af1b2bcSJan Lentfer #include <unistd.h>
377af1b2bcSJan Lentfer #include <math.h>
387af1b2bcSJan Lentfer #include <pwd.h>
397af1b2bcSJan Lentfer #include <sys/errno.h>
407af1b2bcSJan Lentfer #include <sys/sysctl.h>
417af1b2bcSJan Lentfer #include <sys/file.h>
427af1b2bcSJan Lentfer #include <sys/vmmeter.h>
437af1b2bcSJan Lentfer #include <sys/resource.h>
447af1b2bcSJan Lentfer #include <sys/rtprio.h>
457af1b2bcSJan Lentfer 
467af1b2bcSJan Lentfer /* Swap */
477af1b2bcSJan Lentfer #include <stdlib.h>
487af1b2bcSJan Lentfer #include <stdio.h>
497af1b2bcSJan Lentfer #include <sys/conf.h>
507af1b2bcSJan Lentfer 
517af1b2bcSJan Lentfer #include <osreldate.h>		/* for changes in kernel structures */
527af1b2bcSJan Lentfer 
537af1b2bcSJan Lentfer #include <sys/kinfo.h>
547af1b2bcSJan Lentfer #include <kinfo.h>
557af1b2bcSJan Lentfer #include "top.h"
567af1b2bcSJan Lentfer #include "display.h"
577af1b2bcSJan Lentfer #include "machine.h"
587af1b2bcSJan Lentfer #include "screen.h"
597af1b2bcSJan Lentfer #include "utils.h"
607af1b2bcSJan Lentfer 
617af1b2bcSJan Lentfer int swapmode(int *retavail, int *retfree);
627af1b2bcSJan Lentfer static int smpmode;
637af1b2bcSJan Lentfer static int namelength;
647af1b2bcSJan Lentfer static int cmdlength;
65efde5811SJan Lentfer static int show_fullcmd;
667af1b2bcSJan Lentfer 
677af1b2bcSJan Lentfer int n_cpus = 0;
687af1b2bcSJan Lentfer 
697af1b2bcSJan Lentfer /*
70961f1f09SJan Lentfer  * needs to be a global symbol, so wrapper can be modified accordingly.
717af1b2bcSJan Lentfer  */
727af1b2bcSJan Lentfer static int show_threads = 0;
737af1b2bcSJan Lentfer 
747af1b2bcSJan Lentfer /* get_process_info passes back a handle.  This is what it looks like: */
757af1b2bcSJan Lentfer 
76961f1f09SJan Lentfer struct handle {
777af1b2bcSJan Lentfer 	struct kinfo_proc **next_proc;	/* points to next valid proc pointer */
787af1b2bcSJan Lentfer 	int remaining;		/* number of pointers remaining */
797af1b2bcSJan Lentfer };
807af1b2bcSJan Lentfer 
817af1b2bcSJan Lentfer /* declarations for load_avg */
827af1b2bcSJan Lentfer #include "loadavg.h"
837af1b2bcSJan Lentfer 
847af1b2bcSJan Lentfer #define PP(pp, field) ((pp)->kp_ ## field)
857af1b2bcSJan Lentfer #define LP(pp, field) ((pp)->kp_lwp.kl_ ## field)
867af1b2bcSJan Lentfer #define VP(pp, field) ((pp)->kp_vm_ ## field)
877af1b2bcSJan Lentfer 
887af1b2bcSJan Lentfer /* define what weighted cpu is.  */
897af1b2bcSJan Lentfer #define weighted_cpu(pct, pp) (PP((pp), swtime) == 0 ? 0.0 : \
907af1b2bcSJan Lentfer 			 ((pct) / (1.0 - exp(PP((pp), swtime) * logcpu))))
917af1b2bcSJan Lentfer 
927af1b2bcSJan Lentfer /* what we consider to be process size: */
937af1b2bcSJan Lentfer #define PROCSIZE(pp) (VP((pp), map_size) / 1024)
947af1b2bcSJan Lentfer 
957af1b2bcSJan Lentfer /*
967af1b2bcSJan Lentfer  * These definitions control the format of the per-process area
977af1b2bcSJan Lentfer  */
987af1b2bcSJan Lentfer 
997af1b2bcSJan Lentfer static char smp_header[] =
1009ac1ee6eSMatthew Dillon "  PID %-*.*s NICE  SIZE   PRES   STATE CPU  TIME   CTIME    CPU COMMAND";
1017af1b2bcSJan Lentfer 
1027af1b2bcSJan Lentfer #define smp_Proc_format \
1039ac1ee6eSMatthew Dillon 	"%5d %-*.*s %3d%7s %6s %7.7s %2d %6s %7s %5.2f%% %.*s"
1047af1b2bcSJan Lentfer 
1057af1b2bcSJan Lentfer static char up_header[] =
10685512f7bSMatthew Dillon "  PID %-*.*s NICE  SIZE   PRES   STATE    TIME   CTIME    CPU COMMAND";
1077af1b2bcSJan Lentfer 
1087af1b2bcSJan Lentfer #define up_Proc_format \
10985512f7bSMatthew Dillon 	"%5d %-*.*s %3d%7s %6s %7.7s%.0d %7s %7s %5.2f%% %.*s"
1107af1b2bcSJan Lentfer 
1117af1b2bcSJan Lentfer 
1127af1b2bcSJan Lentfer /* process state names for the "STATE" column of the display */
113961f1f09SJan Lentfer /*
114961f1f09SJan Lentfer  * the extra nulls in the string "run" are for adding a slash and the
115961f1f09SJan Lentfer  * processor number when needed
116961f1f09SJan Lentfer  */
1177af1b2bcSJan Lentfer 
118961f1f09SJan Lentfer const char *state_abbrev[] = {
1197af1b2bcSJan Lentfer 	"", "RUN\0\0\0", "STOP", "SLEEP",
1207af1b2bcSJan Lentfer };
1217af1b2bcSJan Lentfer 
1227af1b2bcSJan Lentfer 
1237af1b2bcSJan Lentfer static kvm_t *kd;
1247af1b2bcSJan Lentfer 
1257af1b2bcSJan Lentfer /* values that we stash away in _init and use in later routines */
1267af1b2bcSJan Lentfer 
1277af1b2bcSJan Lentfer static double logcpu;
1287af1b2bcSJan Lentfer 
1297af1b2bcSJan Lentfer static long lastpid;
1307af1b2bcSJan Lentfer static int ccpu;
1317af1b2bcSJan Lentfer 
1327af1b2bcSJan Lentfer /* these are for calculating cpu state percentages */
1337af1b2bcSJan Lentfer 
1347af1b2bcSJan Lentfer static struct kinfo_cputime *cp_time, *cp_old;
1357af1b2bcSJan Lentfer 
1367af1b2bcSJan Lentfer /* these are for detailing the process states */
1377af1b2bcSJan Lentfer 
1387af1b2bcSJan Lentfer int process_states[6];
1397af1b2bcSJan Lentfer char *procstatenames[] = {
140bc40e61dSStathis Kamperis 	" running, ", " idle, ", " active, ", " stopped, ", " zombie, ",
1417af1b2bcSJan Lentfer 	NULL
1427af1b2bcSJan Lentfer };
1437af1b2bcSJan Lentfer 
1447af1b2bcSJan Lentfer /* these are for detailing the cpu states */
1457af1b2bcSJan Lentfer #define CPU_STATES 5
1467af1b2bcSJan Lentfer int *cpu_states;
1477af1b2bcSJan Lentfer char *cpustatenames[CPU_STATES + 1] = {
1487af1b2bcSJan Lentfer 	"user", "nice", "system", "interrupt", "idle", NULL
1497af1b2bcSJan Lentfer };
1507af1b2bcSJan Lentfer 
1517af1b2bcSJan Lentfer /* these are for detailing the memory statistics */
1527af1b2bcSJan Lentfer 
1537af1b2bcSJan Lentfer long memory_stats[7];
1547af1b2bcSJan Lentfer char *memorynames[] = {
1557af1b2bcSJan Lentfer 	"K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ", "K Free",
1567af1b2bcSJan Lentfer 	NULL
1577af1b2bcSJan Lentfer };
1587af1b2bcSJan Lentfer 
1597af1b2bcSJan Lentfer long swap_stats[7];
1607af1b2bcSJan Lentfer char *swapnames[] = {
1617af1b2bcSJan Lentfer 	/* 0           1            2           3            4       5 */
1627af1b2bcSJan Lentfer 	"K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
1637af1b2bcSJan Lentfer 	NULL
1647af1b2bcSJan Lentfer };
1657af1b2bcSJan Lentfer 
1667af1b2bcSJan Lentfer 
1677af1b2bcSJan Lentfer /* these are for keeping track of the proc array */
1687af1b2bcSJan Lentfer 
1697af1b2bcSJan Lentfer static int nproc;
1707af1b2bcSJan Lentfer static int onproc = -1;
1717af1b2bcSJan Lentfer static int pref_len;
1727af1b2bcSJan Lentfer static struct kinfo_proc *pbase;
1737af1b2bcSJan Lentfer static struct kinfo_proc **pref;
1747af1b2bcSJan Lentfer 
1757af1b2bcSJan Lentfer /* these are for getting the memory statistics */
1767af1b2bcSJan Lentfer 
1777af1b2bcSJan Lentfer static int pageshift;		/* log base 2 of the pagesize */
1787af1b2bcSJan Lentfer 
1797af1b2bcSJan Lentfer /* define pagetok in terms of pageshift */
1807af1b2bcSJan Lentfer 
1817af1b2bcSJan Lentfer #define pagetok(size) ((size) << pageshift)
1827af1b2bcSJan Lentfer 
1837af1b2bcSJan Lentfer /* sorting orders. first is default */
1847af1b2bcSJan Lentfer char *ordernames[] = {
18550a55c46SMatthew Dillon   "cpu", "size", "res", "time", "pri", "thr", "pid", "ctime",  "pres", NULL
1867af1b2bcSJan Lentfer };
1877af1b2bcSJan Lentfer 
1887af1b2bcSJan Lentfer /* compare routines */
1898b72b421SJan Lentfer int proc_compare (struct kinfo_proc **, struct kinfo_proc **);
1908b72b421SJan Lentfer int compare_size (struct kinfo_proc **, struct kinfo_proc **);
1918b72b421SJan Lentfer int compare_res (struct kinfo_proc **, struct kinfo_proc **);
1928b72b421SJan Lentfer int compare_time (struct kinfo_proc **, struct kinfo_proc **);
193bcd4a7c1SJan Lentfer int compare_ctime (struct kinfo_proc **, struct kinfo_proc **);
1948b72b421SJan Lentfer int compare_prio(struct kinfo_proc **, struct kinfo_proc **);
1958b72b421SJan Lentfer int compare_thr (struct kinfo_proc **, struct kinfo_proc **);
1968b72b421SJan Lentfer int compare_pid (struct kinfo_proc **, struct kinfo_proc **);
19750a55c46SMatthew Dillon int compare_pres(struct kinfo_proc **, struct kinfo_proc **);
1987af1b2bcSJan Lentfer 
1998b72b421SJan Lentfer int (*proc_compares[]) (struct kinfo_proc **,struct kinfo_proc **) = {
2007af1b2bcSJan Lentfer 	proc_compare,
2017af1b2bcSJan Lentfer 	compare_size,
2027af1b2bcSJan Lentfer 	compare_res,
2037af1b2bcSJan Lentfer 	compare_time,
2047af1b2bcSJan Lentfer 	compare_prio,
2058b72b421SJan Lentfer 	compare_thr,
2068b72b421SJan Lentfer 	compare_pid,
207bcd4a7c1SJan Lentfer 	compare_ctime,
20850a55c46SMatthew Dillon 	compare_pres,
2097af1b2bcSJan Lentfer 	NULL
2107af1b2bcSJan Lentfer };
2117af1b2bcSJan Lentfer 
2127af1b2bcSJan Lentfer static void
2137af1b2bcSJan Lentfer cputime_percentages(int out[CPU_STATES], struct kinfo_cputime *new,
2147af1b2bcSJan Lentfer     struct kinfo_cputime *old)
2157af1b2bcSJan Lentfer {
2167af1b2bcSJan Lentfer 	struct kinfo_cputime diffs;
2177af1b2bcSJan Lentfer 	uint64_t total_change, half_total;
2187af1b2bcSJan Lentfer 
2197af1b2bcSJan Lentfer 	/* initialization */
2207af1b2bcSJan Lentfer 	total_change = 0;
2217af1b2bcSJan Lentfer 
2227af1b2bcSJan Lentfer 	diffs.cp_user = new->cp_user - old->cp_user;
2237af1b2bcSJan Lentfer 	diffs.cp_nice = new->cp_nice - old->cp_nice;
2247af1b2bcSJan Lentfer 	diffs.cp_sys = new->cp_sys - old->cp_sys;
2257af1b2bcSJan Lentfer 	diffs.cp_intr = new->cp_intr - old->cp_intr;
2267af1b2bcSJan Lentfer 	diffs.cp_idle = new->cp_idle - old->cp_idle;
2277af1b2bcSJan Lentfer 	total_change = diffs.cp_user + diffs.cp_nice + diffs.cp_sys +
2287af1b2bcSJan Lentfer 	    diffs.cp_intr + diffs.cp_idle;
2297af1b2bcSJan Lentfer 	old->cp_user = new->cp_user;
2307af1b2bcSJan Lentfer 	old->cp_nice = new->cp_nice;
2317af1b2bcSJan Lentfer 	old->cp_sys = new->cp_sys;
2327af1b2bcSJan Lentfer 	old->cp_intr = new->cp_intr;
2337af1b2bcSJan Lentfer 	old->cp_idle = new->cp_idle;
2347af1b2bcSJan Lentfer 
2357af1b2bcSJan Lentfer 	/* avoid divide by zero potential */
2367af1b2bcSJan Lentfer 	if (total_change == 0)
2377af1b2bcSJan Lentfer 		total_change = 1;
2387af1b2bcSJan Lentfer 
2397af1b2bcSJan Lentfer 	/* calculate percentages based on overall change, rounding up */
2407af1b2bcSJan Lentfer 	half_total = total_change >> 1;
2417af1b2bcSJan Lentfer 
2427af1b2bcSJan Lentfer 	out[0] = ((diffs.cp_user * 1000LL + half_total) / total_change);
2437af1b2bcSJan Lentfer 	out[1] = ((diffs.cp_nice * 1000LL + half_total) / total_change);
2447af1b2bcSJan Lentfer 	out[2] = ((diffs.cp_sys * 1000LL + half_total) / total_change);
2457af1b2bcSJan Lentfer 	out[3] = ((diffs.cp_intr * 1000LL + half_total) / total_change);
2467af1b2bcSJan Lentfer 	out[4] = ((diffs.cp_idle * 1000LL + half_total) / total_change);
2477af1b2bcSJan Lentfer }
2487af1b2bcSJan Lentfer 
2497af1b2bcSJan Lentfer int
2507af1b2bcSJan Lentfer machine_init(struct statics *statics)
2517af1b2bcSJan Lentfer {
2527af1b2bcSJan Lentfer 	int pagesize;
2537af1b2bcSJan Lentfer 	size_t modelen;
2547af1b2bcSJan Lentfer 	struct passwd *pw;
2557af1b2bcSJan Lentfer 	struct timeval boottime;
2567af1b2bcSJan Lentfer 
2577af1b2bcSJan Lentfer 	if (n_cpus < 1) {
2587af1b2bcSJan Lentfer 		if (kinfo_get_cpus(&n_cpus))
2597af1b2bcSJan Lentfer 			err(1, "kinfo_get_cpus failed");
2607af1b2bcSJan Lentfer 	}
2617af1b2bcSJan Lentfer 	/* get boot time */
2627af1b2bcSJan Lentfer 	modelen = sizeof(boottime);
2637af1b2bcSJan Lentfer 	if (sysctlbyname("kern.boottime", &boottime, &modelen, NULL, 0) == -1) {
2647af1b2bcSJan Lentfer 		/* we have no boottime to report */
2657af1b2bcSJan Lentfer 		boottime.tv_sec = -1;
2667af1b2bcSJan Lentfer 	}
2677af1b2bcSJan Lentfer 	modelen = sizeof(smpmode);
2687af1b2bcSJan Lentfer 	if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, NULL, 0) < 0 &&
2697af1b2bcSJan Lentfer 	    sysctlbyname("smp.smp_active", &smpmode, &modelen, NULL, 0) < 0) ||
2707af1b2bcSJan Lentfer 	    modelen != sizeof(smpmode))
2717af1b2bcSJan Lentfer 		smpmode = 0;
2727af1b2bcSJan Lentfer 
2737af1b2bcSJan Lentfer 	while ((pw = getpwent()) != NULL) {
2747af1b2bcSJan Lentfer 		if ((int)strlen(pw->pw_name) > namelength)
2757af1b2bcSJan Lentfer 			namelength = strlen(pw->pw_name);
2767af1b2bcSJan Lentfer 	}
2777af1b2bcSJan Lentfer 	if (namelength < 8)
2787af1b2bcSJan Lentfer 		namelength = 8;
2797af1b2bcSJan Lentfer 	if (smpmode && namelength > 13)
2807af1b2bcSJan Lentfer 		namelength = 13;
2817af1b2bcSJan Lentfer 	else if (namelength > 15)
2827af1b2bcSJan Lentfer 		namelength = 15;
2837af1b2bcSJan Lentfer 
284efde5811SJan Lentfer 	if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
2857af1b2bcSJan Lentfer 		return -1;
2867af1b2bcSJan Lentfer 
2877af1b2bcSJan Lentfer 	if (kinfo_get_sched_ccpu(&ccpu)) {
2887af1b2bcSJan Lentfer 		fprintf(stderr, "top: kinfo_get_sched_ccpu failed\n");
2897af1b2bcSJan Lentfer 		return (-1);
2907af1b2bcSJan Lentfer 	}
2917af1b2bcSJan Lentfer 	/* this is used in calculating WCPU -- calculate it ahead of time */
2927af1b2bcSJan Lentfer 	logcpu = log(loaddouble(ccpu));
2937af1b2bcSJan Lentfer 
2947af1b2bcSJan Lentfer 	pbase = NULL;
2957af1b2bcSJan Lentfer 	pref = NULL;
2967af1b2bcSJan Lentfer 	nproc = 0;
2977af1b2bcSJan Lentfer 	onproc = -1;
298961f1f09SJan Lentfer 	/*
299961f1f09SJan Lentfer 	 * get the page size with "getpagesize" and calculate pageshift from
300961f1f09SJan Lentfer 	 * it
301961f1f09SJan Lentfer 	 */
3027af1b2bcSJan Lentfer 	pagesize = getpagesize();
3037af1b2bcSJan Lentfer 	pageshift = 0;
304961f1f09SJan Lentfer 	while (pagesize > 1) {
3057af1b2bcSJan Lentfer 		pageshift++;
3067af1b2bcSJan Lentfer 		pagesize >>= 1;
3077af1b2bcSJan Lentfer 	}
3087af1b2bcSJan Lentfer 
3097af1b2bcSJan Lentfer 	/* we only need the amount of log(2)1024 for our conversion */
3107af1b2bcSJan Lentfer 	pageshift -= LOG1024;
3117af1b2bcSJan Lentfer 
3127af1b2bcSJan Lentfer 	/* fill in the statics information */
3137af1b2bcSJan Lentfer 	statics->procstate_names = procstatenames;
3147af1b2bcSJan Lentfer 	statics->cpustate_names = cpustatenames;
3157af1b2bcSJan Lentfer 	statics->memory_names = memorynames;
3167af1b2bcSJan Lentfer 	statics->boottime = boottime.tv_sec;
3177af1b2bcSJan Lentfer 	statics->swap_names = swapnames;
3187af1b2bcSJan Lentfer 	statics->order_names = ordernames;
319efde5811SJan Lentfer 	/* we need kvm descriptor in order to show full commands */
320efde5811SJan Lentfer 	statics->flags.fullcmds = kd != NULL;
3217af1b2bcSJan Lentfer 
3227af1b2bcSJan Lentfer 	/* all done! */
3237af1b2bcSJan Lentfer 	return (0);
3247af1b2bcSJan Lentfer }
3257af1b2bcSJan Lentfer 
3267af1b2bcSJan Lentfer char *
3277af1b2bcSJan Lentfer format_header(char *uname_field)
3287af1b2bcSJan Lentfer {
3297af1b2bcSJan Lentfer 	static char Header[128];
3307af1b2bcSJan Lentfer 
3317af1b2bcSJan Lentfer 	snprintf(Header, sizeof(Header), smpmode ? smp_header : up_header,
3327af1b2bcSJan Lentfer 	    namelength, namelength, uname_field);
3337af1b2bcSJan Lentfer 
3347af1b2bcSJan Lentfer 	if (screen_width <= 79)
3357af1b2bcSJan Lentfer 		cmdlength = 80;
3367af1b2bcSJan Lentfer 	else
3378b72b421SJan Lentfer 		cmdlength = screen_width;
3387af1b2bcSJan Lentfer 
3397af1b2bcSJan Lentfer 	cmdlength = cmdlength - strlen(Header) + 6;
3407af1b2bcSJan Lentfer 
3417af1b2bcSJan Lentfer 	return Header;
3427af1b2bcSJan Lentfer }
3437af1b2bcSJan Lentfer 
3447af1b2bcSJan Lentfer static int swappgsin = -1;
3457af1b2bcSJan Lentfer static int swappgsout = -1;
3467af1b2bcSJan Lentfer extern struct timeval timeout;
3477af1b2bcSJan Lentfer 
3487af1b2bcSJan Lentfer void
3497af1b2bcSJan Lentfer get_system_info(struct system_info *si)
3507af1b2bcSJan Lentfer {
3517af1b2bcSJan Lentfer 	size_t len;
3527af1b2bcSJan Lentfer 	int cpu;
3537af1b2bcSJan Lentfer 
3547af1b2bcSJan Lentfer 	if (cpu_states == NULL) {
3557af1b2bcSJan Lentfer 		cpu_states = malloc(sizeof(*cpu_states) * CPU_STATES * n_cpus);
3567af1b2bcSJan Lentfer 		if (cpu_states == NULL)
3577af1b2bcSJan Lentfer 			err(1, "malloc");
3587af1b2bcSJan Lentfer 		bzero(cpu_states, sizeof(*cpu_states) * CPU_STATES * n_cpus);
3597af1b2bcSJan Lentfer 	}
3607af1b2bcSJan Lentfer 	if (cp_time == NULL) {
3617af1b2bcSJan Lentfer 		cp_time = malloc(2 * n_cpus * sizeof(cp_time[0]));
3627af1b2bcSJan Lentfer 		if (cp_time == NULL)
3637af1b2bcSJan Lentfer 			err(1, "cp_time");
3647af1b2bcSJan Lentfer 		cp_old = cp_time + n_cpus;
3657af1b2bcSJan Lentfer 		len = n_cpus * sizeof(cp_old[0]);
3667af1b2bcSJan Lentfer 		bzero(cp_time, len);
3677af1b2bcSJan Lentfer 		if (sysctlbyname("kern.cputime", cp_old, &len, NULL, 0))
3687af1b2bcSJan Lentfer 			err(1, "kern.cputime");
3697af1b2bcSJan Lentfer 	}
3707af1b2bcSJan Lentfer 	len = n_cpus * sizeof(cp_time[0]);
3717af1b2bcSJan Lentfer 	bzero(cp_time, len);
3727af1b2bcSJan Lentfer 	if (sysctlbyname("kern.cputime", cp_time, &len, NULL, 0))
3737af1b2bcSJan Lentfer 		err(1, "kern.cputime");
3747af1b2bcSJan Lentfer 
3757af1b2bcSJan Lentfer 	getloadavg(si->load_avg, 3);
3767af1b2bcSJan Lentfer 
3777af1b2bcSJan Lentfer 	lastpid = 0;
3787af1b2bcSJan Lentfer 
3797af1b2bcSJan Lentfer 	/* convert cp_time counts to percentages */
3807af1b2bcSJan Lentfer 	for (cpu = 0; cpu < n_cpus; ++cpu) {
3817af1b2bcSJan Lentfer 		cputime_percentages(cpu_states + cpu * CPU_STATES,
3827af1b2bcSJan Lentfer 		    &cp_time[cpu], &cp_old[cpu]);
3837af1b2bcSJan Lentfer 	}
3847af1b2bcSJan Lentfer 
3857af1b2bcSJan Lentfer 	/* sum memory & swap statistics */
3867af1b2bcSJan Lentfer 	{
3877af1b2bcSJan Lentfer 		struct vmmeter vmm;
3887af1b2bcSJan Lentfer 		struct vmstats vms;
3897af1b2bcSJan Lentfer 		size_t vms_size = sizeof(vms);
3907af1b2bcSJan Lentfer 		size_t vmm_size = sizeof(vmm);
3917af1b2bcSJan Lentfer 		static unsigned int swap_delay = 0;
3927af1b2bcSJan Lentfer 		static int swapavail = 0;
3937af1b2bcSJan Lentfer 		static int swapfree = 0;
394*3583bbb4SMatthew Dillon 		static long bufspace = 0;
3957af1b2bcSJan Lentfer 
3967af1b2bcSJan Lentfer 		if (sysctlbyname("vm.vmstats", &vms, &vms_size, NULL, 0))
3977af1b2bcSJan Lentfer 			err(1, "sysctlbyname: vm.vmstats");
3987af1b2bcSJan Lentfer 
3997af1b2bcSJan Lentfer 		if (sysctlbyname("vm.vmmeter", &vmm, &vmm_size, NULL, 0))
4007af1b2bcSJan Lentfer 			err(1, "sysctlbyname: vm.vmmeter");
4017af1b2bcSJan Lentfer 
4027af1b2bcSJan Lentfer 		if (kinfo_get_vfs_bufspace(&bufspace))
4037af1b2bcSJan Lentfer 			err(1, "kinfo_get_vfs_bufspace");
4047af1b2bcSJan Lentfer 
4057af1b2bcSJan Lentfer 		/* convert memory stats to Kbytes */
4067af1b2bcSJan Lentfer 		memory_stats[0] = pagetok(vms.v_active_count);
4077af1b2bcSJan Lentfer 		memory_stats[1] = pagetok(vms.v_inactive_count);
4087af1b2bcSJan Lentfer 		memory_stats[2] = pagetok(vms.v_wire_count);
4097af1b2bcSJan Lentfer 		memory_stats[3] = pagetok(vms.v_cache_count);
4107af1b2bcSJan Lentfer 		memory_stats[4] = bufspace / 1024;
4117af1b2bcSJan Lentfer 		memory_stats[5] = pagetok(vms.v_free_count);
4127af1b2bcSJan Lentfer 		memory_stats[6] = -1;
4137af1b2bcSJan Lentfer 
4147af1b2bcSJan Lentfer 		/* first interval */
4157af1b2bcSJan Lentfer 		if (swappgsin < 0) {
4167af1b2bcSJan Lentfer 			swap_stats[4] = 0;
4177af1b2bcSJan Lentfer 			swap_stats[5] = 0;
4187af1b2bcSJan Lentfer 		}
4197af1b2bcSJan Lentfer 		/* compute differences between old and new swap statistic */
4207af1b2bcSJan Lentfer 		else {
4217af1b2bcSJan Lentfer 			swap_stats[4] = pagetok(((vmm.v_swappgsin - swappgsin)));
4227af1b2bcSJan Lentfer 			swap_stats[5] = pagetok(((vmm.v_swappgsout - swappgsout)));
4237af1b2bcSJan Lentfer 		}
4247af1b2bcSJan Lentfer 
4257af1b2bcSJan Lentfer 		swappgsin = vmm.v_swappgsin;
4267af1b2bcSJan Lentfer 		swappgsout = vmm.v_swappgsout;
4277af1b2bcSJan Lentfer 
4287af1b2bcSJan Lentfer 		/* call CPU heavy swapmode() only for changes */
4297af1b2bcSJan Lentfer 		if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) {
4307af1b2bcSJan Lentfer 			swap_stats[3] = swapmode(&swapavail, &swapfree);
4317af1b2bcSJan Lentfer 			swap_stats[0] = swapavail;
4327af1b2bcSJan Lentfer 			swap_stats[1] = swapavail - swapfree;
4337af1b2bcSJan Lentfer 			swap_stats[2] = swapfree;
4347af1b2bcSJan Lentfer 		}
4357af1b2bcSJan Lentfer 		swap_delay = 1;
4367af1b2bcSJan Lentfer 		swap_stats[6] = -1;
4377af1b2bcSJan Lentfer 	}
4387af1b2bcSJan Lentfer 
4397af1b2bcSJan Lentfer 	/* set arrays and strings */
4407af1b2bcSJan Lentfer 	si->cpustates = cpu_states;
4417af1b2bcSJan Lentfer 	si->memory = memory_stats;
4427af1b2bcSJan Lentfer 	si->swap = swap_stats;
4437af1b2bcSJan Lentfer 
4447af1b2bcSJan Lentfer 
4457af1b2bcSJan Lentfer 	if (lastpid > 0) {
4467af1b2bcSJan Lentfer 		si->last_pid = lastpid;
4477af1b2bcSJan Lentfer 	} else {
4487af1b2bcSJan Lentfer 		si->last_pid = -1;
4497af1b2bcSJan Lentfer 	}
4507af1b2bcSJan Lentfer }
4517af1b2bcSJan Lentfer 
4527af1b2bcSJan Lentfer 
4537af1b2bcSJan Lentfer static struct handle handle;
4547af1b2bcSJan Lentfer 
455961f1f09SJan Lentfer caddr_t
456961f1f09SJan Lentfer get_process_info(struct system_info *si, struct process_select *sel,
4577af1b2bcSJan Lentfer     int compare_index)
4587af1b2bcSJan Lentfer {
4597af1b2bcSJan Lentfer 	int i;
4607af1b2bcSJan Lentfer 	int total_procs;
4617af1b2bcSJan Lentfer 	int active_procs;
4627af1b2bcSJan Lentfer 	struct kinfo_proc **prefp;
4637af1b2bcSJan Lentfer 	struct kinfo_proc *pp;
4647af1b2bcSJan Lentfer 
4657af1b2bcSJan Lentfer 	/* these are copied out of sel for speed */
4667af1b2bcSJan Lentfer 	int show_idle;
4677af1b2bcSJan Lentfer 	int show_system;
4687af1b2bcSJan Lentfer 	int show_uid;
4697af1b2bcSJan Lentfer 
4707af1b2bcSJan Lentfer 
4717af1b2bcSJan Lentfer 	pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
4727af1b2bcSJan Lentfer 	if (nproc > onproc)
4737af1b2bcSJan Lentfer 		pref = (struct kinfo_proc **)realloc(pref, sizeof(struct kinfo_proc *)
4747af1b2bcSJan Lentfer 		    * (onproc = nproc));
4757af1b2bcSJan Lentfer 	if (pref == NULL || pbase == NULL) {
4767af1b2bcSJan Lentfer 		(void)fprintf(stderr, "top: Out of memory.\n");
4777af1b2bcSJan Lentfer 		quit(23);
4787af1b2bcSJan Lentfer 	}
4797af1b2bcSJan Lentfer 	/* get a pointer to the states summary array */
4807af1b2bcSJan Lentfer 	si->procstates = process_states;
4817af1b2bcSJan Lentfer 
4827af1b2bcSJan Lentfer 	/* set up flags which define what we are going to select */
4837af1b2bcSJan Lentfer 	show_idle = sel->idle;
4847af1b2bcSJan Lentfer 	show_system = sel->system;
4857af1b2bcSJan Lentfer 	show_uid = sel->uid != -1;
486efde5811SJan Lentfer 	show_fullcmd = sel->fullcmd;
4877af1b2bcSJan Lentfer 
4887af1b2bcSJan Lentfer 	/* count up process states and get pointers to interesting procs */
4897af1b2bcSJan Lentfer 	total_procs = 0;
4907af1b2bcSJan Lentfer 	active_procs = 0;
4917af1b2bcSJan Lentfer 	memset((char *)process_states, 0, sizeof(process_states));
4927af1b2bcSJan Lentfer 	prefp = pref;
493961f1f09SJan Lentfer 	for (pp = pbase, i = 0; i < nproc; pp++, i++) {
4947af1b2bcSJan Lentfer 		/*
4957af1b2bcSJan Lentfer 		 * Place pointers to each valid proc structure in pref[].
4967af1b2bcSJan Lentfer 		 * Process slots that are actually in use have a non-zero
4977af1b2bcSJan Lentfer 		 * status field.  Processes with P_SYSTEM set are system
4987af1b2bcSJan Lentfer 		 * processes---these get ignored unless show_sysprocs is set.
4997af1b2bcSJan Lentfer 		 */
5007af1b2bcSJan Lentfer 		if ((show_threads && (LP(pp, pid) == -1)) ||
501961f1f09SJan Lentfer 		    (show_system || ((PP(pp, flags) & P_SYSTEM) == 0))) {
5027af1b2bcSJan Lentfer 			total_procs++;
503bc40e61dSStathis Kamperis 			if (LP(pp, stat) == LSRUN)
504bc40e61dSStathis Kamperis 				process_states[0]++;
505bc40e61dSStathis Kamperis 			process_states[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 
529cef6b642SMatthew Dillon char fmt[MAX_COLS];		/* 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;
536bcd4a7c1SJan 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;
544bcd4a7c1SJan 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
563bcd4a7c1SJan Lentfer 	 * time includes the interrupt time to be in compliance with ps output.
5647af1b2bcSJan Lentfer 	*/
565bcd4a7c1SJan Lentfer 	cputime = (LP(pp, uticks) + LP(pp, sticks) + LP(pp, iticks)) / 1000000;
566bcd4a7c1SJan Lentfer 	ccputime = cputime + PP(pp, cru).ru_stime.tv_sec + PP(pp, cru).ru_utime.tv_sec;
567bcd4a7c1SJan Lentfer 	format_time(cputime, cputime_fmt, sizeof(cputime_fmt));
568bcd4a7c1SJan 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)xnice,
6277af1b2bcSJan Lentfer 	    format_k(PROCSIZE(pp)),
62850a55c46SMatthew Dillon 	    format_k(pagetok(VP(pp, prssize))),
6297af1b2bcSJan Lentfer 	    status,
6307af1b2bcSJan Lentfer 	    (int)(smpmode ? LP(pp, cpuid) : 0),
631bcd4a7c1SJan Lentfer 	    cputime_fmt,
632bcd4a7c1SJan Lentfer 	    ccputime_fmt,
6337af1b2bcSJan Lentfer 	    100.0 * pct,
6347af1b2bcSJan Lentfer 	    cmdlength,
635efde5811SJan Lentfer 	    show_fullcmd ? *comm_full : comm);
6367af1b2bcSJan Lentfer 
6377af1b2bcSJan Lentfer 	/* return the result */
6387af1b2bcSJan Lentfer 	return (fmt);
6397af1b2bcSJan Lentfer }
6407af1b2bcSJan Lentfer 
6417af1b2bcSJan Lentfer /* comparison routines for qsort */
6427af1b2bcSJan Lentfer 
6437af1b2bcSJan Lentfer /*
6447af1b2bcSJan Lentfer  *  proc_compare - comparison function for "qsort"
6457af1b2bcSJan Lentfer  *	Compares the resource consumption of two processes using five
6467af1b2bcSJan Lentfer  *  	distinct keys.  The keys (in descending order of importance) are:
6477af1b2bcSJan Lentfer  *  	percent cpu, cpu ticks, state, resident set size, total virtual
6487af1b2bcSJan Lentfer  *  	memory usage.  The process states are ordered as follows (from least
6497af1b2bcSJan Lentfer  *  	to most important):  WAIT, zombie, sleep, stop, start, run.  The
6507af1b2bcSJan Lentfer  *  	array declaration below maps a process state index into a number
6517af1b2bcSJan Lentfer  *  	that reflects this ordering.
6527af1b2bcSJan Lentfer  */
6537af1b2bcSJan Lentfer 
6547af1b2bcSJan Lentfer static unsigned char sorted_state[] =
6557af1b2bcSJan Lentfer {
6567af1b2bcSJan Lentfer 	0,			/* not used		 */
6577af1b2bcSJan Lentfer 	3,			/* sleep		 */
6587af1b2bcSJan Lentfer 	1,			/* ABANDONED (WAIT)	 */
6597af1b2bcSJan Lentfer 	6,			/* run			 */
6607af1b2bcSJan Lentfer 	5,			/* start		 */
6617af1b2bcSJan Lentfer 	2,			/* zombie		 */
6627af1b2bcSJan Lentfer 	4			/* stop			 */
6637af1b2bcSJan Lentfer };
6647af1b2bcSJan Lentfer 
6657af1b2bcSJan Lentfer 
6667af1b2bcSJan Lentfer #define ORDERKEY_PCTCPU \
6677af1b2bcSJan Lentfer   if (lresult = (long) LP(p2, pctcpu) - (long) LP(p1, pctcpu), \
6687af1b2bcSJan Lentfer      (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
6697af1b2bcSJan Lentfer 
670bcd4a7c1SJan Lentfer #define CPTICKS(p)	(LP(p, uticks) + LP(p, sticks) + LP(p, iticks))
6717af1b2bcSJan Lentfer 
6727af1b2bcSJan Lentfer #define ORDERKEY_CPTICKS \
6737af1b2bcSJan Lentfer   if ((result = CPTICKS(p2) > CPTICKS(p1) ? 1 : \
6747af1b2bcSJan Lentfer 		CPTICKS(p2) < CPTICKS(p1) ? -1 : 0) == 0)
6757af1b2bcSJan Lentfer 
676bcd4a7c1SJan Lentfer #define CTIME(p)	(((LP(p, uticks) + LP(p, sticks) + LP(p, iticks))/1000000) + \
677bcd4a7c1SJan Lentfer   PP(p, cru).ru_stime.tv_sec + PP(p, cru).ru_utime.tv_sec)
678bcd4a7c1SJan Lentfer 
679bcd4a7c1SJan Lentfer #define ORDERKEY_CTIME \
680bcd4a7c1SJan Lentfer    if ((result = CTIME(p2) > CTIME(p1) ? 1 : \
681bcd4a7c1SJan Lentfer 		CTIME(p2) < CTIME(p1) ? -1 : 0) == 0)
682bcd4a7c1SJan Lentfer 
6837af1b2bcSJan Lentfer #define ORDERKEY_STATE \
6847af1b2bcSJan Lentfer   if ((result = sorted_state[(unsigned char) PP(p2, stat)] - \
6857af1b2bcSJan Lentfer                 sorted_state[(unsigned char) PP(p1, stat)]) == 0)
6867af1b2bcSJan Lentfer 
6877af1b2bcSJan Lentfer #define ORDERKEY_PRIO \
6887af1b2bcSJan Lentfer   if ((result = LP(p2, prio) - LP(p1, prio)) == 0)
6897af1b2bcSJan Lentfer 
6907af1b2bcSJan Lentfer #define ORDERKEY_KTHREADS \
6917af1b2bcSJan Lentfer   if ((result = (LP(p1, pid) == 0) - (LP(p2, pid) == 0)) == 0)
6927af1b2bcSJan Lentfer 
6937af1b2bcSJan Lentfer #define ORDERKEY_KTHREADS_PRIO \
6947af1b2bcSJan Lentfer   if ((result = LP(p2, tdprio) - LP(p1, tdprio)) == 0)
6957af1b2bcSJan Lentfer 
6967af1b2bcSJan Lentfer #define ORDERKEY_RSSIZE \
6977af1b2bcSJan Lentfer   if ((result = VP(p2, rssize) - VP(p1, rssize)) == 0)
6987af1b2bcSJan Lentfer 
6997af1b2bcSJan Lentfer #define ORDERKEY_MEM \
7007af1b2bcSJan Lentfer   if ( (result = PROCSIZE(p2) - PROCSIZE(p1)) == 0 )
7017af1b2bcSJan Lentfer 
7028b72b421SJan Lentfer #define ORDERKEY_PID \
7038b72b421SJan Lentfer   if ( (result = PP(p1, pid) - PP(p2, pid)) == 0)
7048b72b421SJan Lentfer 
70550a55c46SMatthew Dillon #define ORDERKEY_PRSSIZE \
70650a55c46SMatthew Dillon   if((result = VP(p2, prssize) - VP(p1, prssize)) == 0)
70750a55c46SMatthew Dillon 
7087af1b2bcSJan Lentfer /* compare_cpu - the comparison function for sorting by cpu percentage */
7097af1b2bcSJan Lentfer 
7107af1b2bcSJan Lentfer int
7118b72b421SJan Lentfer proc_compare(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
7127af1b2bcSJan Lentfer {
7138b72b421SJan Lentfer 	struct kinfo_proc *p1;
7148b72b421SJan Lentfer 	struct kinfo_proc *p2;
7157af1b2bcSJan Lentfer 	int result;
7167af1b2bcSJan Lentfer 	pctcpu lresult;
7177af1b2bcSJan Lentfer 
7187af1b2bcSJan Lentfer 	/* remove one level of indirection */
7198b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
7208b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
7217af1b2bcSJan Lentfer 
7227af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
7237af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
7247af1b2bcSJan Lentfer 	ORDERKEY_STATE
7257af1b2bcSJan Lentfer 	ORDERKEY_PRIO
7267af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
7277af1b2bcSJan Lentfer 	ORDERKEY_MEM
7287af1b2bcSJan Lentfer 	{}
7297af1b2bcSJan Lentfer 
7307af1b2bcSJan Lentfer 	return (result);
7317af1b2bcSJan Lentfer }
7327af1b2bcSJan Lentfer 
7337af1b2bcSJan Lentfer /* compare_size - the comparison function for sorting by total memory usage */
7347af1b2bcSJan Lentfer 
7357af1b2bcSJan Lentfer int
7368b72b421SJan Lentfer compare_size(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
7377af1b2bcSJan Lentfer {
7387af1b2bcSJan Lentfer 	struct kinfo_proc *p1;
7397af1b2bcSJan Lentfer 	struct kinfo_proc *p2;
7407af1b2bcSJan Lentfer 	int result;
7417af1b2bcSJan Lentfer 	pctcpu lresult;
7427af1b2bcSJan Lentfer 
7437af1b2bcSJan Lentfer 	/* remove one level of indirection */
7448b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
7458b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
7467af1b2bcSJan Lentfer 
7477af1b2bcSJan Lentfer 	ORDERKEY_MEM
7487af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
7497af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
7507af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
7517af1b2bcSJan Lentfer 	ORDERKEY_STATE
7527af1b2bcSJan Lentfer 	ORDERKEY_PRIO
7537af1b2bcSJan Lentfer 	{}
7547af1b2bcSJan Lentfer 
7557af1b2bcSJan Lentfer 	return (result);
7567af1b2bcSJan Lentfer }
7577af1b2bcSJan Lentfer 
7587af1b2bcSJan Lentfer /* compare_res - the comparison function for sorting by resident set size */
7597af1b2bcSJan Lentfer 
7607af1b2bcSJan Lentfer int
7618b72b421SJan Lentfer compare_res(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
7627af1b2bcSJan Lentfer {
7637af1b2bcSJan Lentfer 	struct kinfo_proc *p1;
7647af1b2bcSJan Lentfer 	struct kinfo_proc *p2;
7657af1b2bcSJan Lentfer 	int result;
7667af1b2bcSJan Lentfer 	pctcpu lresult;
7677af1b2bcSJan Lentfer 
7687af1b2bcSJan Lentfer 	/* remove one level of indirection */
7698b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
7708b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
7717af1b2bcSJan Lentfer 
7727af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
7737af1b2bcSJan Lentfer 	ORDERKEY_MEM
7747af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
7757af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
7767af1b2bcSJan Lentfer 	ORDERKEY_STATE
7777af1b2bcSJan Lentfer 	ORDERKEY_PRIO
7787af1b2bcSJan Lentfer 	{}
7797af1b2bcSJan Lentfer 
7807af1b2bcSJan Lentfer 	return (result);
7817af1b2bcSJan Lentfer }
7827af1b2bcSJan Lentfer 
78350a55c46SMatthew Dillon /* compare_pres - the comparison function for sorting by proportional resident set size */
78450a55c46SMatthew Dillon 
78550a55c46SMatthew Dillon int
78650a55c46SMatthew Dillon compare_pres(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
78750a55c46SMatthew Dillon {
78850a55c46SMatthew Dillon 	struct kinfo_proc *p1;
78950a55c46SMatthew Dillon 	struct kinfo_proc *p2;
79050a55c46SMatthew Dillon 	int result;
79150a55c46SMatthew Dillon 	pctcpu lresult;
79250a55c46SMatthew Dillon 
79350a55c46SMatthew Dillon 	/* remove one level of indirection */
79450a55c46SMatthew Dillon 	p1 = *(struct kinfo_proc **) pp1;
79550a55c46SMatthew Dillon 	p2 = *(struct kinfo_proc **) pp2;
79650a55c46SMatthew Dillon 
79750a55c46SMatthew Dillon 	ORDERKEY_PRSSIZE
79850a55c46SMatthew Dillon 	ORDERKEY_RSSIZE
79950a55c46SMatthew Dillon 	ORDERKEY_MEM
80050a55c46SMatthew Dillon 	ORDERKEY_PCTCPU
80150a55c46SMatthew Dillon 	ORDERKEY_CPTICKS
80250a55c46SMatthew Dillon 	ORDERKEY_STATE
80350a55c46SMatthew Dillon 	ORDERKEY_PRIO
80450a55c46SMatthew Dillon 	{}
80550a55c46SMatthew Dillon 
80650a55c46SMatthew Dillon 	return (result);
80750a55c46SMatthew Dillon }
80850a55c46SMatthew Dillon 
8097af1b2bcSJan Lentfer /* compare_time - the comparison function for sorting by total cpu time */
8107af1b2bcSJan Lentfer 
8117af1b2bcSJan Lentfer int
8128b72b421SJan Lentfer compare_time(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
8137af1b2bcSJan Lentfer {
8148b72b421SJan Lentfer 	struct kinfo_proc *p1;
8158b72b421SJan Lentfer 	struct kinfo_proc *p2;
8167af1b2bcSJan Lentfer 	int result;
8177af1b2bcSJan Lentfer 	pctcpu lresult;
8187af1b2bcSJan Lentfer 
8197af1b2bcSJan Lentfer 	/* remove one level of indirection */
8208b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
8218b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
8227af1b2bcSJan Lentfer 
8237af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
8247af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
8257af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS
8267af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS_PRIO
8277af1b2bcSJan Lentfer 	ORDERKEY_STATE
8287af1b2bcSJan Lentfer 	ORDERKEY_PRIO
8297af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
8307af1b2bcSJan Lentfer 	ORDERKEY_MEM
8317af1b2bcSJan Lentfer 	{}
8327af1b2bcSJan Lentfer 
8337af1b2bcSJan Lentfer 	return (result);
8347af1b2bcSJan Lentfer }
8357af1b2bcSJan Lentfer 
836bcd4a7c1SJan Lentfer int
837bcd4a7c1SJan Lentfer compare_ctime(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
838bcd4a7c1SJan Lentfer {
839bcd4a7c1SJan Lentfer 	struct kinfo_proc *p1;
840bcd4a7c1SJan Lentfer 	struct kinfo_proc *p2;
841bcd4a7c1SJan Lentfer 	int result;
842bcd4a7c1SJan Lentfer 	pctcpu lresult;
843bcd4a7c1SJan Lentfer 
844bcd4a7c1SJan Lentfer 	/* remove one level of indirection */
845bcd4a7c1SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
846bcd4a7c1SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
847bcd4a7c1SJan Lentfer 
848bcd4a7c1SJan Lentfer 	ORDERKEY_CTIME
849bcd4a7c1SJan Lentfer 	ORDERKEY_PCTCPU
850bcd4a7c1SJan Lentfer 	ORDERKEY_KTHREADS
851bcd4a7c1SJan Lentfer 	ORDERKEY_KTHREADS_PRIO
852bcd4a7c1SJan Lentfer 	ORDERKEY_STATE
853bcd4a7c1SJan Lentfer 	ORDERKEY_PRIO
854bcd4a7c1SJan Lentfer 	ORDERKEY_RSSIZE
855bcd4a7c1SJan Lentfer 	ORDERKEY_MEM
856bcd4a7c1SJan Lentfer 	{}
857bcd4a7c1SJan Lentfer 
858bcd4a7c1SJan Lentfer 	return (result);
859bcd4a7c1SJan Lentfer }
860bcd4a7c1SJan Lentfer 
8617af1b2bcSJan Lentfer /* compare_prio - the comparison function for sorting by cpu percentage */
8627af1b2bcSJan Lentfer 
8637af1b2bcSJan Lentfer int
8648b72b421SJan Lentfer compare_prio(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
8657af1b2bcSJan Lentfer {
8668b72b421SJan Lentfer 	struct kinfo_proc *p1;
8678b72b421SJan Lentfer 	struct kinfo_proc *p2;
8687af1b2bcSJan Lentfer 	int result;
8697af1b2bcSJan Lentfer 	pctcpu lresult;
8707af1b2bcSJan Lentfer 
8717af1b2bcSJan Lentfer 	/* remove one level of indirection */
8728b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
8738b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
8747af1b2bcSJan Lentfer 
8757af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS
8767af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS_PRIO
8777af1b2bcSJan Lentfer 	ORDERKEY_PRIO
8787af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
8797af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
8807af1b2bcSJan Lentfer 	ORDERKEY_STATE
8817af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
8827af1b2bcSJan Lentfer 	ORDERKEY_MEM
8837af1b2bcSJan Lentfer 	{}
8847af1b2bcSJan Lentfer 
8857af1b2bcSJan Lentfer 	return (result);
8867af1b2bcSJan Lentfer }
8877af1b2bcSJan Lentfer 
8887af1b2bcSJan Lentfer int
8898b72b421SJan Lentfer compare_thr(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
8907af1b2bcSJan Lentfer {
8918b72b421SJan Lentfer 	struct kinfo_proc *p1;
8928b72b421SJan Lentfer 	struct kinfo_proc *p2;
8937af1b2bcSJan Lentfer 	int result;
8947af1b2bcSJan Lentfer 	pctcpu lresult;
8957af1b2bcSJan Lentfer 
8967af1b2bcSJan Lentfer 	/* remove one level of indirection */
8978b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **)pp1;
8988b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **)pp2;
8997af1b2bcSJan Lentfer 
9007af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS
9017af1b2bcSJan Lentfer 	ORDERKEY_KTHREADS_PRIO
9027af1b2bcSJan Lentfer 	ORDERKEY_CPTICKS
9037af1b2bcSJan Lentfer 	ORDERKEY_PCTCPU
9047af1b2bcSJan Lentfer 	ORDERKEY_STATE
9057af1b2bcSJan Lentfer 	ORDERKEY_RSSIZE
9067af1b2bcSJan Lentfer 	ORDERKEY_MEM
9077af1b2bcSJan Lentfer 	{}
9087af1b2bcSJan Lentfer 
9097af1b2bcSJan Lentfer 	return (result);
9107af1b2bcSJan Lentfer }
9117af1b2bcSJan Lentfer 
9128b72b421SJan Lentfer /* compare_pid - the comparison function for sorting by process id */
9138b72b421SJan Lentfer 
9148b72b421SJan Lentfer int
9158b72b421SJan Lentfer compare_pid(struct kinfo_proc **pp1, struct kinfo_proc **pp2)
9168b72b421SJan Lentfer {
9178b72b421SJan Lentfer 	struct kinfo_proc *p1;
9188b72b421SJan Lentfer 	struct kinfo_proc *p2;
9198b72b421SJan Lentfer 	int result;
9208b72b421SJan Lentfer 
9218b72b421SJan Lentfer 	/* remove one level of indirection */
9228b72b421SJan Lentfer 	p1 = *(struct kinfo_proc **) pp1;
9238b72b421SJan Lentfer 	p2 = *(struct kinfo_proc **) pp2;
9248b72b421SJan Lentfer 
9258b72b421SJan Lentfer 	ORDERKEY_PID
9268b72b421SJan Lentfer 	;
9278b72b421SJan Lentfer 
9288b72b421SJan Lentfer 	return(result);
9298b72b421SJan Lentfer }
9308b72b421SJan Lentfer 
9317af1b2bcSJan Lentfer /*
9327af1b2bcSJan Lentfer  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
9337af1b2bcSJan Lentfer  *		the process does not exist.
9347af1b2bcSJan Lentfer  *		It is EXTREMLY IMPORTANT that this function work correctly.
9357af1b2bcSJan Lentfer  *		If top runs setuid root (as in SVR4), then this function
9367af1b2bcSJan Lentfer  *		is the only thing that stands in the way of a serious
9377af1b2bcSJan Lentfer  *		security problem.  It validates requests for the "kill"
9387af1b2bcSJan Lentfer  *		and "renice" commands.
9397af1b2bcSJan Lentfer  */
9407af1b2bcSJan Lentfer 
9417af1b2bcSJan Lentfer int
9427af1b2bcSJan Lentfer proc_owner(int pid)
9437af1b2bcSJan Lentfer {
9447af1b2bcSJan Lentfer 	int xcnt;
9457af1b2bcSJan Lentfer 	struct kinfo_proc **prefp;
9467af1b2bcSJan Lentfer 	struct kinfo_proc *pp;
9477af1b2bcSJan Lentfer 
9487af1b2bcSJan Lentfer 	prefp = pref;
9497af1b2bcSJan Lentfer 	xcnt = pref_len;
950961f1f09SJan Lentfer 	while (--xcnt >= 0) {
9517af1b2bcSJan Lentfer 		pp = *prefp++;
952961f1f09SJan Lentfer 		if (PP(pp, pid) == (pid_t) pid) {
9537af1b2bcSJan Lentfer 			return ((int)PP(pp, ruid));
9547af1b2bcSJan Lentfer 		}
9557af1b2bcSJan Lentfer 	}
9567af1b2bcSJan Lentfer 	return (-1);
9577af1b2bcSJan Lentfer }
9587af1b2bcSJan Lentfer 
9597af1b2bcSJan Lentfer 
9607af1b2bcSJan Lentfer /*
9617af1b2bcSJan Lentfer  * swapmode is based on a program called swapinfo written
9627af1b2bcSJan Lentfer  * by Kevin Lahey <kml@rokkaku.atl.ga.us>.
9637af1b2bcSJan Lentfer  */
9647af1b2bcSJan Lentfer int
9657af1b2bcSJan Lentfer swapmode(int *retavail, int *retfree)
9667af1b2bcSJan Lentfer {
9677af1b2bcSJan Lentfer 	int n;
9687af1b2bcSJan Lentfer 	int pagesize = getpagesize();
9697af1b2bcSJan Lentfer 	struct kvm_swap swapary[1];
9707af1b2bcSJan Lentfer 
9717af1b2bcSJan Lentfer 	*retavail = 0;
9727af1b2bcSJan Lentfer 	*retfree = 0;
9737af1b2bcSJan Lentfer 
9747af1b2bcSJan Lentfer #define CONVERT(v)	((quad_t)(v) * pagesize / 1024)
9757af1b2bcSJan Lentfer 
9767af1b2bcSJan Lentfer 	n = kvm_getswapinfo(kd, swapary, 1, 0);
9777af1b2bcSJan Lentfer 	if (n < 0 || swapary[0].ksw_total == 0)
9787af1b2bcSJan Lentfer 		return (0);
9797af1b2bcSJan Lentfer 
9807af1b2bcSJan Lentfer 	*retavail = CONVERT(swapary[0].ksw_total);
9817af1b2bcSJan Lentfer 	*retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);
9827af1b2bcSJan Lentfer 
9837af1b2bcSJan Lentfer 	n = (int)((double)swapary[0].ksw_used * 100.0 /
9847af1b2bcSJan Lentfer 	    (double)swapary[0].ksw_total);
9857af1b2bcSJan Lentfer 	return (n);
9867af1b2bcSJan Lentfer }
987