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