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