xref: /netbsd-src/external/bsd/top/dist/machine/m_netbsd.c (revision 3816d47b2c42fcd6e549e3407f842a5b1a1d23ad)
1 /*	$NetBSD: m_netbsd.c,v 1.11 2009/10/21 21:11:57 rmind 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.11 2009/10/21 21:11:57 rmind Exp $
41  */
42 #include <sys/cdefs.h>
43 
44 #ifndef lint
45 __RCSID("$NetBSD: m_netbsd.c,v 1.11 2009/10/21 21:11:57 rmind 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.*f%% %5.*f%% %.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 const 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 const 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 const 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 const 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 const 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(struct system_info *si)
418 {
419 	size_t ssize;
420 	int mib[2];
421 	struct uvmexp_sysctl uvmexp;
422 	struct swapent *sep;
423 	u_int64_t totalsize, totalinuse;
424 	int size, inuse, ncounted, i;
425 	int rnswap, nswap;
426 
427 	mib[0] = CTL_KERN;
428 	mib[1] = KERN_CP_TIME;
429 	ssize = sizeof(cp_time[0]) * CPUSTATES * ncpu;
430 	if (sysctl(mib, 2, cp_time, &ssize, NULL, 0) < 0) {
431 		fprintf(stderr, "top: sysctl kern.cp_time failed: %s\n",
432 		    strerror(errno));
433 		quit(23);
434 	}
435 
436 	if (getloadavg(si->load_avg, NUM_AVERAGES) < 0) {
437 		int j;
438 
439 		warn("can't getloadavg");
440 		for (j = 0; j < NUM_AVERAGES; j++)
441 			si->load_avg[j] = 0.0;
442 	}
443 
444 	/* convert cp_time counts to percentages */
445 	for (i = 0; i < ncpu; i++) {
446 	    int j = i * CPUSTATES;
447 	    percentages64(CPUSTATES, cpu_states + j, cp_time + j, cp_old + j,
448 		cp_diff + j);
449 	}
450 
451 	mib[0] = CTL_VM;
452 	mib[1] = VM_UVMEXP2;
453 	ssize = sizeof(uvmexp);
454 	if (sysctl(mib, 2, &uvmexp, &ssize, NULL, 0) < 0) {
455 		fprintf(stderr, "top: sysctl vm.uvmexp2 failed: %s\n",
456 		    strerror(errno));
457 		quit(23);
458 	}
459 
460 	/* convert memory stats to Kbytes */
461 	memory_stats[0] = pagetok(uvmexp.active);
462 	memory_stats[1] = pagetok(uvmexp.inactive);
463 	memory_stats[2] = pagetok(uvmexp.wired);
464 	memory_stats[3] = pagetok(uvmexp.execpages);
465 	memory_stats[4] = pagetok(uvmexp.filepages);
466 	memory_stats[5] = pagetok(uvmexp.free);
467 
468 	swap_stats[0] = swap_stats[1] = swap_stats[2] = 0;
469 
470 	do {
471 		nswap = swapctl(SWAP_NSWAP, 0, 0);
472 		if (nswap < 1)
473 			break;
474 		if (nswap > maxswap) {
475 			if (swapp)
476 				free(swapp);
477 			swapp = sep = malloc(nswap * sizeof(*sep));
478 			if (sep == NULL)
479 				break;
480 			maxswap = nswap;
481 		} else
482 			sep = swapp;
483 		rnswap = swapctl(SWAP_STATS, (void *)sep, nswap);
484 		if (nswap != rnswap)
485 			break;
486 
487 		totalsize = totalinuse = ncounted = 0;
488 		for (; rnswap-- > 0; sep++) {
489 			ncounted++;
490 			size = sep->se_nblks;
491 			inuse = sep->se_inuse;
492 			totalsize += size;
493 			totalinuse += inuse;
494 		}
495 		swap_stats[0] = dbtob(totalsize) / 1024;
496 		swap_stats[1] = dbtob(totalinuse) / 1024;
497 		swap_stats[2] = dbtob(totalsize) / 1024 - swap_stats[1];
498 	} while (0);
499 
500 	memory_stats[6] = -1;
501 	swap_stats[3] = -1;
502 
503 	/* set arrays and strings */
504 	si->cpustates = cpu_states;
505 	si->memory = memory_stats;
506 	si->swap = swap_stats;
507 	si->last_pid = -1;
508 
509 }
510 
511 static struct kinfo_proc2 *
512 proc_from_thread(struct kinfo_lwp *pl)
513 {
514 	struct kinfo_proc2 *pp = thread_pbase;
515 	int i;
516 
517 	for (i = 0; i < thread_nproc; i++, pp++)
518 		if ((pid_t)pp->p_pid == (pid_t)pl->l_pid)
519 			return pp;
520 	return NULL;
521 }
522 
523 static int
524 uid_from_thread(struct kinfo_lwp *pl)
525 {
526 	struct kinfo_proc2 *pp;
527 
528 	if ((pp = proc_from_thread(pl)) == NULL)
529 		return -1;
530 	return pp->p_ruid;
531 }
532 
533 caddr_t
534 get_process_info(struct system_info *si, struct process_select *sel, int c)
535 {
536 	userprint = sel->usernames ? username : itoa7;
537 
538 	if ((threadmode = sel->threads) != 0)
539 		return get_lwp_info(si, sel, proc_compares[c]);
540 	else
541 		return get_proc_info(si, sel, proc_compares[c]);
542 }
543 
544 static caddr_t
545 get_proc_info(struct system_info *si, struct process_select *sel,
546 	      int (*compare)(struct proc **, struct proc **))
547 {
548 	int i;
549 	int total_procs;
550 	int active_procs;
551 	struct kinfo_proc2 **prefp, **n;
552 	struct kinfo_proc2 *pp;
553 	int op, arg;
554 
555 	/* these are copied out of sel for speed */
556 	int show_idle;
557 	int show_system;
558 	int show_uid;
559 	int show_command;
560 
561 	static struct handle handle;
562 
563 	procgen++;
564 
565 	if (sel->pid == (pid_t)-1) {
566 		op = KERN_PROC_ALL;
567 		arg = 0;
568 	} else {
569 		op = KERN_PROC_PID;
570 		arg = sel->pid;
571 	}
572 
573 	pbase = kvm_getproc2(kd, op, arg, sizeof(struct kinfo_proc2), &nproc);
574 	if (pbase == NULL) {
575 		if (sel->pid != (pid_t)-1) {
576 			nproc = 0;
577 		} else {
578 			(void) fprintf(stderr, "top: Out of memory.\n");
579 			quit(23);
580 		}
581 	}
582 	if (nproc > onproc) {
583 		n = (struct kinfo_proc2 **) realloc(pref,
584 		    sizeof(struct kinfo_proc2 *) * nproc);
585 		if (n == NULL) {
586 			(void) fprintf(stderr, "top: Out of memory.\n");
587 			quit(23);
588 		}
589 		pref = n;
590 		onproc = nproc;
591 	}
592 	/* get a pointer to the states summary array */
593 	si->procstates = process_states;
594 
595 	/* set up flags which define what we are going to select */
596 	show_idle = sel->idle;
597 	show_system = sel->system;
598 	show_uid = sel->uid != -1;
599 	show_command = sel->command != NULL;
600 
601 	/* count up process states and get pointers to interesting procs */
602 	total_procs = 0;
603 	active_procs = 0;
604 	memset((char *)process_states, 0, sizeof(process_states));
605 	prefp = pref;
606 	for (pp = pbase, i = 0; i < nproc; pp++, i++) {
607 
608 		/*
609 		 * Place pointers to each valid proc structure in pref[].
610 		 * Process slots that are actually in use have a non-zero
611 		 * status field.  Processes with P_SYSTEM set are system
612 		 * processes---these get ignored unless show_sysprocs is set.
613 		 */
614 		if (pp->p_stat != 0 && (show_system || ((pp->p_flag & P_SYSTEM) == 0))) {
615 			total_procs++;
616 			process_states[(unsigned char) pp->p_stat]++;
617 			if (pp->p_stat != LSZOMB &&
618 			    (show_idle || (pp->p_pctcpu != 0) ||
619 			    (pp->p_stat == LSRUN || pp->p_stat == LSONPROC)) &&
620 			    (!show_uid || pp->p_ruid == (uid_t)sel->uid)) {
621 				*prefp++ = pp;
622 				active_procs++;
623 			}
624 		}
625 	}
626 
627 	/* if requested, sort the "interesting" processes */
628 	if (compare != NULL) {
629 		qsort((char *)pref, active_procs, sizeof(struct kinfo_proc2 *),
630 		    (int (*)(const void *, const void *))compare);
631 	}
632 
633 	/* remember active and total counts */
634 	si->p_total = total_procs;
635 	si->p_active = pref_len = active_procs;
636 
637 	/* pass back a handle */
638 	handle.next_proc = pref;
639 	handle.remaining = active_procs;
640 	return((caddr_t)&handle);
641 }
642 
643 static caddr_t
644 get_lwp_info(struct system_info *si, struct process_select *sel,
645 	     int (*compare)(struct proc **, struct proc **))
646 {
647 	int i;
648 	int total_lwps;
649 	int active_lwps;
650 	struct kinfo_lwp **lrefp, **n;
651 	struct kinfo_lwp *lp;
652 	struct kinfo_proc2 *pp;
653 
654 	/* these are copied out of sel for speed */
655 	int show_idle;
656 	int show_system;
657 	int show_uid;
658 	int show_command;
659 
660 	static struct handle handle;
661 
662 	pp = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2),
663 	    &thread_nproc);
664 	if (pp == NULL) {
665 		(void) fprintf(stderr, "top: Out of memory.\n");
666 		quit(23);
667 	}
668 	if (thread_pbase == NULL || thread_nproc != thread_onproc) {
669 		free(thread_pbase);
670 		thread_onproc = thread_nproc;
671 		thread_pbase = calloc(sizeof(struct kinfo_proc2), thread_nproc);
672 		if (thread_pbase == NULL) {
673 			(void) fprintf(stderr, "top: Out of memory.\n");
674 			quit(23);
675 		}
676 	}
677 	memcpy(thread_pbase, pp, sizeof(struct kinfo_proc2) * thread_nproc);
678 
679 	lbase = kvm_getlwps(kd, -1, 0, sizeof(struct kinfo_lwp), &nlwp);
680 	if (lbase == NULL) {
681 #ifdef notyet
682 		if (sel->pid != (pid_t)-1) {
683 			nproc = 0;
684 			nlwp = 0;
685 		}
686 		else
687 #endif
688 		{
689 			(void) fprintf(stderr, "top: Out of memory.\n");
690 			quit(23);
691 		}
692 	}
693 	if (nlwp > onlwp) {
694 		n = (struct kinfo_lwp **) realloc(lref,
695 		    sizeof(struct kinfo_lwp *) * nlwp);
696 		if (n == NULL) {
697 			(void) fprintf(stderr, "top: Out of memory.\n");
698 			quit(23);
699 		}
700 		lref = n;
701 		onlwp = nlwp;
702 	}
703 	/* get a pointer to the states summary array */
704 	si->procstates = process_states;
705 
706 	/* set up flags which define what we are going to select */
707 	show_idle = sel->idle;
708 	show_system = sel->system;
709 	show_uid = sel->uid != -1;
710 	show_command = sel->command != NULL;
711 
712 	/* count up thread states and get pointers to interesting threads */
713 	total_lwps = 0;
714 	active_lwps = 0;
715 	memset((char *)process_states, 0, sizeof(process_states));
716 	lrefp = lref;
717 	for (lp = lbase, i = 0; i < nlwp; lp++, i++) {
718 		if (sel->pid != (pid_t)-1 && sel->pid != (pid_t)lp->l_pid)
719 			continue;
720 
721 		/*
722 		 * Place pointers to each valid lwp structure in lref[].
723 		 * thread slots that are actually in use have a non-zero
724 		 * status field.  threads with L_SYSTEM set are system
725 		 * threads---these get ignored unless show_sysprocs is set.
726 		 */
727 		if (lp->l_stat != 0 && (show_system || ((lp->l_flag & LW_SYSTEM) == 0))) {
728 			total_lwps++;
729 			process_states[(unsigned char) lp->l_stat]++;
730 			if (lp->l_stat != LSZOMB &&
731 			    (show_idle || (lp->l_pctcpu != 0) ||
732 			    (lp->l_stat == LSRUN || lp->l_stat == LSONPROC)) &&
733 			    (!show_uid || uid_from_thread(lp) == sel->uid)) {
734 				*lrefp++ = lp;
735 				active_lwps++;
736 			}
737 		}
738 	}
739 
740 	/* if requested, sort the "interesting" threads */
741 	if (compare != NULL) {
742 		qsort((char *)lref, active_lwps, sizeof(struct kinfo_lwp *),
743 		    (int (*)(const void *, const void *))compare);
744 	}
745 
746 	/* remember active and total counts */
747 	si->p_total = total_lwps;
748 	si->p_active = lref_len = active_lwps;
749 
750 	/* pass back a handle */
751 	handle.next_proc = (struct kinfo_proc2 **)lref;
752 	handle.remaining = active_lwps;
753 
754 	return((caddr_t)&handle);
755 }
756 
757 char *
758 format_next_process(caddr_t handle, char *(*get_userid)(int))
759 {
760 
761 	if (threadmode)
762 		return format_next_lwp(handle, get_userid);
763 	else
764 		return format_next_proc(handle, get_userid);
765 }
766 
767 
768 char *
769 format_next_proc(caddr_t handle, char *(*get_userid)(int))
770 {
771 	struct kinfo_proc2 *pp;
772 	long cputime;
773 	double pct, wcpu, cpu;
774 	struct handle *hp;
775 	const char *statep;
776 #ifdef KI_NOCPU
777 	char state[10];
778 #endif
779 	char wmesg[KI_WMESGLEN + 1];
780 	static char fmt[MAX_COLS];		/* static area where result is built */
781 	const char *pretty = "";
782 
783 	/* find and remember the next proc structure */
784 	hp = (struct handle *)handle;
785 	pp = *(hp->next_proc++);
786 	hp->remaining--;
787 
788 	/* get the process's user struct and set cputime */
789 	if ((pp->p_flag & P_SYSTEM) != 0)
790 		pretty = "[]";
791 
792 	if (pretty[0] != '\0') {
793 		/*
794 		 * Print swapped processes as <pname> and
795 		 * system processes as [pname]
796 		 */
797 		char *comm = pp->p_comm;
798 #define COMSIZ sizeof(pp->p_comm)
799 		char buf[COMSIZ];
800 		(void) strncpy(buf, comm, COMSIZ);
801 		comm[0] = pretty[0];
802 		(void) strncpy(&comm[1], buf, COMSIZ - 2);
803 		comm[COMSIZ - 2] = '\0';
804 		(void) strncat(comm, &pretty[1], COMSIZ - 1);
805 		comm[COMSIZ - 1] = '\0';
806 	}
807 
808 #if 0
809 	/* This does not produce the correct results */
810 	cputime = pp->p_uticks + pp->p_sticks + pp->p_iticks;
811 #else
812 	cputime = pp->p_rtime_sec;	/* This does not count interrupts */
813 #endif
814 
815 	/* calculate the base for CPU percentages */
816 	pct = pctdouble(pp->p_pctcpu);
817 
818 	if (pp->p_stat == LSSLEEP) {
819 		strlcpy(wmesg, pp->p_wmesg, sizeof(wmesg));
820 		statep = wmesg;
821 	} else
822 		statep = state_abbrev[(unsigned)pp->p_stat];
823 
824 #ifdef KI_NOCPU
825 	/* Post-1.5 change: add CPU number if appropriate */
826 	if (pp->p_cpuid != KI_NOCPU && ncpu > 1) {
827 		switch (pp->p_stat) {
828 		case LSONPROC:
829 		case LSRUN:
830 		case LSSLEEP:
831 		case LSIDL:
832 			(void)snprintf(state, sizeof(state), "%.6s/%d",
833 			     statep, get_cpunum(pp->p_cpuid));
834 			statep = state;
835 			break;
836 		}
837 	}
838 #endif
839 	wcpu = 100.0 * weighted_cpu(p_, pct, pp);
840 	cpu = 100.0 * pct;
841 
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 	    (wcpu >= 100.0) ? 0 : 2, wcpu,
854 	    (cpu >= 100.0) ? 0 : 2, cpu,
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 	static char gone[] = "<gone>";
871 #ifdef KI_NOCPU
872 	char state[10];
873 #endif
874 	char wmesg[KI_WMESGLEN + 1];
875 	static char fmt[MAX_COLS];		/* static area where result is built */
876 	const char *pretty = "";
877 	char *comm;
878 	int uid;
879 
880 	/* find and remember the next proc structure */
881 	hp = (struct handle *)handle;
882 	pl = (struct kinfo_lwp *)*(hp->next_proc++);
883 	hp->remaining--;
884 	pp = proc_from_thread(pl);
885 
886 	/* get the process's user struct and set cputime */
887 	if (pp) {
888 		comm = pp->p_comm;
889 		if ((pp->p_flag & P_SYSTEM) != 0)
890 			pretty = "[]";
891 
892 		if (pretty[0] != '\0' && comm[0] != pretty[0]) {
893 			/*
894 			 * Print swapped processes as <pname> and
895 			 * system processes as [pname]
896 			 */
897 #define COMSIZ sizeof(pp->p_comm)
898 			char buf[COMSIZ];
899 			(void) strncpy(buf, comm, COMSIZ);
900 			comm[0] = pretty[0];
901 			(void) strncpy(&comm[1], buf, COMSIZ - 2);
902 			comm[COMSIZ - 2] = '\0';
903 			(void) strncat(comm, &pretty[1], COMSIZ - 1);
904 			comm[COMSIZ - 1] = '\0';
905 		}
906 		uid = pp->p_ruid;
907 	} else {
908 		comm = gone;
909 		uid = 0;
910 	}
911 
912 	cputime = pl->l_rtime_sec;
913 
914 	/* calculate the base for CPU percentages */
915 	pct = pctdouble(pl->l_pctcpu);
916 
917 	if (pl->l_stat == LSSLEEP) {
918 		strlcpy(wmesg, pl->l_wmesg, sizeof(wmesg));
919 		statep = wmesg;
920 	} else
921 		statep = state_abbrev[(unsigned)pl->l_stat];
922 
923 #ifdef KI_NOCPU
924 	/* Post-1.5 change: add CPU number if appropriate */
925 	if (pl->l_cpuid != KI_NOCPU && ncpu > 1) {
926 		switch (pl->l_stat) {
927 		case LSONPROC:
928 		case LSRUN:
929 		case LSSLEEP:
930 		case LSIDL:
931 			(void)snprintf(state, sizeof(state), "%.6s/%d",
932 			     statep, get_cpunum(pl->l_cpuid));
933 			statep = state;
934 			break;
935 		}
936 	}
937 #endif
938 
939 	if (pl->l_name[0] == '\0') {
940 		pl->l_name[0] = '-';
941 		pl->l_name[1] = '\0';
942 	}
943 
944 	/* format this entry */
945 	sprintf(fmt,
946 	    Thread_format,
947 	    pl->l_pid,
948 	    pl->l_lid,
949 	    (*userprint)(uid),
950 	    pl->l_priority,
951 	    statep,
952 	    format_time(cputime),
953 	    100.0 * weighted_cpu(l_, pct, pl),
954 	    100.0 * pct,
955 	    printable(comm),
956 	    printable(pl->l_name));
957 
958 	/* return the result */
959 	return(fmt);
960 }
961 
962 /* comparison routines for qsort */
963 
964 /*
965  * There are currently four possible comparison routines.  main selects
966  * one of these by indexing in to the array proc_compares.
967  *
968  * Possible keys are defined as macros below.  Currently these keys are
969  * defined:  percent CPU, CPU ticks, process state, resident set size,
970  * total virtual memory usage.  The process states are ordered as follows
971  * (from least to most important):  WAIT, zombie, sleep, stop, start, run.
972  * The array declaration below maps a process state index into a number
973  * that reflects this ordering.
974  */
975 
976 /*
977  * First, the possible comparison keys.  These are defined in such a way
978  * that they can be merely listed in the source code to define the actual
979  * desired ordering.
980  */
981 
982 #define ORDERKEY_PCTCPU(pfx) \
983 	if (lresult = (pctcpu)(p2)->pfx ## pctcpu - (pctcpu)(p1)->pfx ## pctcpu,\
984 	    (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
985 
986 #define ORDERKEY_CPTICKS(pfx) \
987 	if (lresult = (pctcpu)(p2)->pfx ## rtime_sec \
988 		    - (pctcpu)(p1)->pfx ## rtime_sec,\
989 	    (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
990 
991 #define ORDERKEY_STATE(pfx) \
992 	if ((result = sorted_state[(int)(p2)->pfx ## stat] - \
993 		      sorted_state[(int)(p1)->pfx ## stat] ) == 0)
994 
995 #define ORDERKEY_PRIO(pfx) \
996 	if ((result = (p2)->pfx ## priority - (p1)->pfx ## priority) == 0)
997 
998 #define ORDERKEY_RSSIZE \
999 	if ((result = p2->p_vm_rssize - p1->p_vm_rssize) == 0)
1000 
1001 #define ORDERKEY_MEM	\
1002 	if ((result = (PROCSIZE(p2) - PROCSIZE(p1))) == 0)
1003 #define ORDERKEY_SIZE(v1, v2)	\
1004 	if ((result = (v2 - v1)) == 0)
1005 
1006 /*
1007  * Now the array that maps process state to a weight.
1008  * The order of the elements should match those in state_abbrev[]
1009  */
1010 
1011 static int sorted_state[] = {
1012 	0,	/*  (not used)	  ?	*/
1013 	1,	/* "start"	SIDL	*/
1014 	4,	/* "run"	SRUN	*/
1015 	3,	/* "sleep"	SSLEEP	*/
1016 	3,	/* "stop"	SSTOP	*/
1017 	2,	/* "dead"	SDEAD	*/
1018 	1,	/* "zomb"	SZOMB	*/
1019 	5,	/* "onproc"	SONPROC	*/
1020 };
1021 
1022 /* compare_cpu - the comparison function for sorting by CPU percentage */
1023 
1024 static int
1025 compare_cpu(pp1, pp2)
1026 	struct proc **pp1, **pp2;
1027 {
1028 	int result;
1029 	pctcpu lresult;
1030 
1031 	if (threadmode) {
1032 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1033 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1034 
1035 		ORDERKEY_PCTCPU(l_)
1036 		ORDERKEY_CPTICKS(l_)
1037 		ORDERKEY_STATE(l_)
1038 		ORDERKEY_PRIO(l_)
1039 		return result;
1040 	} else {
1041 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1042 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1043 
1044 		ORDERKEY_PCTCPU(p_)
1045 		ORDERKEY_CPTICKS(p_)
1046 		ORDERKEY_STATE(p_)
1047 		ORDERKEY_PRIO(p_)
1048 		ORDERKEY_RSSIZE
1049 		ORDERKEY_MEM
1050 		return result;
1051 	}
1052 
1053 	return (result);
1054 }
1055 
1056 /* compare_prio - the comparison function for sorting by process priority */
1057 
1058 static int
1059 compare_prio(pp1, pp2)
1060 	struct proc **pp1, **pp2;
1061 {
1062 	int result;
1063 	pctcpu lresult;
1064 
1065 	if (threadmode) {
1066 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1067 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1068 
1069 		ORDERKEY_PRIO(l_)
1070 		ORDERKEY_PCTCPU(l_)
1071 		ORDERKEY_CPTICKS(l_)
1072 		ORDERKEY_STATE(l_)
1073 		return result;
1074 	} else {
1075 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1076 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1077 
1078 		ORDERKEY_PRIO(p_)
1079 		ORDERKEY_PCTCPU(p_)
1080 		ORDERKEY_CPTICKS(p_)
1081 		ORDERKEY_STATE(p_)
1082 		ORDERKEY_RSSIZE
1083 		ORDERKEY_MEM
1084 		return result;
1085 	}
1086 
1087 	return (result);
1088 }
1089 
1090 /* compare_res - the comparison function for sorting by resident set size */
1091 
1092 static int
1093 compare_res(pp1, pp2)
1094 	struct proc **pp1, **pp2;
1095 {
1096 	int result;
1097 	pctcpu lresult;
1098 
1099 	if (threadmode) {
1100 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1101 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1102 
1103 		ORDERKEY_PCTCPU(l_)
1104 		ORDERKEY_CPTICKS(l_)
1105 		ORDERKEY_STATE(l_)
1106 		ORDERKEY_PRIO(l_)
1107 		return result;
1108 	} else {
1109 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1110 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1111 
1112 		ORDERKEY_RSSIZE
1113 		ORDERKEY_MEM
1114 		ORDERKEY_PCTCPU(p_)
1115 		ORDERKEY_CPTICKS(p_)
1116 		ORDERKEY_STATE(p_)
1117 		ORDERKEY_PRIO(p_)
1118 		return result;
1119 	}
1120 
1121 	return (result);
1122 }
1123 
1124 static int
1125 compare_pid(pp1, pp2)
1126 	struct proc **pp1, **pp2;
1127 {
1128 	if (threadmode) {
1129 		struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
1130 		struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
1131 		struct kinfo_proc2 *p1 = proc_from_thread(l1);
1132 		struct kinfo_proc2 *p2 = proc_from_thread(l2);
1133 		return p2->p_pid - p1->p_pid;
1134 	} else {
1135 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1136 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1137 		return p2->p_pid - p1->p_pid;
1138 	}
1139 }
1140 
1141 static int
1142 compare_command(pp1, pp2)
1143 	struct proc **pp1, **pp2;
1144 {
1145 	if (threadmode) {
1146 		struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
1147 		struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
1148 		struct kinfo_proc2 *p1 = proc_from_thread(l1);
1149 		struct kinfo_proc2 *p2 = proc_from_thread(l2);
1150 		return strcmp(p2->p_comm, p1->p_comm);
1151 	} else {
1152 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1153 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1154 		return strcmp(p2->p_comm, p1->p_comm);
1155 	}
1156 }
1157 
1158 static int
1159 compare_username(pp1, pp2)
1160 	struct proc **pp1, **pp2;
1161 {
1162 	if (threadmode) {
1163 		struct kinfo_lwp *l1 = *(struct kinfo_lwp **) pp1;
1164 		struct kinfo_lwp *l2 = *(struct kinfo_lwp **) pp2;
1165 		struct kinfo_proc2 *p1 = proc_from_thread(l1);
1166 		struct kinfo_proc2 *p2 = proc_from_thread(l2);
1167 		return strcmp(p2->p_login, p1->p_login);
1168 	} else {
1169 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1170 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1171 		return strcmp(p2->p_login, p1->p_login);
1172 	}
1173 }
1174 /* compare_size - the comparison function for sorting by total memory usage */
1175 
1176 static int
1177 compare_size(pp1, pp2)
1178 	struct proc **pp1, **pp2;
1179 {
1180 	int result;
1181 	pctcpu lresult;
1182 
1183 	if (threadmode) {
1184 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1185 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1186 
1187 		ORDERKEY_PCTCPU(l_)
1188 		ORDERKEY_CPTICKS(l_)
1189 		ORDERKEY_STATE(l_)
1190 		ORDERKEY_PRIO(l_)
1191 		return result;
1192 	} else {
1193 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1194 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1195 
1196 		ORDERKEY_MEM
1197 		ORDERKEY_RSSIZE
1198 		ORDERKEY_PCTCPU(p_)
1199 		ORDERKEY_CPTICKS(p_)
1200 		ORDERKEY_STATE(p_)
1201 		ORDERKEY_PRIO(p_)
1202 		return result;
1203 	}
1204 
1205 	return (result);
1206 }
1207 
1208 /* compare_state - the comparison function for sorting by process state */
1209 
1210 static int
1211 compare_state(pp1, pp2)
1212 	struct proc **pp1, **pp2;
1213 {
1214 	int result;
1215 	pctcpu lresult;
1216 
1217 	if (threadmode) {
1218 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1219 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1220 
1221 		ORDERKEY_STATE(l_)
1222 		ORDERKEY_PCTCPU(l_)
1223 		ORDERKEY_CPTICKS(l_)
1224 		ORDERKEY_PRIO(l_)
1225 		return result;
1226 	} else {
1227 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1228 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1229 
1230 		ORDERKEY_STATE(p_)
1231 		ORDERKEY_PCTCPU(p_)
1232 		ORDERKEY_CPTICKS(p_)
1233 		ORDERKEY_PRIO(p_)
1234 		ORDERKEY_RSSIZE
1235 		ORDERKEY_MEM
1236 		return result;
1237 	}
1238 
1239 	return (result);
1240 }
1241 
1242 /* compare_time - the comparison function for sorting by total CPU time */
1243 
1244 static int
1245 compare_time(pp1, pp2)
1246 	struct proc **pp1, **pp2;
1247 {
1248 	int result;
1249 	pctcpu lresult;
1250 
1251 	if (threadmode) {
1252 		struct kinfo_lwp *p1 = *(struct kinfo_lwp **) pp1;
1253 		struct kinfo_lwp *p2 = *(struct kinfo_lwp **) pp2;
1254 
1255 		ORDERKEY_CPTICKS(l_)
1256 		ORDERKEY_PCTCPU(l_)
1257 		ORDERKEY_STATE(l_)
1258 		ORDERKEY_PRIO(l_)
1259 		return result;
1260 	} else {
1261 		struct kinfo_proc2 *p1 = *(struct kinfo_proc2 **) pp1;
1262 		struct kinfo_proc2 *p2 = *(struct kinfo_proc2 **) pp2;
1263 
1264 		ORDERKEY_CPTICKS(p_)
1265 		ORDERKEY_PCTCPU(p_)
1266 		ORDERKEY_STATE(p_)
1267 		ORDERKEY_PRIO(p_)
1268 		ORDERKEY_MEM
1269 		ORDERKEY_RSSIZE
1270 		return result;
1271 	}
1272 
1273 	return (result);
1274 }
1275 
1276 
1277 /*
1278  * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
1279  *		the process does not exist.
1280  *		It is EXTREMLY IMPORTANT that this function work correctly.
1281  *		If top runs setuid root (as in SVR4), then this function
1282  *		is the only thing that stands in the way of a serious
1283  *		security problem.  It validates requests for the "kill"
1284  *		and "renice" commands.
1285  */
1286 
1287 int
1288 proc_owner(pid)
1289 	int pid;
1290 {
1291 	int cnt;
1292 	struct kinfo_proc2 **prefp;
1293 	struct kinfo_proc2 *pp;
1294 
1295 	if (threadmode)
1296 		return(-1);
1297 
1298 	prefp = pref;
1299 	cnt = pref_len;
1300 	while (--cnt >= 0) {
1301 		pp = *prefp++;
1302 		if (pp->p_pid == (pid_t)pid)
1303 			return(pp->p_ruid);
1304 	}
1305 	return(-1);
1306 }
1307 
1308 /*
1309  *  percentages(cnt, out, new, old, diffs) - calculate percentage change
1310  *	between array "old" and "new", putting the percentages i "out".
1311  *	"cnt" is size of each array and "diffs" is used for scratch space.
1312  *	The array "old" is updated on each call.
1313  *	The routine assumes modulo arithmetic.  This function is especially
1314  *	useful on BSD mchines for calculating CPU state percentages.
1315  */
1316 
1317 static void
1318 percentages64(cnt, out, new, old, diffs)
1319 	int cnt;
1320 	int *out;
1321 	u_int64_t *new;
1322 	u_int64_t *old;
1323 	u_int64_t *diffs;
1324 {
1325 	int i;
1326 	u_int64_t change;
1327 	u_int64_t total_change;
1328 	u_int64_t *dp;
1329 	u_int64_t half_total;
1330 
1331 	/* initialization */
1332 	total_change = 0;
1333 	dp = diffs;
1334 
1335 	/* calculate changes for each state and the overall change */
1336 	for (i = 0; i < cnt; i++) {
1337 		/*
1338 		 * Don't worry about wrapping - even at hz=1GHz, a
1339 		 * u_int64_t will last at least 544 years.
1340 		 */
1341 		change = *new - *old;
1342 		total_change += (*dp++ = change);
1343 		*old++ = *new++;
1344 	}
1345 
1346 	/* avoid divide by zero potential */
1347 	if (total_change == 0)
1348 		total_change = 1;
1349 
1350 	/* calculate percentages based on overall change, rounding up */
1351 	half_total = total_change / 2;
1352 	for (i = 0; i < cnt; i++)
1353 		*out++ = (int)((*diffs++ * 1000 + half_total) / total_change);
1354 }
1355