xref: /minix3/external/bsd/top/dist/machine/m_netbsd.c (revision b89261ba018da33f0bd8cd05f5a1fe9e7a9c837b)
1*b89261baSDavid van Moolenbroek /*	$NetBSD: m_netbsd.c,v 1.18 2013/10/20 03:02:27 christos Exp $	*/
2*b89261baSDavid van Moolenbroek 
3*b89261baSDavid van Moolenbroek /*
4*b89261baSDavid van Moolenbroek  * top - a top users display for Unix
5*b89261baSDavid van Moolenbroek  *
6*b89261baSDavid van Moolenbroek  * SYNOPSIS:  For a NetBSD-1.5 (or later) system
7*b89261baSDavid van Moolenbroek  *
8*b89261baSDavid van Moolenbroek  * DESCRIPTION:
9*b89261baSDavid van Moolenbroek  * Originally written for BSD4.4 system by Christos Zoulas.
10*b89261baSDavid van Moolenbroek  * Based on the FreeBSD 2.0 version by Steven Wallace and Wolfram Schneider.
11*b89261baSDavid van Moolenbroek  * NetBSD-1.0 port by Arne Helme. Process ordering by Luke Mewburn.
12*b89261baSDavid van Moolenbroek  * NetBSD-1.3 port by Luke Mewburn, based on code by Matthew Green.
13*b89261baSDavid van Moolenbroek  * NetBSD-1.4/UVM port by matthew green.
14*b89261baSDavid van Moolenbroek  * NetBSD-1.5 port by Simon Burge.
15*b89261baSDavid van Moolenbroek  * NetBSD-1.6/UBC port by Tomas Svensson.
16*b89261baSDavid van Moolenbroek  * -
17*b89261baSDavid van Moolenbroek  * This is the machine-dependent module for NetBSD-1.5 and later
18*b89261baSDavid van Moolenbroek  * works for:
19*b89261baSDavid van Moolenbroek  *	NetBSD-1.6ZC
20*b89261baSDavid van Moolenbroek  * and should work for:
21*b89261baSDavid van Moolenbroek  *	NetBSD-2.0	(when released)
22*b89261baSDavid van Moolenbroek  * -
23*b89261baSDavid van Moolenbroek  * top does not need to be installed setuid or setgid with this module.
24*b89261baSDavid van Moolenbroek  *
25*b89261baSDavid van Moolenbroek  * LIBS: -lkvm
26*b89261baSDavid van Moolenbroek  *
27*b89261baSDavid van Moolenbroek  * CFLAGS: -DHAVE_GETOPT -DORDER -DHAVE_STRERROR
28*b89261baSDavid van Moolenbroek  *
29*b89261baSDavid van Moolenbroek  * AUTHORS:	Christos Zoulas <christos@ee.cornell.edu>
30*b89261baSDavid van Moolenbroek  *		Steven Wallace <swallace@freebsd.org>
31*b89261baSDavid van Moolenbroek  *		Wolfram Schneider <wosch@cs.tu-berlin.de>
32*b89261baSDavid van Moolenbroek  *		Arne Helme <arne@acm.org>
33*b89261baSDavid van Moolenbroek  *		Luke Mewburn <lukem@NetBSD.org>
34*b89261baSDavid van Moolenbroek  *		matthew green <mrg@eterna.com.au>
35*b89261baSDavid van Moolenbroek  *		Simon Burge <simonb@NetBSD.org>
36*b89261baSDavid van Moolenbroek  *		Tomas Svensson <ts@unix1.net>
37*b89261baSDavid van Moolenbroek  *		Andrew Doran <ad@NetBSD.org>
38*b89261baSDavid van Moolenbroek  *
39*b89261baSDavid van Moolenbroek  *
40*b89261baSDavid van Moolenbroek  * $Id: m_netbsd.c,v 1.18 2013/10/20 03:02:27 christos Exp $
41*b89261baSDavid van Moolenbroek  */
42*b89261baSDavid van Moolenbroek #include <sys/cdefs.h>
43*b89261baSDavid van Moolenbroek 
44*b89261baSDavid van Moolenbroek #ifndef lint
45*b89261baSDavid van Moolenbroek __RCSID("$NetBSD: m_netbsd.c,v 1.18 2013/10/20 03:02:27 christos Exp $");
46*b89261baSDavid van Moolenbroek #endif
47*b89261baSDavid van Moolenbroek 
48*b89261baSDavid van Moolenbroek #include <sys/param.h>
49*b89261baSDavid van Moolenbroek #include <sys/resource.h>
50*b89261baSDavid van Moolenbroek #include <sys/sysctl.h>
51*b89261baSDavid van Moolenbroek #include <sys/sched.h>
52*b89261baSDavid van Moolenbroek #include <sys/swap.h>
53*b89261baSDavid van Moolenbroek 
54*b89261baSDavid van Moolenbroek #include <uvm/uvm_extern.h>
55*b89261baSDavid van Moolenbroek 
56*b89261baSDavid van Moolenbroek #include <err.h>
57*b89261baSDavid van Moolenbroek #include <errno.h>
58*b89261baSDavid van Moolenbroek #include <kvm.h>
59*b89261baSDavid van Moolenbroek #include <math.h>
60*b89261baSDavid van Moolenbroek #include <nlist.h>
61*b89261baSDavid van Moolenbroek #include <stdio.h>
62*b89261baSDavid van Moolenbroek #include <stdlib.h>
63*b89261baSDavid van Moolenbroek #include <string.h>
64*b89261baSDavid van Moolenbroek #include <unistd.h>
65*b89261baSDavid van Moolenbroek 
66*b89261baSDavid van Moolenbroek #include "os.h"
67*b89261baSDavid van Moolenbroek #include "top.h"
68*b89261baSDavid van Moolenbroek #include "machine.h"
69*b89261baSDavid van Moolenbroek #include "utils.h"
70*b89261baSDavid van Moolenbroek #include "display.h"
71*b89261baSDavid van Moolenbroek #include "loadavg.h"
72*b89261baSDavid van Moolenbroek #include "username.h"
73*b89261baSDavid van Moolenbroek 
74*b89261baSDavid van Moolenbroek static void percentages64(int, int *, u_int64_t *, u_int64_t *,
75*b89261baSDavid van Moolenbroek     u_int64_t *);
76*b89261baSDavid van Moolenbroek 
77*b89261baSDavid van Moolenbroek /* get_process_info passes back a handle.  This is what it looks like: */
78*b89261baSDavid van Moolenbroek 
79*b89261baSDavid van Moolenbroek struct handle {
80*b89261baSDavid van Moolenbroek 	struct process_select *sel;
81*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 **next_proc;	/* points to next valid proc pointer */
82*b89261baSDavid van Moolenbroek 	int remaining;		/* number of pointers remaining */
83*b89261baSDavid van Moolenbroek };
84*b89261baSDavid van Moolenbroek 
85*b89261baSDavid van Moolenbroek /* define what weighted CPU is. */
86*b89261baSDavid van Moolenbroek #define weighted_cpu(pfx, pct, pp) ((pp)->pfx ## swtime == 0 ? 0.0 : \
87*b89261baSDavid van Moolenbroek 			 ((pct) / (1.0 - exp((pp)->pfx ## swtime * logcpu))))
88*b89261baSDavid van Moolenbroek 
89*b89261baSDavid van Moolenbroek /* what we consider to be process size: */
90*b89261baSDavid van Moolenbroek /* NetBSD introduced p_vm_msize with RLIMIT_AS */
91*b89261baSDavid van Moolenbroek #ifdef RLIMIT_AS
92*b89261baSDavid van Moolenbroek #define PROCSIZE(pp) \
93*b89261baSDavid van Moolenbroek     ((pp)->p_vm_msize)
94*b89261baSDavid van Moolenbroek #else
95*b89261baSDavid van Moolenbroek #define PROCSIZE(pp) \
96*b89261baSDavid van Moolenbroek     ((pp)->p_vm_tsize + (pp)->p_vm_dsize + (pp)->p_vm_ssize)
97*b89261baSDavid van Moolenbroek #endif
98*b89261baSDavid van Moolenbroek 
99*b89261baSDavid van Moolenbroek 
100*b89261baSDavid van Moolenbroek /*
101*b89261baSDavid van Moolenbroek  * These definitions control the format of the per-process area
102*b89261baSDavid van Moolenbroek  */
103*b89261baSDavid van Moolenbroek 
104*b89261baSDavid van Moolenbroek static char Proc_header[] =
105*b89261baSDavid van Moolenbroek   "  PID X        PRI NICE   SIZE   RES STATE      TIME   WCPU    CPU COMMAND";
106*b89261baSDavid van Moolenbroek /* 0123456   -- field to fill in starts at header+6 */
107*b89261baSDavid van Moolenbroek #define PROC_UNAME_START 6
108*b89261baSDavid van Moolenbroek #define Proc_format \
109*b89261baSDavid van Moolenbroek 	"%5d %-8.8s %3d %4d%7s %5s %-8.8s%7s %5.*f%% %5.*f%% %s"
110*b89261baSDavid van Moolenbroek 
111*b89261baSDavid van Moolenbroek static char Thread_header[] =
112*b89261baSDavid van Moolenbroek   "  PID   LID X        PRI STATE      TIME   WCPU    CPU NAME      COMMAND";
113*b89261baSDavid van Moolenbroek /* 0123456   -- field to fill in starts at header+6 */
114*b89261baSDavid van Moolenbroek #define THREAD_UNAME_START 12
115*b89261baSDavid van Moolenbroek #define Thread_format \
116*b89261baSDavid van Moolenbroek         "%5d %5d %-8.8s %3d %-8.8s%7s %5.2f%% %5.2f%% %-9.9s %s"
117*b89261baSDavid van Moolenbroek 
118*b89261baSDavid van Moolenbroek /*
119*b89261baSDavid van Moolenbroek  * Process state names for the "STATE" column of the display.
120*b89261baSDavid van Moolenbroek  */
121*b89261baSDavid van Moolenbroek 
122*b89261baSDavid van Moolenbroek const char *state_abbrev[] = {
123*b89261baSDavid van Moolenbroek 	"", "IDLE", "RUN", "SLEEP", "STOP", "ZOMB", "DEAD", "CPU"
124*b89261baSDavid van Moolenbroek };
125*b89261baSDavid van Moolenbroek 
126*b89261baSDavid van Moolenbroek static kvm_t *kd;
127*b89261baSDavid van Moolenbroek 
128*b89261baSDavid van Moolenbroek static char *(*userprint)(int);
129*b89261baSDavid van Moolenbroek 
130*b89261baSDavid van Moolenbroek /* these are retrieved from the kernel in _init */
131*b89261baSDavid van Moolenbroek 
132*b89261baSDavid van Moolenbroek static double logcpu;
133*b89261baSDavid van Moolenbroek static int hz;
134*b89261baSDavid van Moolenbroek static int ccpu;
135*b89261baSDavid van Moolenbroek 
136*b89261baSDavid van Moolenbroek /* these are for calculating CPU state percentages */
137*b89261baSDavid van Moolenbroek 
138*b89261baSDavid van Moolenbroek static int ncpu = 0;
139*b89261baSDavid van Moolenbroek static u_int64_t *cp_time;
140*b89261baSDavid van Moolenbroek static u_int64_t *cp_old;
141*b89261baSDavid van Moolenbroek static u_int64_t *cp_diff;
142*b89261baSDavid van Moolenbroek 
143*b89261baSDavid van Moolenbroek /* these are for detailing the process states */
144*b89261baSDavid van Moolenbroek 
145*b89261baSDavid van Moolenbroek int process_states[8];
146*b89261baSDavid van Moolenbroek const char *procstatenames[] = {
147*b89261baSDavid van Moolenbroek 	"", " idle, ", " runnable, ", " sleeping, ", " stopped, ",
148*b89261baSDavid van Moolenbroek 	" zombie, ", " dead, ", " on CPU, ",
149*b89261baSDavid van Moolenbroek 	NULL
150*b89261baSDavid van Moolenbroek };
151*b89261baSDavid van Moolenbroek 
152*b89261baSDavid van Moolenbroek /* these are for detailing the CPU states */
153*b89261baSDavid van Moolenbroek 
154*b89261baSDavid van Moolenbroek int *cpu_states;
155*b89261baSDavid van Moolenbroek const char *cpustatenames[] = {
156*b89261baSDavid van Moolenbroek #ifndef __minix
157*b89261baSDavid van Moolenbroek 	"user", "nice", "system", "interrupt", "idle", NULL
158*b89261baSDavid van Moolenbroek #else /* __minix */
159*b89261baSDavid van Moolenbroek 	"user", "nice", "system", "kernel", "idle", NULL
160*b89261baSDavid van Moolenbroek #endif /* __minix */
161*b89261baSDavid van Moolenbroek };
162*b89261baSDavid van Moolenbroek 
163*b89261baSDavid van Moolenbroek /* these are for detailing the memory statistics */
164*b89261baSDavid van Moolenbroek 
165*b89261baSDavid van Moolenbroek long memory_stats[7];
166*b89261baSDavid van Moolenbroek const char *memorynames[] = {
167*b89261baSDavid van Moolenbroek #ifndef __minix
168*b89261baSDavid van Moolenbroek 	"K Act, ", "K Inact, ", "K Wired, ", "K Exec, ", "K File, ",
169*b89261baSDavid van Moolenbroek 	"K Free, ",
170*b89261baSDavid van Moolenbroek #else /* __minix */
171*b89261baSDavid van Moolenbroek 	"K Total, ", "K Free, ", "K Contig, ", "K Cached, ", "K ???, ",
172*b89261baSDavid van Moolenbroek 	"K ???, ",
173*b89261baSDavid van Moolenbroek #endif /* __minix */
174*b89261baSDavid van Moolenbroek 	NULL
175*b89261baSDavid van Moolenbroek };
176*b89261baSDavid van Moolenbroek 
177*b89261baSDavid van Moolenbroek long swap_stats[4];
178*b89261baSDavid van Moolenbroek const char *swapnames[] = {
179*b89261baSDavid van Moolenbroek #ifndef __minix
180*b89261baSDavid van Moolenbroek 	"K Total, ", "K Used, ", "K Free, ",
181*b89261baSDavid van Moolenbroek #endif /* __minix */
182*b89261baSDavid van Moolenbroek 	NULL
183*b89261baSDavid van Moolenbroek };
184*b89261baSDavid van Moolenbroek 
185*b89261baSDavid van Moolenbroek 
186*b89261baSDavid van Moolenbroek /* these are names given to allowed sorting orders -- first is default */
187*b89261baSDavid van Moolenbroek const char *ordernames[] = {
188*b89261baSDavid van Moolenbroek 	"cpu",
189*b89261baSDavid van Moolenbroek 	"pri",
190*b89261baSDavid van Moolenbroek 	"res",
191*b89261baSDavid van Moolenbroek 	"size",
192*b89261baSDavid van Moolenbroek 	"state",
193*b89261baSDavid van Moolenbroek 	"time",
194*b89261baSDavid van Moolenbroek 	"pid",
195*b89261baSDavid van Moolenbroek 	"command",
196*b89261baSDavid van Moolenbroek 	"username",
197*b89261baSDavid van Moolenbroek 	NULL
198*b89261baSDavid van Moolenbroek };
199*b89261baSDavid van Moolenbroek 
200*b89261baSDavid van Moolenbroek /* forward definitions for comparison functions */
201*b89261baSDavid van Moolenbroek static int compare_cpu(struct proc **, struct proc **);
202*b89261baSDavid van Moolenbroek static int compare_prio(struct proc **, struct proc **);
203*b89261baSDavid van Moolenbroek static int compare_res(struct proc **, struct proc **);
204*b89261baSDavid van Moolenbroek static int compare_size(struct proc **, struct proc **);
205*b89261baSDavid van Moolenbroek static int compare_state(struct proc **, struct proc **);
206*b89261baSDavid van Moolenbroek static int compare_time(struct proc **, struct proc **);
207*b89261baSDavid van Moolenbroek static int compare_pid(struct proc **, struct proc **);
208*b89261baSDavid van Moolenbroek static int compare_command(struct proc **, struct proc **);
209*b89261baSDavid van Moolenbroek static int compare_username(struct proc **, struct proc **);
210*b89261baSDavid van Moolenbroek 
211*b89261baSDavid van Moolenbroek int (*proc_compares[])(struct proc **, struct proc **) = {
212*b89261baSDavid van Moolenbroek 	compare_cpu,
213*b89261baSDavid van Moolenbroek 	compare_prio,
214*b89261baSDavid van Moolenbroek 	compare_res,
215*b89261baSDavid van Moolenbroek 	compare_size,
216*b89261baSDavid van Moolenbroek 	compare_state,
217*b89261baSDavid van Moolenbroek 	compare_time,
218*b89261baSDavid van Moolenbroek 	compare_pid,
219*b89261baSDavid van Moolenbroek 	compare_command,
220*b89261baSDavid van Moolenbroek 	compare_username,
221*b89261baSDavid van Moolenbroek 	NULL
222*b89261baSDavid van Moolenbroek };
223*b89261baSDavid van Moolenbroek 
224*b89261baSDavid van Moolenbroek static char *format_next_lwp(caddr_t, char *(*)(int));
225*b89261baSDavid van Moolenbroek static char *format_next_proc(caddr_t, char *(*)(int));
226*b89261baSDavid van Moolenbroek 
227*b89261baSDavid van Moolenbroek static caddr_t get_proc_info(struct system_info *, struct process_select *,
228*b89261baSDavid van Moolenbroek 			     int (*)(struct proc **, struct proc **));
229*b89261baSDavid van Moolenbroek static caddr_t get_lwp_info(struct system_info *, struct process_select *,
230*b89261baSDavid van Moolenbroek 			    int (*)(struct proc **, struct proc **));
231*b89261baSDavid van Moolenbroek 
232*b89261baSDavid van Moolenbroek /* these are for keeping track of the proc array */
233*b89261baSDavid van Moolenbroek 
234*b89261baSDavid van Moolenbroek static int nproc;
235*b89261baSDavid van Moolenbroek static int onproc = -1;
236*b89261baSDavid van Moolenbroek static int nlwp;
237*b89261baSDavid van Moolenbroek static int onlwp = -1;
238*b89261baSDavid van Moolenbroek static int pref_len;
239*b89261baSDavid van Moolenbroek static int lref_len;
240*b89261baSDavid van Moolenbroek static struct kinfo_proc2 *pbase;
241*b89261baSDavid van Moolenbroek static struct kinfo_lwp *lbase;
242*b89261baSDavid van Moolenbroek static struct kinfo_proc2 **pref;
243*b89261baSDavid van Moolenbroek static struct kinfo_lwp **lref;
244*b89261baSDavid van Moolenbroek static int maxswap;
245*b89261baSDavid van Moolenbroek static void *swapp;
246*b89261baSDavid van Moolenbroek static int procgen;
247*b89261baSDavid van Moolenbroek static int thread_nproc;
248*b89261baSDavid van Moolenbroek static int thread_onproc = -1;
249*b89261baSDavid van Moolenbroek static struct kinfo_proc2 *thread_pbase;
250*b89261baSDavid van Moolenbroek 
251*b89261baSDavid van Moolenbroek /* these are for getting the memory statistics */
252*b89261baSDavid van Moolenbroek 
253*b89261baSDavid van Moolenbroek static int pageshift;		/* log base 2 of the pagesize */
254*b89261baSDavid van Moolenbroek 
255*b89261baSDavid van Moolenbroek int threadmode;
256*b89261baSDavid van Moolenbroek 
257*b89261baSDavid van Moolenbroek /* define pagetok in terms of pageshift */
258*b89261baSDavid van Moolenbroek 
259*b89261baSDavid van Moolenbroek #define pagetok(size) ((size) << pageshift)
260*b89261baSDavid van Moolenbroek 
261*b89261baSDavid van Moolenbroek /*
262*b89261baSDavid van Moolenbroek  * Print swapped processes as <pname> and
263*b89261baSDavid van Moolenbroek  * system processes as [pname]
264*b89261baSDavid van Moolenbroek  */
265*b89261baSDavid van Moolenbroek static const char *
get_pretty(const struct kinfo_proc2 * pp)266*b89261baSDavid van Moolenbroek get_pretty(const struct kinfo_proc2 *pp)
267*b89261baSDavid van Moolenbroek {
268*b89261baSDavid van Moolenbroek 	if ((pp->p_flag & P_SYSTEM) != 0)
269*b89261baSDavid van Moolenbroek 		return "[]";
270*b89261baSDavid van Moolenbroek 	if ((pp->p_flag & P_INMEM) == 0)
271*b89261baSDavid van Moolenbroek 		return "<>";
272*b89261baSDavid van Moolenbroek 	return "";
273*b89261baSDavid van Moolenbroek }
274*b89261baSDavid van Moolenbroek 
275*b89261baSDavid van Moolenbroek static const char *
get_command(const struct process_select * sel,struct kinfo_proc2 * pp)276*b89261baSDavid van Moolenbroek get_command(const struct process_select *sel, struct kinfo_proc2 *pp)
277*b89261baSDavid van Moolenbroek {
278*b89261baSDavid van Moolenbroek 	static char cmdbuf[128];
279*b89261baSDavid van Moolenbroek 	const char *pretty;
280*b89261baSDavid van Moolenbroek 	char **argv;
281*b89261baSDavid van Moolenbroek 	if (pp == NULL)
282*b89261baSDavid van Moolenbroek 		return "<gone>";
283*b89261baSDavid van Moolenbroek 	pretty = get_pretty(pp);
284*b89261baSDavid van Moolenbroek 
285*b89261baSDavid van Moolenbroek 	if (sel->fullcmd == 0 || kd == NULL || (argv = kvm_getargv2(kd, pp,
286*b89261baSDavid van Moolenbroek 	    sizeof(cmdbuf))) == NULL) {
287*b89261baSDavid van Moolenbroek 		if (pretty[0] != '\0' && pp->p_comm[0] != pretty[0])
288*b89261baSDavid van Moolenbroek 			snprintf(cmdbuf, sizeof(cmdbuf), "%c%s%c", pretty[0],
289*b89261baSDavid van Moolenbroek 			    printable(pp->p_comm), pretty[1]);
290*b89261baSDavid van Moolenbroek 		else
291*b89261baSDavid van Moolenbroek 			strlcpy(cmdbuf, printable(pp->p_comm), sizeof(cmdbuf));
292*b89261baSDavid van Moolenbroek 	} else {
293*b89261baSDavid van Moolenbroek 		char *d = cmdbuf;
294*b89261baSDavid van Moolenbroek 		if (pretty[0] != '\0' && argv[0][0] != pretty[0])
295*b89261baSDavid van Moolenbroek 			*d++ = pretty[0];
296*b89261baSDavid van Moolenbroek 		while (*argv) {
297*b89261baSDavid van Moolenbroek 			const char *s = printable(*argv++);
298*b89261baSDavid van Moolenbroek 			while (d < cmdbuf + sizeof(cmdbuf) - 2 &&
299*b89261baSDavid van Moolenbroek 			    (*d++ = *s++) != '\0')
300*b89261baSDavid van Moolenbroek 				continue;
301*b89261baSDavid van Moolenbroek 			if (d > cmdbuf && d < cmdbuf + sizeof(cmdbuf) - 2 &&
302*b89261baSDavid van Moolenbroek 			    d[-1] == '\0')
303*b89261baSDavid van Moolenbroek 				d[-1] = ' ';
304*b89261baSDavid van Moolenbroek 		}
305*b89261baSDavid van Moolenbroek 		if (pretty[0] != '\0' && pretty[0] == cmdbuf[0])
306*b89261baSDavid van Moolenbroek 			*d++ = pretty[1];
307*b89261baSDavid van Moolenbroek 		*d++ = '\0';
308*b89261baSDavid van Moolenbroek 	}
309*b89261baSDavid van Moolenbroek 	return cmdbuf;
310*b89261baSDavid van Moolenbroek }
311*b89261baSDavid van Moolenbroek 
312*b89261baSDavid van Moolenbroek int
machine_init(statics)313*b89261baSDavid van Moolenbroek machine_init(statics)
314*b89261baSDavid van Moolenbroek 	struct statics *statics;
315*b89261baSDavid van Moolenbroek {
316*b89261baSDavid van Moolenbroek 	int pagesize;
317*b89261baSDavid van Moolenbroek 	int mib[2];
318*b89261baSDavid van Moolenbroek 	size_t size;
319*b89261baSDavid van Moolenbroek 	struct clockinfo clockinfo;
320*b89261baSDavid van Moolenbroek 	struct timeval boottime;
321*b89261baSDavid van Moolenbroek 
322*b89261baSDavid van Moolenbroek 	if ((kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open")) == NULL)
323*b89261baSDavid van Moolenbroek 		return -1;
324*b89261baSDavid van Moolenbroek 
325*b89261baSDavid van Moolenbroek 	mib[0] = CTL_HW;
326*b89261baSDavid van Moolenbroek 	mib[1] = HW_NCPU;
327*b89261baSDavid van Moolenbroek 	size = sizeof(ncpu);
328*b89261baSDavid van Moolenbroek 	if (sysctl(mib, 2, &ncpu, &size, NULL, 0) == -1) {
329*b89261baSDavid van Moolenbroek 		fprintf(stderr, "top: sysctl hw.ncpu failed: %s\n",
330*b89261baSDavid van Moolenbroek 		    strerror(errno));
331*b89261baSDavid van Moolenbroek 		return(-1);
332*b89261baSDavid van Moolenbroek 	}
333*b89261baSDavid van Moolenbroek 	statics->ncpu = ncpu;
334*b89261baSDavid van Moolenbroek 	cp_time = malloc(sizeof(cp_time[0]) * CPUSTATES * ncpu);
335*b89261baSDavid van Moolenbroek 	mib[0] = CTL_KERN;
336*b89261baSDavid van Moolenbroek 	mib[1] = KERN_CP_TIME;
337*b89261baSDavid van Moolenbroek 	size = sizeof(cp_time[0]) * CPUSTATES * ncpu;
338*b89261baSDavid van Moolenbroek 	if (sysctl(mib, 2, cp_time, &size, NULL, 0) < 0) {
339*b89261baSDavid van Moolenbroek 		fprintf(stderr, "top: sysctl kern.cp_time failed: %s\n",
340*b89261baSDavid van Moolenbroek 		    strerror(errno));
341*b89261baSDavid van Moolenbroek 		return(-1);
342*b89261baSDavid van Moolenbroek 	}
343*b89261baSDavid van Moolenbroek 
344*b89261baSDavid van Moolenbroek 	/* Handle old call that returned only aggregate */
345*b89261baSDavid van Moolenbroek 	if (size == sizeof(cp_time[0]) * CPUSTATES)
346*b89261baSDavid van Moolenbroek 		ncpu = 1;
347*b89261baSDavid van Moolenbroek 
348*b89261baSDavid van Moolenbroek 	cpu_states = malloc(sizeof(cpu_states[0]) * CPUSTATES * ncpu);
349*b89261baSDavid van Moolenbroek 	cp_old = malloc(sizeof(cp_old[0]) * CPUSTATES * ncpu);
350*b89261baSDavid van Moolenbroek 	cp_diff = malloc(sizeof(cp_diff[0]) * CPUSTATES * ncpu);
351*b89261baSDavid van Moolenbroek 	if (cpu_states == NULL || cp_time == NULL || cp_old == NULL ||
352*b89261baSDavid van Moolenbroek 	    cp_diff == NULL) {
353*b89261baSDavid van Moolenbroek 		fprintf(stderr, "top: machine_init: %s\n",
354*b89261baSDavid van Moolenbroek 		    strerror(errno));
355*b89261baSDavid van Moolenbroek 		return(-1);
356*b89261baSDavid van Moolenbroek 	}
357*b89261baSDavid van Moolenbroek 
358*b89261baSDavid van Moolenbroek 	mib[0] = CTL_KERN;
359*b89261baSDavid van Moolenbroek 	mib[1] = KERN_CCPU;
360*b89261baSDavid van Moolenbroek 	size = sizeof(ccpu);
361*b89261baSDavid van Moolenbroek 	if (sysctl(mib, 2, &ccpu, &size, NULL, 0) == -1) {
362*b89261baSDavid van Moolenbroek 		fprintf(stderr, "top: sysctl kern.ccpu failed: %s\n",
363*b89261baSDavid van Moolenbroek 		    strerror(errno));
364*b89261baSDavid van Moolenbroek 		return(-1);
365*b89261baSDavid van Moolenbroek 	}
366*b89261baSDavid van Moolenbroek 
367*b89261baSDavid van Moolenbroek 	mib[0] = CTL_KERN;
368*b89261baSDavid van Moolenbroek 	mib[1] = KERN_CLOCKRATE;
369*b89261baSDavid van Moolenbroek 	size = sizeof(clockinfo);
370*b89261baSDavid van Moolenbroek 	if (sysctl(mib, 2, &clockinfo, &size, NULL, 0) == -1) {
371*b89261baSDavid van Moolenbroek 		fprintf(stderr, "top: sysctl kern.clockrate failed: %s\n",
372*b89261baSDavid van Moolenbroek 		    strerror(errno));
373*b89261baSDavid van Moolenbroek 		return(-1);
374*b89261baSDavid van Moolenbroek 	}
375*b89261baSDavid van Moolenbroek 	hz = clockinfo.stathz;
376*b89261baSDavid van Moolenbroek 
377*b89261baSDavid van Moolenbroek 	/* this is used in calculating WCPU -- calculate it ahead of time */
378*b89261baSDavid van Moolenbroek 	logcpu = log(loaddouble(ccpu));
379*b89261baSDavid van Moolenbroek 
380*b89261baSDavid van Moolenbroek 	pbase = NULL;
381*b89261baSDavid van Moolenbroek 	lbase = NULL;
382*b89261baSDavid van Moolenbroek 	pref = NULL;
383*b89261baSDavid van Moolenbroek 	nproc = 0;
384*b89261baSDavid van Moolenbroek 	onproc = -1;
385*b89261baSDavid van Moolenbroek 	nlwp = 0;
386*b89261baSDavid van Moolenbroek 	onlwp = -1;
387*b89261baSDavid van Moolenbroek 	/* get the page size with "getpagesize" and calculate pageshift from it */
388*b89261baSDavid van Moolenbroek 	pagesize = getpagesize();
389*b89261baSDavid van Moolenbroek 	pageshift = 0;
390*b89261baSDavid van Moolenbroek 	while (pagesize > 1) {
391*b89261baSDavid van Moolenbroek 		pageshift++;
392*b89261baSDavid van Moolenbroek 		pagesize >>= 1;
393*b89261baSDavid van Moolenbroek 	}
394*b89261baSDavid van Moolenbroek 
395*b89261baSDavid van Moolenbroek 	/* we only need the amount of log(2)1024 for our conversion */
396*b89261baSDavid van Moolenbroek 	pageshift -= LOG1024;
397*b89261baSDavid van Moolenbroek 
398*b89261baSDavid van Moolenbroek 	/* fill in the statics information */
399*b89261baSDavid van Moolenbroek #ifdef notyet
400*b89261baSDavid van Moolenbroek 	statics->ncpu = ncpu;
401*b89261baSDavid van Moolenbroek #endif
402*b89261baSDavid van Moolenbroek 	statics->procstate_names = procstatenames;
403*b89261baSDavid van Moolenbroek 	statics->cpustate_names = cpustatenames;
404*b89261baSDavid van Moolenbroek 	statics->memory_names = memorynames;
405*b89261baSDavid van Moolenbroek 	statics->swap_names = swapnames;
406*b89261baSDavid van Moolenbroek 	statics->order_names = ordernames;
407*b89261baSDavid van Moolenbroek 	statics->flags.threads = 1;
408*b89261baSDavid van Moolenbroek 	statics->flags.fullcmds = 1;
409*b89261baSDavid van Moolenbroek 
410*b89261baSDavid van Moolenbroek 	mib[0] = CTL_KERN;
411*b89261baSDavid van Moolenbroek 	mib[1] = KERN_BOOTTIME;
412*b89261baSDavid van Moolenbroek 	size = sizeof(boottime);
413*b89261baSDavid van Moolenbroek 	if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
414*b89261baSDavid van Moolenbroek     	    boottime.tv_sec != 0)
415*b89261baSDavid van Moolenbroek 		statics->boottime = boottime.tv_sec;
416*b89261baSDavid van Moolenbroek 	else
417*b89261baSDavid van Moolenbroek 		statics->boottime = 0;
418*b89261baSDavid van Moolenbroek 	/* all done! */
419*b89261baSDavid van Moolenbroek 	return(0);
420*b89261baSDavid van Moolenbroek }
421*b89261baSDavid van Moolenbroek 
422*b89261baSDavid van Moolenbroek char *
format_process_header(struct process_select * sel,caddr_t handle,int count)423*b89261baSDavid van Moolenbroek format_process_header(struct process_select *sel, caddr_t handle, int count)
424*b89261baSDavid van Moolenbroek 
425*b89261baSDavid van Moolenbroek {
426*b89261baSDavid van Moolenbroek 	char *header;
427*b89261baSDavid van Moolenbroek 	char *ptr;
428*b89261baSDavid van Moolenbroek 	const char *uname_field = sel->usernames ? "USERNAME" : "    UID ";
429*b89261baSDavid van Moolenbroek 
430*b89261baSDavid van Moolenbroek 	if (sel->threads) {
431*b89261baSDavid van Moolenbroek 		header = Thread_header;
432*b89261baSDavid van Moolenbroek 		ptr = header + THREAD_UNAME_START;
433*b89261baSDavid van Moolenbroek 	} else {
434*b89261baSDavid van Moolenbroek 		header = Proc_header;
435*b89261baSDavid van Moolenbroek 		ptr = header + PROC_UNAME_START;
436*b89261baSDavid van Moolenbroek 	}
437*b89261baSDavid van Moolenbroek 
438*b89261baSDavid van Moolenbroek 	while (*uname_field != '\0') {
439*b89261baSDavid van Moolenbroek 		*ptr++ = *uname_field++;
440*b89261baSDavid van Moolenbroek 	}
441*b89261baSDavid van Moolenbroek 
442*b89261baSDavid van Moolenbroek 	return(header);
443*b89261baSDavid van Moolenbroek }
444*b89261baSDavid van Moolenbroek 
445*b89261baSDavid van Moolenbroek char *
format_header(char * uname_field)446*b89261baSDavid van Moolenbroek format_header(char *uname_field)
447*b89261baSDavid van Moolenbroek {
448*b89261baSDavid van Moolenbroek 	char *header = Proc_header;
449*b89261baSDavid van Moolenbroek 	char *ptr = header + PROC_UNAME_START;
450*b89261baSDavid van Moolenbroek 
451*b89261baSDavid van Moolenbroek 	while (*uname_field != '\0') {
452*b89261baSDavid van Moolenbroek 		*ptr++ = *uname_field++;
453*b89261baSDavid van Moolenbroek 	}
454*b89261baSDavid van Moolenbroek 
455*b89261baSDavid van Moolenbroek 	return(header);
456*b89261baSDavid van Moolenbroek }
457*b89261baSDavid van Moolenbroek 
458*b89261baSDavid van Moolenbroek void
get_system_info(struct system_info * si)459*b89261baSDavid van Moolenbroek get_system_info(struct system_info *si)
460*b89261baSDavid van Moolenbroek {
461*b89261baSDavid van Moolenbroek 	size_t ssize;
462*b89261baSDavid van Moolenbroek 	int mib[2];
463*b89261baSDavid van Moolenbroek 	struct uvmexp_sysctl uvmexp;
464*b89261baSDavid van Moolenbroek 	struct swapent *sep;
465*b89261baSDavid van Moolenbroek 	u_int64_t totalsize, totalinuse;
466*b89261baSDavid van Moolenbroek 	int size, inuse, ncounted, i;
467*b89261baSDavid van Moolenbroek 	int rnswap, nswap;
468*b89261baSDavid van Moolenbroek 
469*b89261baSDavid van Moolenbroek 	mib[0] = CTL_KERN;
470*b89261baSDavid van Moolenbroek 	mib[1] = KERN_CP_TIME;
471*b89261baSDavid van Moolenbroek 	ssize = sizeof(cp_time[0]) * CPUSTATES * ncpu;
472*b89261baSDavid van Moolenbroek 	if (sysctl(mib, 2, cp_time, &ssize, NULL, 0) < 0) {
473*b89261baSDavid van Moolenbroek 		fprintf(stderr, "top: sysctl kern.cp_time failed: %s\n",
474*b89261baSDavid van Moolenbroek 		    strerror(errno));
475*b89261baSDavid van Moolenbroek 		quit(23);
476*b89261baSDavid van Moolenbroek 	}
477*b89261baSDavid van Moolenbroek 
478*b89261baSDavid van Moolenbroek 	if (getloadavg(si->load_avg, NUM_AVERAGES) < 0) {
479*b89261baSDavid van Moolenbroek 		int j;
480*b89261baSDavid van Moolenbroek 
481*b89261baSDavid van Moolenbroek 		warn("can't getloadavg");
482*b89261baSDavid van Moolenbroek 		for (j = 0; j < NUM_AVERAGES; j++)
483*b89261baSDavid van Moolenbroek 			si->load_avg[j] = 0.0;
484*b89261baSDavid van Moolenbroek 	}
485*b89261baSDavid van Moolenbroek 
486*b89261baSDavid van Moolenbroek 	/* convert cp_time counts to percentages */
487*b89261baSDavid van Moolenbroek 	for (i = 0; i < ncpu; i++) {
488*b89261baSDavid van Moolenbroek 	    int j = i * CPUSTATES;
489*b89261baSDavid van Moolenbroek 	    percentages64(CPUSTATES, cpu_states + j, cp_time + j, cp_old + j,
490*b89261baSDavid van Moolenbroek 		cp_diff + j);
491*b89261baSDavid van Moolenbroek 	}
492*b89261baSDavid van Moolenbroek 
493*b89261baSDavid van Moolenbroek 	mib[0] = CTL_VM;
494*b89261baSDavid van Moolenbroek 	mib[1] = VM_UVMEXP2;
495*b89261baSDavid van Moolenbroek 	ssize = sizeof(uvmexp);
496*b89261baSDavid van Moolenbroek 	if (sysctl(mib, 2, &uvmexp, &ssize, NULL, 0) < 0) {
497*b89261baSDavid van Moolenbroek 		fprintf(stderr, "top: sysctl vm.uvmexp2 failed: %s\n",
498*b89261baSDavid van Moolenbroek 		    strerror(errno));
499*b89261baSDavid van Moolenbroek 		quit(23);
500*b89261baSDavid van Moolenbroek 	}
501*b89261baSDavid van Moolenbroek 
502*b89261baSDavid van Moolenbroek 	/* convert memory stats to Kbytes */
503*b89261baSDavid van Moolenbroek #ifndef __minix
504*b89261baSDavid van Moolenbroek 	memory_stats[0] = pagetok(uvmexp.active);
505*b89261baSDavid van Moolenbroek 	memory_stats[1] = pagetok(uvmexp.inactive);
506*b89261baSDavid van Moolenbroek 	memory_stats[2] = pagetok(uvmexp.wired);
507*b89261baSDavid van Moolenbroek 	memory_stats[3] = pagetok(uvmexp.execpages);
508*b89261baSDavid van Moolenbroek 	memory_stats[4] = pagetok(uvmexp.filepages);
509*b89261baSDavid van Moolenbroek 	memory_stats[5] = pagetok(uvmexp.free);
510*b89261baSDavid van Moolenbroek #else /* __minix */
511*b89261baSDavid van Moolenbroek 	memory_stats[0] = pagetok(uvmexp.npages);
512*b89261baSDavid van Moolenbroek 	memory_stats[1] = pagetok(uvmexp.free);
513*b89261baSDavid van Moolenbroek 	memory_stats[2] = pagetok(uvmexp.unused1); /* largest phys contig */
514*b89261baSDavid van Moolenbroek 	memory_stats[3] = pagetok(uvmexp.filepages);
515*b89261baSDavid van Moolenbroek 	memory_stats[4] = 0;
516*b89261baSDavid van Moolenbroek 	memory_stats[5] = 0;
517*b89261baSDavid van Moolenbroek #endif /* __minix */
518*b89261baSDavid van Moolenbroek 
519*b89261baSDavid van Moolenbroek 	swap_stats[0] = swap_stats[1] = swap_stats[2] = 0;
520*b89261baSDavid van Moolenbroek 
521*b89261baSDavid van Moolenbroek 	do {
522*b89261baSDavid van Moolenbroek #ifndef __minix
523*b89261baSDavid van Moolenbroek 		nswap = swapctl(SWAP_NSWAP, 0, 0);
524*b89261baSDavid van Moolenbroek #else /* __minix */
525*b89261baSDavid van Moolenbroek 		nswap = 0;
526*b89261baSDavid van Moolenbroek #endif /* __minix */
527*b89261baSDavid van Moolenbroek 		if (nswap < 1)
528*b89261baSDavid van Moolenbroek 			break;
529*b89261baSDavid van Moolenbroek 		if (nswap > maxswap) {
530*b89261baSDavid van Moolenbroek 			if (swapp)
531*b89261baSDavid van Moolenbroek 				free(swapp);
532*b89261baSDavid van Moolenbroek 			swapp = sep = malloc(nswap * sizeof(*sep));
533*b89261baSDavid van Moolenbroek 			if (sep == NULL)
534*b89261baSDavid van Moolenbroek 				break;
535*b89261baSDavid van Moolenbroek 			maxswap = nswap;
536*b89261baSDavid van Moolenbroek 		} else
537*b89261baSDavid van Moolenbroek 			sep = swapp;
538*b89261baSDavid van Moolenbroek #ifndef __minix
539*b89261baSDavid van Moolenbroek 		rnswap = swapctl(SWAP_STATS, (void *)sep, nswap);
540*b89261baSDavid van Moolenbroek #else /* __minix */
541*b89261baSDavid van Moolenbroek 		rnswap = 0;
542*b89261baSDavid van Moolenbroek #endif /* __minix */
543*b89261baSDavid van Moolenbroek 		if (nswap != rnswap)
544*b89261baSDavid van Moolenbroek 			break;
545*b89261baSDavid van Moolenbroek 
546*b89261baSDavid van Moolenbroek 		totalsize = totalinuse = ncounted = 0;
547*b89261baSDavid van Moolenbroek 		for (; rnswap-- > 0; sep++) {
548*b89261baSDavid van Moolenbroek 			ncounted++;
549*b89261baSDavid van Moolenbroek 			size = sep->se_nblks;
550*b89261baSDavid van Moolenbroek 			inuse = sep->se_inuse;
551*b89261baSDavid van Moolenbroek 			totalsize += size;
552*b89261baSDavid van Moolenbroek 			totalinuse += inuse;
553*b89261baSDavid van Moolenbroek 		}
554*b89261baSDavid van Moolenbroek 		swap_stats[0] = dbtob(totalsize) / 1024;
555*b89261baSDavid van Moolenbroek 		swap_stats[1] = dbtob(totalinuse) / 1024;
556*b89261baSDavid van Moolenbroek 		swap_stats[2] = dbtob(totalsize) / 1024 - swap_stats[1];
557*b89261baSDavid van Moolenbroek 	} while (0);
558*b89261baSDavid van Moolenbroek 
559*b89261baSDavid van Moolenbroek 	memory_stats[6] = -1;
560*b89261baSDavid van Moolenbroek 	swap_stats[3] = -1;
561*b89261baSDavid van Moolenbroek 
562*b89261baSDavid van Moolenbroek 	/* set arrays and strings */
563*b89261baSDavid van Moolenbroek 	si->cpustates = cpu_states;
564*b89261baSDavid van Moolenbroek 	si->memory = memory_stats;
565*b89261baSDavid van Moolenbroek 	si->swap = swap_stats;
566*b89261baSDavid van Moolenbroek 	si->last_pid = -1;
567*b89261baSDavid van Moolenbroek 
568*b89261baSDavid van Moolenbroek }
569*b89261baSDavid van Moolenbroek 
570*b89261baSDavid van Moolenbroek static struct kinfo_proc2 *
proc_from_thread(struct kinfo_lwp * pl)571*b89261baSDavid van Moolenbroek proc_from_thread(struct kinfo_lwp *pl)
572*b89261baSDavid van Moolenbroek {
573*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 *pp = thread_pbase;
574*b89261baSDavid van Moolenbroek 	int i;
575*b89261baSDavid van Moolenbroek 
576*b89261baSDavid van Moolenbroek 	for (i = 0; i < thread_nproc; i++, pp++)
577*b89261baSDavid van Moolenbroek 		if ((pid_t)pp->p_pid == (pid_t)pl->l_pid)
578*b89261baSDavid van Moolenbroek 			return pp;
579*b89261baSDavid van Moolenbroek 	return NULL;
580*b89261baSDavid van Moolenbroek }
581*b89261baSDavid van Moolenbroek 
582*b89261baSDavid van Moolenbroek static int
uid_from_thread(struct kinfo_lwp * pl)583*b89261baSDavid van Moolenbroek uid_from_thread(struct kinfo_lwp *pl)
584*b89261baSDavid van Moolenbroek {
585*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 *pp;
586*b89261baSDavid van Moolenbroek 
587*b89261baSDavid van Moolenbroek 	if ((pp = proc_from_thread(pl)) == NULL)
588*b89261baSDavid van Moolenbroek 		return -1;
589*b89261baSDavid van Moolenbroek 	return pp->p_ruid;
590*b89261baSDavid van Moolenbroek }
591*b89261baSDavid van Moolenbroek 
592*b89261baSDavid van Moolenbroek caddr_t
get_process_info(struct system_info * si,struct process_select * sel,int c)593*b89261baSDavid van Moolenbroek get_process_info(struct system_info *si, struct process_select *sel, int c)
594*b89261baSDavid van Moolenbroek {
595*b89261baSDavid van Moolenbroek 	userprint = sel->usernames ? username : itoa7;
596*b89261baSDavid van Moolenbroek 
597*b89261baSDavid van Moolenbroek 	if ((threadmode = sel->threads) != 0)
598*b89261baSDavid van Moolenbroek 		return get_lwp_info(si, sel, proc_compares[c]);
599*b89261baSDavid van Moolenbroek 	else
600*b89261baSDavid van Moolenbroek 		return get_proc_info(si, sel, proc_compares[c]);
601*b89261baSDavid van Moolenbroek }
602*b89261baSDavid van Moolenbroek 
603*b89261baSDavid van Moolenbroek static caddr_t
get_proc_info(struct system_info * si,struct process_select * sel,int (* compare)(struct proc **,struct proc **))604*b89261baSDavid van Moolenbroek get_proc_info(struct system_info *si, struct process_select *sel,
605*b89261baSDavid van Moolenbroek 	      int (*compare)(struct proc **, struct proc **))
606*b89261baSDavid van Moolenbroek {
607*b89261baSDavid van Moolenbroek 	int i;
608*b89261baSDavid van Moolenbroek 	int total_procs;
609*b89261baSDavid van Moolenbroek 	int active_procs;
610*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 **prefp, **n;
611*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 *pp;
612*b89261baSDavid van Moolenbroek 	int op, arg;
613*b89261baSDavid van Moolenbroek 
614*b89261baSDavid van Moolenbroek 	/* these are copied out of sel for speed */
615*b89261baSDavid van Moolenbroek 	int show_idle;
616*b89261baSDavid van Moolenbroek 	int show_system;
617*b89261baSDavid van Moolenbroek 	int show_uid;
618*b89261baSDavid van Moolenbroek 
619*b89261baSDavid van Moolenbroek 	static struct handle handle;
620*b89261baSDavid van Moolenbroek 
621*b89261baSDavid van Moolenbroek 	procgen++;
622*b89261baSDavid van Moolenbroek 
623*b89261baSDavid van Moolenbroek 	if (sel->pid == (pid_t)-1) {
624*b89261baSDavid van Moolenbroek 		op = KERN_PROC_ALL;
625*b89261baSDavid van Moolenbroek 		arg = 0;
626*b89261baSDavid van Moolenbroek 	} else {
627*b89261baSDavid van Moolenbroek 		op = KERN_PROC_PID;
628*b89261baSDavid van Moolenbroek 		arg = sel->pid;
629*b89261baSDavid van Moolenbroek 	}
630*b89261baSDavid van Moolenbroek 
631*b89261baSDavid van Moolenbroek 	pbase = kvm_getproc2(kd, op, arg, sizeof(struct kinfo_proc2), &nproc);
632*b89261baSDavid van Moolenbroek 	if (pbase == NULL) {
633*b89261baSDavid van Moolenbroek 		if (sel->pid != (pid_t)-1) {
634*b89261baSDavid van Moolenbroek 			nproc = 0;
635*b89261baSDavid van Moolenbroek 		} else {
636*b89261baSDavid van Moolenbroek 			(void) fprintf(stderr, "top: Out of memory.\n");
637*b89261baSDavid van Moolenbroek 			quit(23);
638*b89261baSDavid van Moolenbroek 		}
639*b89261baSDavid van Moolenbroek 	}
640*b89261baSDavid van Moolenbroek 	if (nproc > onproc) {
641*b89261baSDavid van Moolenbroek 		n = (struct kinfo_proc2 **) realloc(pref,
642*b89261baSDavid van Moolenbroek 		    sizeof(struct kinfo_proc2 *) * nproc);
643*b89261baSDavid van Moolenbroek 		if (n == NULL) {
644*b89261baSDavid van Moolenbroek 			(void) fprintf(stderr, "top: Out of memory.\n");
645*b89261baSDavid van Moolenbroek 			quit(23);
646*b89261baSDavid van Moolenbroek 		}
647*b89261baSDavid van Moolenbroek 		pref = n;
648*b89261baSDavid van Moolenbroek 		onproc = nproc;
649*b89261baSDavid van Moolenbroek 	}
650*b89261baSDavid van Moolenbroek 	/* get a pointer to the states summary array */
651*b89261baSDavid van Moolenbroek 	si->procstates = process_states;
652*b89261baSDavid van Moolenbroek 
653*b89261baSDavid van Moolenbroek 	/* set up flags which define what we are going to select */
654*b89261baSDavid van Moolenbroek 	show_idle = sel->idle;
655*b89261baSDavid van Moolenbroek 	show_system = sel->system;
656*b89261baSDavid van Moolenbroek 	show_uid = sel->uid != -1;
657*b89261baSDavid van Moolenbroek 
658*b89261baSDavid van Moolenbroek 	/* count up process states and get pointers to interesting procs */
659*b89261baSDavid van Moolenbroek 	total_procs = 0;
660*b89261baSDavid van Moolenbroek 	active_procs = 0;
661*b89261baSDavid van Moolenbroek 	memset((char *)process_states, 0, sizeof(process_states));
662*b89261baSDavid van Moolenbroek 	prefp = pref;
663*b89261baSDavid van Moolenbroek 	for (pp = pbase, i = 0; i < nproc; pp++, i++) {
664*b89261baSDavid van Moolenbroek 
665*b89261baSDavid van Moolenbroek 		/*
666*b89261baSDavid van Moolenbroek 		 * Place pointers to each valid proc structure in pref[].
667*b89261baSDavid van Moolenbroek 		 * Process slots that are actually in use have a non-zero
668*b89261baSDavid van Moolenbroek 		 * status field.  Processes with P_SYSTEM set are system
669*b89261baSDavid van Moolenbroek 		 * processes---these get ignored unless show_sysprocs is set.
670*b89261baSDavid van Moolenbroek 		 */
671*b89261baSDavid van Moolenbroek 		if (pp->p_stat != 0 && (show_system || ((pp->p_flag & P_SYSTEM) == 0))) {
672*b89261baSDavid van Moolenbroek 			total_procs++;
673*b89261baSDavid van Moolenbroek 			process_states[(unsigned char) pp->p_stat]++;
674*b89261baSDavid van Moolenbroek 			if (pp->p_stat != LSZOMB &&
675*b89261baSDavid van Moolenbroek 			    (show_idle || (pp->p_pctcpu != 0) ||
676*b89261baSDavid van Moolenbroek 			    (pp->p_stat == LSRUN || pp->p_stat == LSONPROC)) &&
677*b89261baSDavid van Moolenbroek 			    (!show_uid || pp->p_ruid == (uid_t)sel->uid)) {
678*b89261baSDavid van Moolenbroek 				*prefp++ = pp;
679*b89261baSDavid van Moolenbroek 				active_procs++;
680*b89261baSDavid van Moolenbroek 			}
681*b89261baSDavid van Moolenbroek 		}
682*b89261baSDavid van Moolenbroek 	}
683*b89261baSDavid van Moolenbroek 
684*b89261baSDavid van Moolenbroek 	/* if requested, sort the "interesting" processes */
685*b89261baSDavid van Moolenbroek 	if (compare != NULL) {
686*b89261baSDavid van Moolenbroek 		qsort((char *)pref, active_procs, sizeof(struct kinfo_proc2 *),
687*b89261baSDavid van Moolenbroek 		    (int (*)(const void *, const void *))compare);
688*b89261baSDavid van Moolenbroek 	}
689*b89261baSDavid van Moolenbroek 
690*b89261baSDavid van Moolenbroek 	/* remember active and total counts */
691*b89261baSDavid van Moolenbroek 	si->p_total = total_procs;
692*b89261baSDavid van Moolenbroek 	si->p_active = pref_len = active_procs;
693*b89261baSDavid van Moolenbroek 
694*b89261baSDavid van Moolenbroek 	/* pass back a handle */
695*b89261baSDavid van Moolenbroek 	handle.next_proc = pref;
696*b89261baSDavid van Moolenbroek 	handle.remaining = active_procs;
697*b89261baSDavid van Moolenbroek 	handle.sel = sel;
698*b89261baSDavid van Moolenbroek 	return((caddr_t)&handle);
699*b89261baSDavid van Moolenbroek }
700*b89261baSDavid van Moolenbroek 
701*b89261baSDavid van Moolenbroek static caddr_t
get_lwp_info(struct system_info * si,struct process_select * sel,int (* compare)(struct proc **,struct proc **))702*b89261baSDavid van Moolenbroek get_lwp_info(struct system_info *si, struct process_select *sel,
703*b89261baSDavid van Moolenbroek 	     int (*compare)(struct proc **, struct proc **))
704*b89261baSDavid van Moolenbroek {
705*b89261baSDavid van Moolenbroek 	int i;
706*b89261baSDavid van Moolenbroek 	int total_lwps;
707*b89261baSDavid van Moolenbroek 	int active_lwps;
708*b89261baSDavid van Moolenbroek 	struct kinfo_lwp **lrefp, **n;
709*b89261baSDavid van Moolenbroek 	struct kinfo_lwp *lp;
710*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 *pp;
711*b89261baSDavid van Moolenbroek 
712*b89261baSDavid van Moolenbroek 	/* these are copied out of sel for speed */
713*b89261baSDavid van Moolenbroek 	int show_idle;
714*b89261baSDavid van Moolenbroek 	int show_system;
715*b89261baSDavid van Moolenbroek 	int show_uid;
716*b89261baSDavid van Moolenbroek 
717*b89261baSDavid van Moolenbroek 	static struct handle handle;
718*b89261baSDavid van Moolenbroek 
719*b89261baSDavid van Moolenbroek 	pp = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2),
720*b89261baSDavid van Moolenbroek 	    &thread_nproc);
721*b89261baSDavid van Moolenbroek 	if (pp == NULL) {
722*b89261baSDavid van Moolenbroek 		(void) fprintf(stderr, "top: Out of memory.\n");
723*b89261baSDavid van Moolenbroek 		quit(23);
724*b89261baSDavid van Moolenbroek 	}
725*b89261baSDavid van Moolenbroek 	if (thread_pbase == NULL || thread_nproc != thread_onproc) {
726*b89261baSDavid van Moolenbroek 		free(thread_pbase);
727*b89261baSDavid van Moolenbroek 		thread_onproc = thread_nproc;
728*b89261baSDavid van Moolenbroek 		thread_pbase = calloc(sizeof(struct kinfo_proc2), thread_nproc);
729*b89261baSDavid van Moolenbroek 		if (thread_pbase == NULL) {
730*b89261baSDavid van Moolenbroek 			(void) fprintf(stderr, "top: Out of memory.\n");
731*b89261baSDavid van Moolenbroek 			quit(23);
732*b89261baSDavid van Moolenbroek 		}
733*b89261baSDavid van Moolenbroek 	}
734*b89261baSDavid van Moolenbroek 	memcpy(thread_pbase, pp, sizeof(struct kinfo_proc2) * thread_nproc);
735*b89261baSDavid van Moolenbroek 
736*b89261baSDavid van Moolenbroek 	lbase = kvm_getlwps(kd, -1, 0, sizeof(struct kinfo_lwp), &nlwp);
737*b89261baSDavid van Moolenbroek 	if (lbase == NULL) {
738*b89261baSDavid van Moolenbroek #ifdef notyet
739*b89261baSDavid van Moolenbroek 		if (sel->pid != (pid_t)-1) {
740*b89261baSDavid van Moolenbroek 			nproc = 0;
741*b89261baSDavid van Moolenbroek 			nlwp = 0;
742*b89261baSDavid van Moolenbroek 		}
743*b89261baSDavid van Moolenbroek 		else
744*b89261baSDavid van Moolenbroek #endif
745*b89261baSDavid van Moolenbroek 		{
746*b89261baSDavid van Moolenbroek 			(void) fprintf(stderr, "top: Out of memory.\n");
747*b89261baSDavid van Moolenbroek 			quit(23);
748*b89261baSDavid van Moolenbroek 		}
749*b89261baSDavid van Moolenbroek 	}
750*b89261baSDavid van Moolenbroek 	if (nlwp > onlwp) {
751*b89261baSDavid van Moolenbroek 		n = (struct kinfo_lwp **) realloc(lref,
752*b89261baSDavid van Moolenbroek 		    sizeof(struct kinfo_lwp *) * nlwp);
753*b89261baSDavid van Moolenbroek 		if (n == NULL) {
754*b89261baSDavid van Moolenbroek 			(void) fprintf(stderr, "top: Out of memory.\n");
755*b89261baSDavid van Moolenbroek 			quit(23);
756*b89261baSDavid van Moolenbroek 		}
757*b89261baSDavid van Moolenbroek 		lref = n;
758*b89261baSDavid van Moolenbroek 		onlwp = nlwp;
759*b89261baSDavid van Moolenbroek 	}
760*b89261baSDavid van Moolenbroek 	/* get a pointer to the states summary array */
761*b89261baSDavid van Moolenbroek 	si->procstates = process_states;
762*b89261baSDavid van Moolenbroek 
763*b89261baSDavid van Moolenbroek 	/* set up flags which define what we are going to select */
764*b89261baSDavid van Moolenbroek 	show_idle = sel->idle;
765*b89261baSDavid van Moolenbroek 	show_system = sel->system;
766*b89261baSDavid van Moolenbroek 	show_uid = sel->uid != -1;
767*b89261baSDavid van Moolenbroek 
768*b89261baSDavid van Moolenbroek 	/* count up thread states and get pointers to interesting threads */
769*b89261baSDavid van Moolenbroek 	total_lwps = 0;
770*b89261baSDavid van Moolenbroek 	active_lwps = 0;
771*b89261baSDavid van Moolenbroek 	memset((char *)process_states, 0, sizeof(process_states));
772*b89261baSDavid van Moolenbroek 	lrefp = lref;
773*b89261baSDavid van Moolenbroek 	for (lp = lbase, i = 0; i < nlwp; lp++, i++) {
774*b89261baSDavid van Moolenbroek 		if (sel->pid != (pid_t)-1 && sel->pid != (pid_t)lp->l_pid)
775*b89261baSDavid van Moolenbroek 			continue;
776*b89261baSDavid van Moolenbroek 
777*b89261baSDavid van Moolenbroek 		/*
778*b89261baSDavid van Moolenbroek 		 * Place pointers to each valid lwp structure in lref[].
779*b89261baSDavid van Moolenbroek 		 * thread slots that are actually in use have a non-zero
780*b89261baSDavid van Moolenbroek 		 * status field.  threads with L_SYSTEM set are system
781*b89261baSDavid van Moolenbroek 		 * threads---these get ignored unless show_sysprocs is set.
782*b89261baSDavid van Moolenbroek 		 */
783*b89261baSDavid van Moolenbroek 		if (lp->l_stat != 0 && (show_system || ((lp->l_flag & LW_SYSTEM) == 0))) {
784*b89261baSDavid van Moolenbroek 			total_lwps++;
785*b89261baSDavid van Moolenbroek 			process_states[(unsigned char) lp->l_stat]++;
786*b89261baSDavid van Moolenbroek 			if (lp->l_stat != LSZOMB &&
787*b89261baSDavid van Moolenbroek 			    (show_idle || (lp->l_pctcpu != 0) ||
788*b89261baSDavid van Moolenbroek 			    (lp->l_stat == LSRUN || lp->l_stat == LSONPROC)) &&
789*b89261baSDavid van Moolenbroek 			    (!show_uid || uid_from_thread(lp) == sel->uid)) {
790*b89261baSDavid van Moolenbroek 				*lrefp++ = lp;
791*b89261baSDavid van Moolenbroek 				active_lwps++;
792*b89261baSDavid van Moolenbroek 			}
793*b89261baSDavid van Moolenbroek 		}
794*b89261baSDavid van Moolenbroek 	}
795*b89261baSDavid van Moolenbroek 
796*b89261baSDavid van Moolenbroek 	/* if requested, sort the "interesting" threads */
797*b89261baSDavid van Moolenbroek 	if (compare != NULL) {
798*b89261baSDavid van Moolenbroek 		qsort((char *)lref, active_lwps, sizeof(struct kinfo_lwp *),
799*b89261baSDavid van Moolenbroek 		    (int (*)(const void *, const void *))compare);
800*b89261baSDavid van Moolenbroek 	}
801*b89261baSDavid van Moolenbroek 
802*b89261baSDavid van Moolenbroek 	/* remember active and total counts */
803*b89261baSDavid van Moolenbroek 	si->p_total = total_lwps;
804*b89261baSDavid van Moolenbroek 	si->p_active = lref_len = active_lwps;
805*b89261baSDavid van Moolenbroek 
806*b89261baSDavid van Moolenbroek 	/* pass back a handle */
807*b89261baSDavid van Moolenbroek 	handle.next_proc = (struct kinfo_proc2 **)lref;
808*b89261baSDavid van Moolenbroek 	handle.remaining = active_lwps;
809*b89261baSDavid van Moolenbroek 	handle.sel = sel;
810*b89261baSDavid van Moolenbroek 
811*b89261baSDavid van Moolenbroek 	return((caddr_t)&handle);
812*b89261baSDavid van Moolenbroek }
813*b89261baSDavid van Moolenbroek 
814*b89261baSDavid van Moolenbroek char *
format_next_process(caddr_t handle,char * (* get_userid)(int))815*b89261baSDavid van Moolenbroek format_next_process(caddr_t handle, char *(*get_userid)(int))
816*b89261baSDavid van Moolenbroek {
817*b89261baSDavid van Moolenbroek 
818*b89261baSDavid van Moolenbroek 	if (threadmode)
819*b89261baSDavid van Moolenbroek 		return format_next_lwp(handle, get_userid);
820*b89261baSDavid van Moolenbroek 	else
821*b89261baSDavid van Moolenbroek 		return format_next_proc(handle, get_userid);
822*b89261baSDavid van Moolenbroek }
823*b89261baSDavid van Moolenbroek 
824*b89261baSDavid van Moolenbroek 
825*b89261baSDavid van Moolenbroek char *
format_next_proc(caddr_t handle,char * (* get_userid)(int))826*b89261baSDavid van Moolenbroek format_next_proc(caddr_t handle, char *(*get_userid)(int))
827*b89261baSDavid van Moolenbroek {
828*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 *pp;
829*b89261baSDavid van Moolenbroek 	long cputime;
830*b89261baSDavid van Moolenbroek 	double pct, wcpu, cpu;
831*b89261baSDavid van Moolenbroek 	struct handle *hp;
832*b89261baSDavid van Moolenbroek 	const char *statep;
833*b89261baSDavid van Moolenbroek #ifdef KI_NOCPU
834*b89261baSDavid van Moolenbroek 	char state[10];
835*b89261baSDavid van Moolenbroek #endif
836*b89261baSDavid van Moolenbroek 	char wmesg[KI_WMESGLEN + 1];
837*b89261baSDavid van Moolenbroek 	static char fmt[MAX_COLS];		/* static area where result is built */
838*b89261baSDavid van Moolenbroek 
839*b89261baSDavid van Moolenbroek 	/* find and remember the next proc structure */
840*b89261baSDavid van Moolenbroek 	hp = (struct handle *)handle;
841*b89261baSDavid van Moolenbroek 	pp = *(hp->next_proc++);
842*b89261baSDavid van Moolenbroek 	hp->remaining--;
843*b89261baSDavid van Moolenbroek 
844*b89261baSDavid van Moolenbroek 	/* get the process's user struct and set cputime */
845*b89261baSDavid van Moolenbroek 
846*b89261baSDavid van Moolenbroek #if 0
847*b89261baSDavid van Moolenbroek 	/* This does not produce the correct results */
848*b89261baSDavid van Moolenbroek 	cputime = pp->p_uticks + pp->p_sticks + pp->p_iticks;
849*b89261baSDavid van Moolenbroek #else
850*b89261baSDavid van Moolenbroek 	cputime = pp->p_rtime_sec;	/* This does not count interrupts */
851*b89261baSDavid van Moolenbroek #endif
852*b89261baSDavid van Moolenbroek 
853*b89261baSDavid van Moolenbroek 	/* calculate the base for CPU percentages */
854*b89261baSDavid van Moolenbroek 	pct = pctdouble(pp->p_pctcpu);
855*b89261baSDavid van Moolenbroek 
856*b89261baSDavid van Moolenbroek 	if (pp->p_stat == LSSLEEP) {
857*b89261baSDavid van Moolenbroek 		strlcpy(wmesg, pp->p_wmesg, sizeof(wmesg));
858*b89261baSDavid van Moolenbroek 		statep = wmesg;
859*b89261baSDavid van Moolenbroek 	} else
860*b89261baSDavid van Moolenbroek 		statep = state_abbrev[(unsigned)pp->p_stat];
861*b89261baSDavid van Moolenbroek 
862*b89261baSDavid van Moolenbroek #ifdef KI_NOCPU
863*b89261baSDavid van Moolenbroek 	/* Post-1.5 change: add CPU number if appropriate */
864*b89261baSDavid van Moolenbroek 	if (pp->p_cpuid != KI_NOCPU && ncpu > 1) {
865*b89261baSDavid van Moolenbroek 		switch (pp->p_stat) {
866*b89261baSDavid van Moolenbroek 		case LSONPROC:
867*b89261baSDavid van Moolenbroek 		case LSRUN:
868*b89261baSDavid van Moolenbroek 		case LSSLEEP:
869*b89261baSDavid van Moolenbroek 		case LSIDL:
870*b89261baSDavid van Moolenbroek 			(void)snprintf(state, sizeof(state), "%.6s/%u",
871*b89261baSDavid van Moolenbroek 			     statep, (unsigned int)pp->p_cpuid);
872*b89261baSDavid van Moolenbroek 			statep = state;
873*b89261baSDavid van Moolenbroek 			break;
874*b89261baSDavid van Moolenbroek 		}
875*b89261baSDavid van Moolenbroek 	}
876*b89261baSDavid van Moolenbroek #endif
877*b89261baSDavid van Moolenbroek 	wcpu = 100.0 * weighted_cpu(p_, pct, pp);
878*b89261baSDavid van Moolenbroek 	cpu = 100.0 * pct;
879*b89261baSDavid van Moolenbroek 
880*b89261baSDavid van Moolenbroek 	/* format this entry */
881*b89261baSDavid van Moolenbroek 	sprintf(fmt,
882*b89261baSDavid van Moolenbroek 	    Proc_format,
883*b89261baSDavid van Moolenbroek 	    pp->p_pid,
884*b89261baSDavid van Moolenbroek 	    (*userprint)(pp->p_ruid),
885*b89261baSDavid van Moolenbroek 	    pp->p_priority,
886*b89261baSDavid van Moolenbroek 	    pp->p_nice - NZERO,
887*b89261baSDavid van Moolenbroek 	    format_k(pagetok(PROCSIZE(pp))),
888*b89261baSDavid van Moolenbroek 	    format_k(pagetok(pp->p_vm_rssize)),
889*b89261baSDavid van Moolenbroek 	    statep,
890*b89261baSDavid van Moolenbroek 	    format_time(cputime),
891*b89261baSDavid van Moolenbroek 	    (wcpu >= 100.0) ? 0 : 2, wcpu,
892*b89261baSDavid van Moolenbroek 	    (cpu >= 100.0) ? 0 : 2, cpu,
893*b89261baSDavid van Moolenbroek 	    get_command(hp->sel, pp));
894*b89261baSDavid van Moolenbroek 
895*b89261baSDavid van Moolenbroek 	/* return the result */
896*b89261baSDavid van Moolenbroek 	return(fmt);
897*b89261baSDavid van Moolenbroek }
898*b89261baSDavid van Moolenbroek 
899*b89261baSDavid van Moolenbroek static char *
format_next_lwp(caddr_t handle,char * (* get_userid)(int))900*b89261baSDavid van Moolenbroek format_next_lwp(caddr_t handle, char *(*get_userid)(int))
901*b89261baSDavid van Moolenbroek {
902*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 *pp;
903*b89261baSDavid van Moolenbroek 	struct kinfo_lwp *pl;
904*b89261baSDavid van Moolenbroek 	long cputime;
905*b89261baSDavid van Moolenbroek 	double pct;
906*b89261baSDavid van Moolenbroek 	struct handle *hp;
907*b89261baSDavid van Moolenbroek 	const char *statep;
908*b89261baSDavid van Moolenbroek #ifdef KI_NOCPU
909*b89261baSDavid van Moolenbroek 	char state[10];
910*b89261baSDavid van Moolenbroek #endif
911*b89261baSDavid van Moolenbroek 	char wmesg[KI_WMESGLEN + 1];
912*b89261baSDavid van Moolenbroek 	static char fmt[MAX_COLS];		/* static area where result is built */
913*b89261baSDavid van Moolenbroek 	int uid;
914*b89261baSDavid van Moolenbroek 
915*b89261baSDavid van Moolenbroek 	/* find and remember the next proc structure */
916*b89261baSDavid van Moolenbroek 	hp = (struct handle *)handle;
917*b89261baSDavid van Moolenbroek 	pl = (struct kinfo_lwp *)*(hp->next_proc++);
918*b89261baSDavid van Moolenbroek 	hp->remaining--;
919*b89261baSDavid van Moolenbroek 	pp = proc_from_thread(pl);
920*b89261baSDavid van Moolenbroek 
921*b89261baSDavid van Moolenbroek 	/* get the process's user struct and set cputime */
922*b89261baSDavid van Moolenbroek 	uid = pp ? pp->p_ruid : 0;
923*b89261baSDavid van Moolenbroek 
924*b89261baSDavid van Moolenbroek 	cputime = pl->l_rtime_sec;
925*b89261baSDavid van Moolenbroek 
926*b89261baSDavid van Moolenbroek 	/* calculate the base for CPU percentages */
927*b89261baSDavid van Moolenbroek 	pct = pctdouble(pl->l_pctcpu);
928*b89261baSDavid van Moolenbroek 
929*b89261baSDavid van Moolenbroek 	if (pl->l_stat == LSSLEEP) {
930*b89261baSDavid van Moolenbroek 		strlcpy(wmesg, pl->l_wmesg, sizeof(wmesg));
931*b89261baSDavid van Moolenbroek 		statep = wmesg;
932*b89261baSDavid van Moolenbroek 	} else
933*b89261baSDavid van Moolenbroek 		statep = state_abbrev[(unsigned)pl->l_stat];
934*b89261baSDavid van Moolenbroek 
935*b89261baSDavid van Moolenbroek #ifdef KI_NOCPU
936*b89261baSDavid van Moolenbroek 	/* Post-1.5 change: add CPU number if appropriate */
937*b89261baSDavid van Moolenbroek 	if (pl->l_cpuid != KI_NOCPU && ncpu > 1) {
938*b89261baSDavid van Moolenbroek 		switch (pl->l_stat) {
939*b89261baSDavid van Moolenbroek 		case LSONPROC:
940*b89261baSDavid van Moolenbroek 		case LSRUN:
941*b89261baSDavid van Moolenbroek 		case LSSLEEP:
942*b89261baSDavid van Moolenbroek 		case LSIDL:
943*b89261baSDavid van Moolenbroek 			(void)snprintf(state, sizeof(state), "%.6s/%u",
944*b89261baSDavid van Moolenbroek 			     statep, (unsigned int)pl->l_cpuid);
945*b89261baSDavid van Moolenbroek 			statep = state;
946*b89261baSDavid van Moolenbroek 			break;
947*b89261baSDavid van Moolenbroek 		}
948*b89261baSDavid van Moolenbroek 	}
949*b89261baSDavid van Moolenbroek #endif
950*b89261baSDavid van Moolenbroek 
951*b89261baSDavid van Moolenbroek 	if (pl->l_name[0] == '\0') {
952*b89261baSDavid van Moolenbroek 		pl->l_name[0] = '-';
953*b89261baSDavid van Moolenbroek 		pl->l_name[1] = '\0';
954*b89261baSDavid van Moolenbroek 	}
955*b89261baSDavid van Moolenbroek 
956*b89261baSDavid van Moolenbroek 	/* format this entry */
957*b89261baSDavid van Moolenbroek 	sprintf(fmt,
958*b89261baSDavid van Moolenbroek 	    Thread_format,
959*b89261baSDavid van Moolenbroek 	    pl->l_pid,
960*b89261baSDavid van Moolenbroek 	    pl->l_lid,
961*b89261baSDavid van Moolenbroek 	    (*userprint)(uid),
962*b89261baSDavid van Moolenbroek 	    pl->l_priority,
963*b89261baSDavid van Moolenbroek 	    statep,
964*b89261baSDavid van Moolenbroek 	    format_time(cputime),
965*b89261baSDavid van Moolenbroek 	    100.0 * weighted_cpu(l_, pct, pl),
966*b89261baSDavid van Moolenbroek 	    100.0 * pct,
967*b89261baSDavid van Moolenbroek 	    printable(pl->l_name),
968*b89261baSDavid van Moolenbroek 	    get_command(hp->sel, pp));
969*b89261baSDavid van Moolenbroek 
970*b89261baSDavid van Moolenbroek 	/* return the result */
971*b89261baSDavid van Moolenbroek 	return(fmt);
972*b89261baSDavid van Moolenbroek }
973*b89261baSDavid van Moolenbroek 
974*b89261baSDavid van Moolenbroek /* comparison routines for qsort */
975*b89261baSDavid van Moolenbroek 
976*b89261baSDavid van Moolenbroek /*
977*b89261baSDavid van Moolenbroek  * There are currently four possible comparison routines.  main selects
978*b89261baSDavid van Moolenbroek  * one of these by indexing in to the array proc_compares.
979*b89261baSDavid van Moolenbroek  *
980*b89261baSDavid van Moolenbroek  * Possible keys are defined as macros below.  Currently these keys are
981*b89261baSDavid van Moolenbroek  * defined:  percent CPU, CPU ticks, process state, resident set size,
982*b89261baSDavid van Moolenbroek  * total virtual memory usage.  The process states are ordered as follows
983*b89261baSDavid van Moolenbroek  * (from least to most important):  WAIT, zombie, sleep, stop, start, run.
984*b89261baSDavid van Moolenbroek  * The array declaration below maps a process state index into a number
985*b89261baSDavid van Moolenbroek  * that reflects this ordering.
986*b89261baSDavid van Moolenbroek  */
987*b89261baSDavid van Moolenbroek 
988*b89261baSDavid van Moolenbroek /*
989*b89261baSDavid van Moolenbroek  * First, the possible comparison keys.  These are defined in such a way
990*b89261baSDavid van Moolenbroek  * that they can be merely listed in the source code to define the actual
991*b89261baSDavid van Moolenbroek  * desired ordering.
992*b89261baSDavid van Moolenbroek  */
993*b89261baSDavid van Moolenbroek 
994*b89261baSDavid van Moolenbroek #define ORDERKEY_PCTCPU(pfx) \
995*b89261baSDavid van Moolenbroek 	if (lresult = (pctcpu)(p2)->pfx ## pctcpu - (pctcpu)(p1)->pfx ## pctcpu,\
996*b89261baSDavid van Moolenbroek 	    (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
997*b89261baSDavid van Moolenbroek 
998*b89261baSDavid van Moolenbroek #define ORDERKEY_CPTICKS(pfx) \
999*b89261baSDavid van Moolenbroek 	if (lresult = (pctcpu)(p2)->pfx ## rtime_sec \
1000*b89261baSDavid van Moolenbroek 		    - (pctcpu)(p1)->pfx ## rtime_sec,\
1001*b89261baSDavid van Moolenbroek 	    (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
1002*b89261baSDavid van Moolenbroek 
1003*b89261baSDavid van Moolenbroek #define ORDERKEY_STATE(pfx) \
1004*b89261baSDavid van Moolenbroek 	if ((result = sorted_state[(int)(p2)->pfx ## stat] - \
1005*b89261baSDavid van Moolenbroek 		      sorted_state[(int)(p1)->pfx ## stat] ) == 0)
1006*b89261baSDavid van Moolenbroek 
1007*b89261baSDavid van Moolenbroek #define ORDERKEY_PRIO(pfx) \
1008*b89261baSDavid van Moolenbroek 	if ((result = (p2)->pfx ## priority - (p1)->pfx ## priority) == 0)
1009*b89261baSDavid van Moolenbroek 
1010*b89261baSDavid van Moolenbroek #define ORDERKEY_RSSIZE \
1011*b89261baSDavid van Moolenbroek 	if ((result = p2->p_vm_rssize - p1->p_vm_rssize) == 0)
1012*b89261baSDavid van Moolenbroek 
1013*b89261baSDavid van Moolenbroek #define ORDERKEY_MEM	\
1014*b89261baSDavid van Moolenbroek 	if ((result = (PROCSIZE(p2) - PROCSIZE(p1))) == 0)
1015*b89261baSDavid van Moolenbroek #define ORDERKEY_SIZE(v1, v2)	\
1016*b89261baSDavid van Moolenbroek 	if ((result = (v2 - v1)) == 0)
1017*b89261baSDavid van Moolenbroek 
1018*b89261baSDavid van Moolenbroek /*
1019*b89261baSDavid van Moolenbroek  * Now the array that maps process state to a weight.
1020*b89261baSDavid van Moolenbroek  * The order of the elements should match those in state_abbrev[]
1021*b89261baSDavid van Moolenbroek  */
1022*b89261baSDavid van Moolenbroek 
1023*b89261baSDavid van Moolenbroek static int sorted_state[] = {
1024*b89261baSDavid van Moolenbroek 	0,	/*  (not used)	  ?	*/
1025*b89261baSDavid van Moolenbroek 	1,	/* "start"	SIDL	*/
1026*b89261baSDavid van Moolenbroek 	4,	/* "run"	SRUN	*/
1027*b89261baSDavid van Moolenbroek 	3,	/* "sleep"	SSLEEP	*/
1028*b89261baSDavid van Moolenbroek 	3,	/* "stop"	SSTOP	*/
1029*b89261baSDavid van Moolenbroek 	2,	/* "dead"	SDEAD	*/
1030*b89261baSDavid van Moolenbroek 	1,	/* "zomb"	SZOMB	*/
1031*b89261baSDavid van Moolenbroek 	5,	/* "onproc"	SONPROC	*/
1032*b89261baSDavid van Moolenbroek };
1033*b89261baSDavid van Moolenbroek 
1034*b89261baSDavid van Moolenbroek /* compare_cpu - the comparison function for sorting by CPU percentage */
1035*b89261baSDavid van Moolenbroek 
1036*b89261baSDavid van Moolenbroek static int
compare_cpu(pp1,pp2)1037*b89261baSDavid van Moolenbroek compare_cpu(pp1, pp2)
1038*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1039*b89261baSDavid van Moolenbroek {
1040*b89261baSDavid van Moolenbroek 	int result;
1041*b89261baSDavid van Moolenbroek 	pctcpu lresult;
1042*b89261baSDavid van Moolenbroek 
1043*b89261baSDavid van Moolenbroek 	if (threadmode) {
1044*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1045*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1046*b89261baSDavid van Moolenbroek 
1047*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(l_)
1048*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(l_)
1049*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(l_)
1050*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(l_)
1051*b89261baSDavid van Moolenbroek 		return result;
1052*b89261baSDavid van Moolenbroek 	} else {
1053*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1054*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1055*b89261baSDavid van Moolenbroek 
1056*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(p_)
1057*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(p_)
1058*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(p_)
1059*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(p_)
1060*b89261baSDavid van Moolenbroek 		ORDERKEY_RSSIZE
1061*b89261baSDavid van Moolenbroek 		ORDERKEY_MEM
1062*b89261baSDavid van Moolenbroek 		return result;
1063*b89261baSDavid van Moolenbroek 	}
1064*b89261baSDavid van Moolenbroek 
1065*b89261baSDavid van Moolenbroek 	return (result);
1066*b89261baSDavid van Moolenbroek }
1067*b89261baSDavid van Moolenbroek 
1068*b89261baSDavid van Moolenbroek /* compare_prio - the comparison function for sorting by process priority */
1069*b89261baSDavid van Moolenbroek 
1070*b89261baSDavid van Moolenbroek static int
compare_prio(pp1,pp2)1071*b89261baSDavid van Moolenbroek compare_prio(pp1, pp2)
1072*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1073*b89261baSDavid van Moolenbroek {
1074*b89261baSDavid van Moolenbroek 	int result;
1075*b89261baSDavid van Moolenbroek 	pctcpu lresult;
1076*b89261baSDavid van Moolenbroek 
1077*b89261baSDavid van Moolenbroek 	if (threadmode) {
1078*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1079*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1080*b89261baSDavid van Moolenbroek 
1081*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(l_)
1082*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(l_)
1083*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(l_)
1084*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(l_)
1085*b89261baSDavid van Moolenbroek 		return result;
1086*b89261baSDavid van Moolenbroek 	} else {
1087*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1088*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1089*b89261baSDavid van Moolenbroek 
1090*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(p_)
1091*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(p_)
1092*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(p_)
1093*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(p_)
1094*b89261baSDavid van Moolenbroek 		ORDERKEY_RSSIZE
1095*b89261baSDavid van Moolenbroek 		ORDERKEY_MEM
1096*b89261baSDavid van Moolenbroek 		return result;
1097*b89261baSDavid van Moolenbroek 	}
1098*b89261baSDavid van Moolenbroek 
1099*b89261baSDavid van Moolenbroek 	return (result);
1100*b89261baSDavid van Moolenbroek }
1101*b89261baSDavid van Moolenbroek 
1102*b89261baSDavid van Moolenbroek /* compare_res - the comparison function for sorting by resident set size */
1103*b89261baSDavid van Moolenbroek 
1104*b89261baSDavid van Moolenbroek static int
compare_res(pp1,pp2)1105*b89261baSDavid van Moolenbroek compare_res(pp1, pp2)
1106*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1107*b89261baSDavid van Moolenbroek {
1108*b89261baSDavid van Moolenbroek 	int result;
1109*b89261baSDavid van Moolenbroek 	pctcpu lresult;
1110*b89261baSDavid van Moolenbroek 
1111*b89261baSDavid van Moolenbroek 	if (threadmode) {
1112*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1113*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1114*b89261baSDavid van Moolenbroek 
1115*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(l_)
1116*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(l_)
1117*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(l_)
1118*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(l_)
1119*b89261baSDavid van Moolenbroek 		return result;
1120*b89261baSDavid van Moolenbroek 	} else {
1121*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1122*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1123*b89261baSDavid van Moolenbroek 
1124*b89261baSDavid van Moolenbroek 		ORDERKEY_RSSIZE
1125*b89261baSDavid van Moolenbroek 		ORDERKEY_MEM
1126*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(p_)
1127*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(p_)
1128*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(p_)
1129*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(p_)
1130*b89261baSDavid van Moolenbroek 		return result;
1131*b89261baSDavid van Moolenbroek 	}
1132*b89261baSDavid van Moolenbroek 
1133*b89261baSDavid van Moolenbroek 	return (result);
1134*b89261baSDavid van Moolenbroek }
1135*b89261baSDavid van Moolenbroek 
1136*b89261baSDavid van Moolenbroek static int
compare_pid(pp1,pp2)1137*b89261baSDavid van Moolenbroek compare_pid(pp1, pp2)
1138*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1139*b89261baSDavid van Moolenbroek {
1140*b89261baSDavid van Moolenbroek 	if (threadmode) {
1141*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
1142*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
1143*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = proc_from_thread(l1);
1144*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = proc_from_thread(l2);
1145*b89261baSDavid van Moolenbroek 		return p2->p_pid - p1->p_pid;
1146*b89261baSDavid van Moolenbroek 	} else {
1147*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1148*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1149*b89261baSDavid van Moolenbroek 		return p2->p_pid - p1->p_pid;
1150*b89261baSDavid van Moolenbroek 	}
1151*b89261baSDavid van Moolenbroek }
1152*b89261baSDavid van Moolenbroek 
1153*b89261baSDavid van Moolenbroek static int
compare_command(pp1,pp2)1154*b89261baSDavid van Moolenbroek compare_command(pp1, pp2)
1155*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1156*b89261baSDavid van Moolenbroek {
1157*b89261baSDavid van Moolenbroek 	if (threadmode) {
1158*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
1159*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
1160*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = proc_from_thread(l1);
1161*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = proc_from_thread(l2);
1162*b89261baSDavid van Moolenbroek 		return strcmp(p2->p_comm, p1->p_comm);
1163*b89261baSDavid van Moolenbroek 	} else {
1164*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1165*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1166*b89261baSDavid van Moolenbroek 		return strcmp(p2->p_comm, p1->p_comm);
1167*b89261baSDavid van Moolenbroek 	}
1168*b89261baSDavid van Moolenbroek }
1169*b89261baSDavid van Moolenbroek 
1170*b89261baSDavid van Moolenbroek static int
compare_username(pp1,pp2)1171*b89261baSDavid van Moolenbroek compare_username(pp1, pp2)
1172*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1173*b89261baSDavid van Moolenbroek {
1174*b89261baSDavid van Moolenbroek 	if (threadmode) {
1175*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
1176*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
1177*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = proc_from_thread(l1);
1178*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = proc_from_thread(l2);
1179*b89261baSDavid van Moolenbroek 		return strcmp(p2->p_login, p1->p_login);
1180*b89261baSDavid van Moolenbroek 	} else {
1181*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1182*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1183*b89261baSDavid van Moolenbroek 		return strcmp(p2->p_login, p1->p_login);
1184*b89261baSDavid van Moolenbroek 	}
1185*b89261baSDavid van Moolenbroek }
1186*b89261baSDavid van Moolenbroek /* compare_size - the comparison function for sorting by total memory usage */
1187*b89261baSDavid van Moolenbroek 
1188*b89261baSDavid van Moolenbroek static int
compare_size(pp1,pp2)1189*b89261baSDavid van Moolenbroek compare_size(pp1, pp2)
1190*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1191*b89261baSDavid van Moolenbroek {
1192*b89261baSDavid van Moolenbroek 	int result;
1193*b89261baSDavid van Moolenbroek 	pctcpu lresult;
1194*b89261baSDavid van Moolenbroek 
1195*b89261baSDavid van Moolenbroek 	if (threadmode) {
1196*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1197*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1198*b89261baSDavid van Moolenbroek 
1199*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(l_)
1200*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(l_)
1201*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(l_)
1202*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(l_)
1203*b89261baSDavid van Moolenbroek 		return result;
1204*b89261baSDavid van Moolenbroek 	} else {
1205*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1206*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1207*b89261baSDavid van Moolenbroek 
1208*b89261baSDavid van Moolenbroek 		ORDERKEY_MEM
1209*b89261baSDavid van Moolenbroek 		ORDERKEY_RSSIZE
1210*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(p_)
1211*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(p_)
1212*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(p_)
1213*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(p_)
1214*b89261baSDavid van Moolenbroek 		return result;
1215*b89261baSDavid van Moolenbroek 	}
1216*b89261baSDavid van Moolenbroek 
1217*b89261baSDavid van Moolenbroek 	return (result);
1218*b89261baSDavid van Moolenbroek }
1219*b89261baSDavid van Moolenbroek 
1220*b89261baSDavid van Moolenbroek /* compare_state - the comparison function for sorting by process state */
1221*b89261baSDavid van Moolenbroek 
1222*b89261baSDavid van Moolenbroek static int
compare_state(pp1,pp2)1223*b89261baSDavid van Moolenbroek compare_state(pp1, pp2)
1224*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1225*b89261baSDavid van Moolenbroek {
1226*b89261baSDavid van Moolenbroek 	int result;
1227*b89261baSDavid van Moolenbroek 	pctcpu lresult;
1228*b89261baSDavid van Moolenbroek 
1229*b89261baSDavid van Moolenbroek 	if (threadmode) {
1230*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1231*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1232*b89261baSDavid van Moolenbroek 
1233*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(l_)
1234*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(l_)
1235*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(l_)
1236*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(l_)
1237*b89261baSDavid van Moolenbroek 		return result;
1238*b89261baSDavid van Moolenbroek 	} else {
1239*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1240*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1241*b89261baSDavid van Moolenbroek 
1242*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(p_)
1243*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(p_)
1244*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(p_)
1245*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(p_)
1246*b89261baSDavid van Moolenbroek 		ORDERKEY_RSSIZE
1247*b89261baSDavid van Moolenbroek 		ORDERKEY_MEM
1248*b89261baSDavid van Moolenbroek 		return result;
1249*b89261baSDavid van Moolenbroek 	}
1250*b89261baSDavid van Moolenbroek 
1251*b89261baSDavid van Moolenbroek 	return (result);
1252*b89261baSDavid van Moolenbroek }
1253*b89261baSDavid van Moolenbroek 
1254*b89261baSDavid van Moolenbroek /* compare_time - the comparison function for sorting by total CPU time */
1255*b89261baSDavid van Moolenbroek 
1256*b89261baSDavid van Moolenbroek static int
compare_time(pp1,pp2)1257*b89261baSDavid van Moolenbroek compare_time(pp1, pp2)
1258*b89261baSDavid van Moolenbroek 	struct proc **pp1, **pp2;
1259*b89261baSDavid van Moolenbroek {
1260*b89261baSDavid van Moolenbroek 	int result;
1261*b89261baSDavid van Moolenbroek 	pctcpu lresult;
1262*b89261baSDavid van Moolenbroek 
1263*b89261baSDavid van Moolenbroek 	if (threadmode) {
1264*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1265*b89261baSDavid van Moolenbroek 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1266*b89261baSDavid van Moolenbroek 
1267*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(l_)
1268*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(l_)
1269*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(l_)
1270*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(l_)
1271*b89261baSDavid van Moolenbroek 		return result;
1272*b89261baSDavid van Moolenbroek 	} else {
1273*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1274*b89261baSDavid van Moolenbroek 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1275*b89261baSDavid van Moolenbroek 
1276*b89261baSDavid van Moolenbroek 		ORDERKEY_CPTICKS(p_)
1277*b89261baSDavid van Moolenbroek 		ORDERKEY_PCTCPU(p_)
1278*b89261baSDavid van Moolenbroek 		ORDERKEY_STATE(p_)
1279*b89261baSDavid van Moolenbroek 		ORDERKEY_PRIO(p_)
1280*b89261baSDavid van Moolenbroek 		ORDERKEY_MEM
1281*b89261baSDavid van Moolenbroek 		ORDERKEY_RSSIZE
1282*b89261baSDavid van Moolenbroek 		return result;
1283*b89261baSDavid van Moolenbroek 	}
1284*b89261baSDavid van Moolenbroek 
1285*b89261baSDavid van Moolenbroek 	return (result);
1286*b89261baSDavid van Moolenbroek }
1287*b89261baSDavid van Moolenbroek 
1288*b89261baSDavid van Moolenbroek 
1289*b89261baSDavid van Moolenbroek /*
1290*b89261baSDavid van Moolenbroek  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
1291*b89261baSDavid van Moolenbroek  *		the process does not exist.
1292*b89261baSDavid van Moolenbroek  *		It is EXTREMLY IMPORTANT that this function work correctly.
1293*b89261baSDavid van Moolenbroek  *		If top runs setuid root (as in SVR4), then this function
1294*b89261baSDavid van Moolenbroek  *		is the only thing that stands in the way of a serious
1295*b89261baSDavid van Moolenbroek  *		security problem.  It validates requests for the "kill"
1296*b89261baSDavid van Moolenbroek  *		and "renice" commands.
1297*b89261baSDavid van Moolenbroek  */
1298*b89261baSDavid van Moolenbroek 
1299*b89261baSDavid van Moolenbroek int
proc_owner(pid)1300*b89261baSDavid van Moolenbroek proc_owner(pid)
1301*b89261baSDavid van Moolenbroek 	int pid;
1302*b89261baSDavid van Moolenbroek {
1303*b89261baSDavid van Moolenbroek 	int cnt;
1304*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 **prefp;
1305*b89261baSDavid van Moolenbroek 	struct kinfo_proc2 *pp;
1306*b89261baSDavid van Moolenbroek 
1307*b89261baSDavid van Moolenbroek 	if (threadmode)
1308*b89261baSDavid van Moolenbroek 		return(-1);
1309*b89261baSDavid van Moolenbroek 
1310*b89261baSDavid van Moolenbroek 	prefp = pref;
1311*b89261baSDavid van Moolenbroek 	cnt = pref_len;
1312*b89261baSDavid van Moolenbroek 	while (--cnt >= 0) {
1313*b89261baSDavid van Moolenbroek 		pp = *prefp++;
1314*b89261baSDavid van Moolenbroek 		if (pp->p_pid == (pid_t)pid)
1315*b89261baSDavid van Moolenbroek 			return(pp->p_ruid);
1316*b89261baSDavid van Moolenbroek 	}
1317*b89261baSDavid van Moolenbroek 	return(-1);
1318*b89261baSDavid van Moolenbroek }
1319*b89261baSDavid van Moolenbroek 
1320*b89261baSDavid van Moolenbroek /*
1321*b89261baSDavid van Moolenbroek  *  percentages(cnt, out, new, old, diffs) - calculate percentage change
1322*b89261baSDavid van Moolenbroek  *	between array "old" and "new", putting the percentages i "out".
1323*b89261baSDavid van Moolenbroek  *	"cnt" is size of each array and "diffs" is used for scratch space.
1324*b89261baSDavid van Moolenbroek  *	The array "old" is updated on each call.
1325*b89261baSDavid van Moolenbroek  *	The routine assumes modulo arithmetic.  This function is especially
1326*b89261baSDavid van Moolenbroek  *	useful on BSD mchines for calculating CPU state percentages.
1327*b89261baSDavid van Moolenbroek  */
1328*b89261baSDavid van Moolenbroek 
1329*b89261baSDavid van Moolenbroek static void
percentages64(cnt,out,new,old,diffs)1330*b89261baSDavid van Moolenbroek percentages64(cnt, out, new, old, diffs)
1331*b89261baSDavid van Moolenbroek 	int cnt;
1332*b89261baSDavid van Moolenbroek 	int *out;
1333*b89261baSDavid van Moolenbroek 	u_int64_t *new;
1334*b89261baSDavid van Moolenbroek 	u_int64_t *old;
1335*b89261baSDavid van Moolenbroek 	u_int64_t *diffs;
1336*b89261baSDavid van Moolenbroek {
1337*b89261baSDavid van Moolenbroek 	int i;
1338*b89261baSDavid van Moolenbroek 	u_int64_t change;
1339*b89261baSDavid van Moolenbroek 	u_int64_t total_change;
1340*b89261baSDavid van Moolenbroek 	u_int64_t *dp;
1341*b89261baSDavid van Moolenbroek 	u_int64_t half_total;
1342*b89261baSDavid van Moolenbroek 
1343*b89261baSDavid van Moolenbroek 	/* initialization */
1344*b89261baSDavid van Moolenbroek 	total_change = 0;
1345*b89261baSDavid van Moolenbroek 	dp = diffs;
1346*b89261baSDavid van Moolenbroek 
1347*b89261baSDavid van Moolenbroek 	/* calculate changes for each state and the overall change */
1348*b89261baSDavid van Moolenbroek 	for (i = 0; i < cnt; i++) {
1349*b89261baSDavid van Moolenbroek 		/*
1350*b89261baSDavid van Moolenbroek 		 * Don't worry about wrapping - even at hz=1GHz, a
1351*b89261baSDavid van Moolenbroek 		 * u_int64_t will last at least 544 years.
1352*b89261baSDavid van Moolenbroek 		 */
1353*b89261baSDavid van Moolenbroek 		change = *new - *old;
1354*b89261baSDavid van Moolenbroek 		total_change += (*dp++ = change);
1355*b89261baSDavid van Moolenbroek 		*old++ = *new++;
1356*b89261baSDavid van Moolenbroek 	}
1357*b89261baSDavid van Moolenbroek 
1358*b89261baSDavid van Moolenbroek 	/* avoid divide by zero potential */
1359*b89261baSDavid van Moolenbroek 	if (total_change == 0)
1360*b89261baSDavid van Moolenbroek 		total_change = 1;
1361*b89261baSDavid van Moolenbroek 
1362*b89261baSDavid van Moolenbroek 	/* calculate percentages based on overall change, rounding up */
1363*b89261baSDavid van Moolenbroek 	half_total = total_change / 2;
1364*b89261baSDavid van Moolenbroek 	for (i = 0; i < cnt; i++)
1365*b89261baSDavid van Moolenbroek 		*out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
1366*b89261baSDavid van Moolenbroek }
1367