machine.c revision 131623
1/*
2 * top - a top users display for Unix
3 *
4 * SYNOPSIS:  For FreeBSD-2.x and later
5 *
6 * DESCRIPTION:
7 * Originally written for BSD4.4 system by Christos Zoulas.
8 * Ported to FreeBSD 2.x by Steven Wallace && Wolfram Schneider
9 * Order support hacked in from top-3.5beta6/machine/m_aix41.c
10 *   by Monte Mitzelfelt (for latest top see http://www.groupsys.com/topinfo/)
11 *
12 * This is the machine-dependent module for FreeBSD 2.2
13 * Works for:
14 *	FreeBSD 2.2.x, 3.x, 4.x, and probably FreeBSD 2.1.x
15 *
16 * LIBS: -lkvm
17 *
18 * AUTHOR:  Christos Zoulas <christos@ee.cornell.edu>
19 *          Steven Wallace  <swallace@freebsd.org>
20 *          Wolfram Schneider <wosch@FreeBSD.org>
21 *          Thomas Moestl <tmoestl@gmx.net>
22 *
23 * $FreeBSD: head/usr.bin/top/machine.c 131623 2004-07-05 13:12:16Z des $
24 */
25
26#include <sys/param.h>
27#include <sys/errno.h>
28#include <sys/file.h>
29#include <sys/proc.h>
30#include <sys/resource.h>
31#include <sys/rtprio.h>
32#include <sys/signal.h>
33#include <sys/sysctl.h>
34#include <sys/time.h>
35#include <sys/user.h>
36#include <sys/vmmeter.h>
37
38#include <kvm.h>
39#include <math.h>
40#include <nlist.h>
41#include <pwd.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <unistd.h>
45
46#include "top.h"
47#include "machine.h"
48#include "screen.h"
49#include "utils.h"
50
51static void getsysctl(char *, void *, size_t);
52
53#define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
54
55extern char* printable(char *);
56int swapmode(int *retavail, int *retfree);
57static int smpmode;
58enum displaymodes displaymode;
59static int namelength;
60static int cmdlengthdelta;
61
62/* Prototypes for top internals */
63void quit(int);
64int compare_pid(const void *a, const void *b);
65
66/* get_process_info passes back a handle.  This is what it looks like: */
67
68struct handle
69{
70	struct kinfo_proc **next_proc;	/* points to next valid proc pointer */
71	int remaining;			/* number of pointers remaining */
72};
73
74/* declarations for load_avg */
75#include "loadavg.h"
76
77/* define what weighted cpu is.  */
78#define weighted_cpu(pct, pp) ((pp)->ki_swtime == 0 ? 0.0 : \
79			 ((pct) / (1.0 - exp((pp)->ki_swtime * logcpu))))
80
81/* what we consider to be process size: */
82#define PROCSIZE(pp) ((pp)->ki_size / 1024)
83
84#define RU(pp)	(&(pp)->ki_rusage)
85#define RUTOT(pp) \
86	(RU(pp)->ru_inblock + RU(pp)->ru_oublock + RU(pp)->ru_majflt)
87
88
89/* definitions for indices in the nlist array */
90
91/*
92 *  These definitions control the format of the per-process area
93 */
94
95static char io_header[] =
96  "  PID %-*.*s   READ  WRITE  FAULT  TOTAL PERCENT COMMAND";
97
98#define io_Proc_format \
99	"%5d %-*.*s %6d %6d %6d %6d %6.2f%% %.*s"
100
101static char smp_header[] =
102  "  PID %-*.*s PRI NICE   SIZE    RES STATE  C   TIME   WCPU    CPU COMMAND";
103
104#define smp_Proc_format \
105	"%5d %-*.*s %3d %4d%7s %6s %-6.6s %1x%7s %5.2f%% %5.2f%% %.*s"
106
107static char up_header[] =
108  "  PID %-*.*s PRI NICE   SIZE    RES STATE    TIME   WCPU    CPU COMMAND";
109
110#define up_Proc_format \
111	"%5d %-*.*s %3d %4d%7s %6s %-6.6s%.0d%7s %5.2f%% %5.2f%% %.*s"
112
113
114
115/* process state names for the "STATE" column of the display */
116/* the extra nulls in the string "run" are for adding a slash and
117   the processor number when needed */
118
119char *state_abbrev[] =
120{
121	"", "START", "RUN\0\0\0", "SLEEP", "STOP", "ZOMB", "WAIT", "LOCK"
122};
123
124
125static kvm_t *kd;
126
127/* values that we stash away in _init and use in later routines */
128
129static double logcpu;
130
131/* these are retrieved from the kernel in _init */
132
133static load_avg  ccpu;
134
135/* these are used in the get_ functions */
136
137static int lastpid;
138
139/* these are for calculating cpu state percentages */
140
141static long cp_time[CPUSTATES];
142static long cp_old[CPUSTATES];
143static long cp_diff[CPUSTATES];
144
145/* these are for detailing the process states */
146
147int process_states[8];
148char *procstatenames[] = {
149	"", " starting, ", " running, ", " sleeping, ", " stopped, ",
150	" zombie, ", " waiting, ", " lock, ",
151	NULL
152};
153
154/* these are for detailing the cpu states */
155
156int cpu_states[CPUSTATES];
157char *cpustatenames[] = {
158	"user", "nice", "system", "interrupt", "idle", NULL
159};
160
161/* these are for detailing the memory statistics */
162
163int memory_stats[7];
164char *memorynames[] = {
165	/* 0             1            2            3            4          5 */
166	"K Active, ", "K Inact, ", "K Wired, ", "K Cache, ", "K Buf, ", "K Free",
167	NULL
168};
169
170int swap_stats[7];
171char *swapnames[] = {
172	/* 0            1           2           3            4         5 */
173	"K Total, ", "K Used, ", "K Free, ", "% Inuse, ", "K In, ", "K Out",
174	NULL
175};
176
177
178/* these are for keeping track of the proc array */
179
180static int nproc;
181static int onproc = -1;
182static int pref_len;
183static struct kinfo_proc *pbase;
184static struct kinfo_proc **pref;
185static struct kinfo_proc *previous_procs;
186static struct kinfo_proc **previous_pref;
187static int previous_proc_count = 0;
188static int previous_proc_count_max = 0;
189
190/* total number of io operations */
191static long total_inblock;
192static long total_oublock;
193static long total_majflt;
194
195/* these are for getting the memory statistics */
196
197static int pageshift;		/* log base 2 of the pagesize */
198
199/* define pagetok in terms of pageshift */
200
201#define pagetok(size) ((size) << pageshift)
202
203/* useful externals */
204long percentages();
205
206#ifdef ORDER
207/* sorting orders. first is default */
208char *ordernames[] = {
209	"cpu", "size", "res", "time", "pri", NULL
210};
211#endif
212
213int
214machine_init(struct statics *statics)
215{
216	int pagesize;
217	size_t modelen;
218	struct passwd *pw;
219
220	modelen = sizeof(smpmode);
221	if ((sysctlbyname("machdep.smp_active", &smpmode, &modelen, NULL, 0) < 0 &&
222		sysctlbyname("kern.smp.active", &smpmode, &modelen, NULL, 0) < 0) ||
223	    modelen != sizeof(smpmode))
224		smpmode = 0;
225
226	while ((pw = getpwent()) != NULL) {
227		if (strlen(pw->pw_name) > namelength)
228			namelength = strlen(pw->pw_name);
229	}
230	if (namelength < 8)
231		namelength = 8;
232	if (smpmode && namelength > 13)
233		namelength = 13;
234	else if (namelength > 15)
235		namelength = 15;
236
237	if ((kd = kvm_open("/dev/null", "/dev/null", "/dev/null", O_RDONLY, "kvm_open")) == NULL)
238		return -1;
239
240	GETSYSCTL("kern.ccpu", ccpu);
241
242	/* this is used in calculating WCPU -- calculate it ahead of time */
243	logcpu = log(loaddouble(ccpu));
244
245	pbase = NULL;
246	pref = NULL;
247	nproc = 0;
248	onproc = -1;
249	/* get the page size with "getpagesize" and calculate pageshift from it */
250	pagesize = getpagesize();
251	pageshift = 0;
252	while (pagesize > 1)
253	{
254		pageshift++;
255		pagesize >>= 1;
256	}
257
258	/* we only need the amount of log(2)1024 for our conversion */
259	pageshift -= LOG1024;
260
261	/* fill in the statics information */
262	statics->procstate_names = procstatenames;
263	statics->cpustate_names = cpustatenames;
264	statics->memory_names = memorynames;
265	statics->swap_names = swapnames;
266#ifdef ORDER
267	statics->order_names = ordernames;
268#endif
269
270	/* all done! */
271	return (0);
272}
273
274char *
275format_header(char *uname_field)
276{
277	static char Header[128];
278	const char *prehead;
279
280	switch (displaymode) {
281	case DISP_CPU:
282		prehead = smpmode ? smp_header : up_header;
283		break;
284	case DISP_IO:
285		prehead = io_header;
286		break;
287	}
288
289	snprintf(Header, sizeof(Header), prehead,
290	    namelength, namelength, uname_field);
291
292	cmdlengthdelta = strlen(Header) - 7;
293
294	return (Header);
295}
296
297static int swappgsin = -1;
298static int swappgsout = -1;
299extern struct timeval timeout;
300
301void
302get_system_info(struct system_info *si)
303{
304	long total;
305	struct loadavg sysload;
306	int mib[2];
307	struct timeval boottime;
308	size_t bt_size;
309
310	/* get the cp_time array */
311	GETSYSCTL("kern.cp_time", cp_time);
312	GETSYSCTL("vm.loadavg", sysload);
313	GETSYSCTL("kern.lastpid", lastpid);
314
315	/* convert load averages to doubles */
316	{
317		int i;
318		double *infoloadp;
319
320		infoloadp = si->load_avg;
321		for (i = 0; i < 3; i++)
322		{
323#ifdef notyet
324			*infoloadp++ = ((double) sysload.ldavg[i]) / sysload.fscale;
325#endif
326			*infoloadp++ = loaddouble(sysload.ldavg[i]);
327		}
328	}
329
330	/* convert cp_time counts to percentages */
331	total = percentages(CPUSTATES, cpu_states, cp_time, cp_old, cp_diff);
332
333	/* sum memory & swap statistics */
334	{
335		static unsigned int swap_delay = 0;
336		static int swapavail = 0;
337		static int swapfree = 0;
338		static int bufspace = 0;
339		static int nspgsin, nspgsout;
340
341		GETSYSCTL("vfs.bufspace", bufspace);
342		GETSYSCTL("vm.stats.vm.v_active_count", memory_stats[0]);
343		GETSYSCTL("vm.stats.vm.v_inactive_count", memory_stats[1]);
344		GETSYSCTL("vm.stats.vm.v_wire_count", memory_stats[2]);
345		GETSYSCTL("vm.stats.vm.v_cache_count", memory_stats[3]);
346		GETSYSCTL("vm.stats.vm.v_free_count", memory_stats[5]);
347		GETSYSCTL("vm.stats.vm.v_swappgsin", nspgsin);
348		GETSYSCTL("vm.stats.vm.v_swappgsout", nspgsout);
349		/* convert memory stats to Kbytes */
350		memory_stats[0] = pagetok(memory_stats[0]);
351		memory_stats[1] = pagetok(memory_stats[1]);
352		memory_stats[2] = pagetok(memory_stats[2]);
353		memory_stats[3] = pagetok(memory_stats[3]);
354		memory_stats[4] = bufspace / 1024;
355		memory_stats[5] = pagetok(memory_stats[5]);
356		memory_stats[6] = -1;
357
358		/* first interval */
359		if (swappgsin < 0) {
360			swap_stats[4] = 0;
361			swap_stats[5] = 0;
362		}
363
364		/* compute differences between old and new swap statistic */
365		else {
366			swap_stats[4] = pagetok(((nspgsin - swappgsin)));
367			swap_stats[5] = pagetok(((nspgsout - swappgsout)));
368		}
369
370		swappgsin = nspgsin;
371		swappgsout = nspgsout;
372
373		/* call CPU heavy swapmode() only for changes */
374		if (swap_stats[4] > 0 || swap_stats[5] > 0 || swap_delay == 0) {
375			swap_stats[3] = swapmode(&swapavail, &swapfree);
376			swap_stats[0] = swapavail;
377			swap_stats[1] = swapavail - swapfree;
378			swap_stats[2] = swapfree;
379		}
380		swap_delay = 1;
381		swap_stats[6] = -1;
382	}
383
384	/* set arrays and strings */
385	si->cpustates = cpu_states;
386	si->memory = memory_stats;
387	si->swap = swap_stats;
388
389
390	if (lastpid > 0) {
391		si->last_pid = lastpid;
392	} else {
393		si->last_pid = -1;
394	}
395
396	/*
397	 * Print how long system has been up.
398	 * (Found by looking getting "boottime" from the kernel)
399	 */
400	mib[0] = CTL_KERN;
401	mib[1] = KERN_BOOTTIME;
402	bt_size = sizeof(boottime);
403	if (sysctl(mib, 2, &boottime, &bt_size, NULL, 0) != -1 &&
404	    boottime.tv_sec != 0) {
405		si->boottime = boottime;
406	} else {
407		si->boottime.tv_sec = -1;
408	}
409}
410
411const struct kinfo_proc *
412get_old_proc(struct kinfo_proc *pp)
413{
414	struct kinfo_proc **oldpp, *oldp;
415
416	if (previous_proc_count == 0)
417		return (NULL);
418	oldpp = bsearch(&pp, previous_pref, previous_proc_count,
419	    sizeof(struct kinfo_proc *), compare_pid);
420	if (oldpp == NULL)
421		return (NULL);
422	oldp = *oldpp;
423	if (bcmp(&oldp->ki_start, &pp->ki_start, sizeof(pp->ki_start)) != 0)
424		return (NULL);
425	return (oldp);
426}
427
428long
429get_io_stats(struct kinfo_proc *pp, long *inp, long *oup, long *flp)
430{
431	const struct kinfo_proc *oldp;
432	static struct kinfo_proc dummy;
433	long ret;
434
435	oldp = get_old_proc(pp);
436	if (oldp == NULL) {
437		bzero(&dummy, sizeof(dummy));
438		oldp = &dummy;
439	}
440
441	*inp = RU(pp)->ru_inblock - RU(oldp)->ru_inblock;
442	*oup = RU(pp)->ru_oublock - RU(oldp)->ru_oublock;
443	*flp = RU(pp)->ru_majflt - RU(oldp)->ru_majflt;
444	ret =
445	    (RU(pp)->ru_inblock - RU(oldp)->ru_inblock) +
446	    (RU(pp)->ru_oublock - RU(oldp)->ru_oublock) +
447	    (RU(pp)->ru_majflt - RU(oldp)->ru_majflt);
448	return (ret);
449}
450
451long
452get_io_total(struct kinfo_proc *pp)
453{
454	long dummy;
455
456	return (get_io_stats(pp, &dummy, &dummy, &dummy));
457}
458
459static struct handle handle;
460
461caddr_t
462get_process_info(struct system_info *si, struct process_select *sel,
463    int (*compare)())
464{
465	int i;
466	int total_procs;
467	long p_io;
468	long p_inblock, p_oublock, p_majflt;
469	int active_procs;
470	struct kinfo_proc **prefp;
471	struct kinfo_proc *pp;
472	struct kinfo_proc *prev_pp = NULL;
473
474	/* these are copied out of sel for speed */
475	int show_idle;
476	int show_self;
477	int show_system;
478	int show_uid;
479	int show_command;
480
481	/*
482	 * Save the previous process info.
483	 */
484	if (previous_proc_count_max < nproc) {
485		free(previous_procs);
486		previous_procs = malloc(nproc * sizeof(struct kinfo_proc));
487		free(previous_pref);
488		previous_pref = malloc(nproc * sizeof(struct kinfo_proc *));
489		if (previous_procs == NULL || previous_pref == NULL) {
490			(void) fprintf(stderr, "top: Out of memory.\n");
491			quit(23);
492		}
493		previous_proc_count_max = nproc;
494	}
495	if (nproc) {
496		for (i = 0; i < nproc; i++)
497			previous_pref[i] = &previous_procs[i];
498		bcopy(pbase, previous_procs, nproc * sizeof(struct kinfo_proc));
499		qsort(previous_pref, nproc,
500		    sizeof(struct kinfo_proc *), compare_pid);
501	}
502	previous_proc_count = nproc;
503
504	pbase = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);
505	if (nproc > onproc)
506		pref = (struct kinfo_proc **) realloc(pref, sizeof(struct kinfo_proc *)
507		    * (onproc = nproc));
508	if (pref == NULL || pbase == NULL) {
509		(void) fprintf(stderr, "top: Out of memory.\n");
510		quit(23);
511	}
512	/* get a pointer to the states summary array */
513	si->procstates = process_states;
514
515	/* set up flags which define what we are going to select */
516	show_idle = sel->idle;
517	show_self = sel->self;
518	show_system = sel->system;
519	show_uid = sel->uid != -1;
520	show_command = sel->command != NULL;
521
522	/* count up process states and get pointers to interesting procs */
523	total_procs = 0;
524	active_procs = 0;
525	total_inblock = 0;
526	total_oublock = 0;
527	total_majflt = 0;
528	memset((char *)process_states, 0, sizeof(process_states));
529	prefp = pref;
530	for (pp = pbase, i = 0; i < nproc; pp++, i++)
531	{
532		/*
533		 *  Place pointers to each valid proc structure in pref[].
534		 */
535
536		if (pp->ki_stat == 0)
537		/* not in use */
538		continue;
539
540		if (!show_self && pp->ki_pid == sel->self)
541			/* skip self */
542			continue;
543
544		if (!show_system && (pp->ki_flag & P_SYSTEM))
545			/* skip system process */
546			continue;
547
548		p_io = get_io_stats(pp, &p_inblock, &p_oublock, &p_majflt);
549		total_inblock += p_inblock;
550		total_oublock += p_oublock;
551		total_majflt += p_majflt;
552		total_procs++;
553		process_states[(unsigned char) pp->ki_stat]++;
554
555		if (pp->ki_stat == SZOMB)
556			/* skip zombies */
557			continue;
558
559		if (displaymode == DISP_CPU && !show_idle &&
560		    (pp->ki_pctcpu == 0 || pp->ki_stat != SRUN))
561			/* skip idle or non-running processes */
562			continue;
563
564		if (displaymode == DISP_IO && !show_idle && p_io == 0)
565			/* skip processes that aren't doing I/O */
566			continue;
567
568		if (show_uid && pp->ki_ruid != (uid_t)sel->uid)
569			/* skip processes which don't belong to the selected UID */
570			continue;
571
572		/*
573		 * When not showing threads, take the first thread
574		 * for output and add the fields that we can from
575		 * the rest of the process's threads rather than
576		 * using the system's mostly-broken KERN_PROC_PROC.
577		 */
578		if (sel->thread || prev_pp == NULL || prev_pp->ki_pid != pp->ki_pid)
579		{
580			*prefp++ = pp;
581			active_procs++;
582			prev_pp = pp;
583		} else {
584			prev_pp->ki_pctcpu += pp->ki_pctcpu;
585		}
586	}
587
588	/* if requested, sort the "interesting" processes */
589	if (compare != NULL)
590	{
591		qsort((char *)pref, active_procs, sizeof(struct kinfo_proc *), compare);
592	}
593
594	/* remember active and total counts */
595	si->p_total = total_procs;
596	si->p_active = pref_len = active_procs;
597
598	/* pass back a handle */
599	handle.next_proc = pref;
600	handle.remaining = active_procs;
601	return ((caddr_t)&handle);
602}
603
604char fmt[128];		/* static area where result is built */
605
606char *
607format_next_process(caddr_t handle, char *(*get_userid)())
608{
609	struct kinfo_proc *pp;
610	const struct kinfo_proc *oldp;
611	long cputime;
612	double pct;
613	struct handle *hp;
614	char status[16];
615	int state;
616	struct rusage ru, *rup;
617	long p_tot, s_tot;
618
619	/* find and remember the next proc structure */
620	hp = (struct handle *)handle;
621	pp = *(hp->next_proc++);
622	hp->remaining--;
623
624	/* get the process's command name */
625	if ((pp->ki_sflag & PS_INMEM) == 0) {
626		/*
627		 * Print swapped processes as <pname>
628		 */
629		char *comm = pp->ki_comm;
630#define COMSIZ sizeof(pp->ki_comm)
631		char buf[COMSIZ];
632		(void) strncpy(buf, comm, COMSIZ);
633		comm[0] = '<';
634		(void) strncpy(&comm[1], buf, COMSIZ - 2);
635		comm[COMSIZ - 2] = '\0';
636		(void) strncat(comm, ">", COMSIZ - 1);
637		comm[COMSIZ - 1] = '\0';
638	}
639
640	/*
641	 * Convert the process's runtime from microseconds to seconds.  This
642	 * time includes the interrupt time although that is not wanted here.
643	 * ps(1) is similarly sloppy.
644	 */
645	cputime = (pp->ki_runtime + 500000) / 1000000;
646
647	/* calculate the base for cpu percentages */
648	pct = pctdouble(pp->ki_pctcpu);
649
650	/* generate "STATE" field */
651	switch (state = pp->ki_stat) {
652	case SRUN:
653		if (smpmode && pp->ki_oncpu != 0xff)
654			sprintf(status, "CPU%d", pp->ki_oncpu);
655		else
656			strcpy(status, "RUN");
657		break;
658	case SLOCK:
659		if (pp->ki_kiflag & KI_LOCKBLOCK) {
660			sprintf(status, "*%.6s", pp->ki_lockname);
661			break;
662		}
663		/* fall through */
664	case SSLEEP:
665		if (pp->ki_wmesg != NULL) {
666			sprintf(status, "%.6s", pp->ki_wmesg);
667			break;
668		}
669		/* FALLTHROUGH */
670	default:
671
672		if (state >= 0 &&
673		    state < sizeof(state_abbrev) / sizeof(*state_abbrev))
674			sprintf(status, "%.6s", state_abbrev[(unsigned char) state]);
675		else
676			sprintf(status, "?%5d", state);
677		break;
678	}
679
680	if (displaymode == DISP_IO) {
681		oldp = get_old_proc(pp);
682		if (oldp != NULL) {
683			ru.ru_inblock = RU(pp)->ru_inblock - RU(oldp)->ru_inblock;
684			ru.ru_oublock = RU(pp)->ru_oublock - RU(oldp)->ru_oublock;
685			ru.ru_majflt = RU(pp)->ru_majflt - RU(oldp)->ru_majflt;
686			rup = &ru;
687		} else {
688			rup = RU(pp);
689		}
690		p_tot = rup->ru_inblock + rup->ru_oublock + rup->ru_majflt;
691		s_tot = total_inblock + total_oublock + total_majflt;
692
693		sprintf(fmt, io_Proc_format,
694		    pp->ki_pid,
695		    namelength, namelength,
696		    (*get_userid)(pp->ki_ruid),
697		    (int)rup->ru_inblock,
698		    (int)rup->ru_oublock,
699		    (int)rup->ru_majflt,
700		    (int)p_tot,
701		    p_tot == 0 ? 0.0 : ((float)(p_tot * 100))/(float)s_tot,
702		    screen_width > cmdlengthdelta ?
703		    screen_width - cmdlengthdelta : 0,
704		    printable(pp->ki_comm));
705		return (fmt);
706	}
707	/* format this entry */
708	sprintf(fmt,
709	    smpmode ? smp_Proc_format : up_Proc_format,
710	    pp->ki_pid,
711	    namelength, namelength,
712	    (*get_userid)(pp->ki_ruid),
713	    pp->ki_pri.pri_level - PZERO,
714
715	    /*
716	     * normal time      -> nice value -20 - +20
717	     * real time 0 - 31 -> nice value -52 - -21
718	     * idle time 0 - 31 -> nice value +21 - +52
719	     */
720	    (pp->ki_pri.pri_class ==  PRI_TIMESHARE ?
721		pp->ki_nice - NZERO :
722		(PRI_IS_REALTIME(pp->ki_pri.pri_class) ?
723		    (PRIO_MIN - 1 - (PRI_MAX_REALTIME - pp->ki_pri.pri_level)) :
724		    (PRIO_MAX + 1 + pp->ki_pri.pri_level - PRI_MIN_IDLE))),
725	    format_k2(PROCSIZE(pp)),
726	    format_k2(pagetok(pp->ki_rssize)),
727	    status,
728	    smpmode ? pp->ki_lastcpu : 0,
729	    format_time(cputime),
730	    100.0 * weighted_cpu(pct, pp),
731	    100.0 * pct,
732	    screen_width > cmdlengthdelta ?
733	    screen_width - cmdlengthdelta :
734	    0,
735	    printable(pp->ki_comm));
736
737	/* return the result */
738	return (fmt);
739}
740
741static void
742getsysctl(char *name, void *ptr, size_t len)
743{
744	size_t nlen = len;
745
746	if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
747		fprintf(stderr, "top: sysctl(%s...) failed: %s\n", name,
748		    strerror(errno));
749		quit(23);
750	}
751	if (nlen != len) {
752		fprintf(stderr, "top: sysctl(%s...) expected %lu, got %lu\n", name,
753		    (unsigned long)len, (unsigned long)nlen);
754		quit(23);
755	}
756}
757
758/* comparison routines for qsort */
759
760int
761compare_pid(const void *p1, const void *p2)
762{
763	const struct kinfo_proc * const *pp1 = p1;
764	const struct kinfo_proc * const *pp2 = p2;
765
766	if ((*pp2)->ki_pid < 0 || (*pp1)->ki_pid < 0)
767		abort();
768
769	return ((*pp1)->ki_pid - (*pp2)->ki_pid);
770}
771
772/*
773 *  proc_compare - comparison function for "qsort"
774 *	Compares the resource consumption of two processes using five
775 *	distinct keys.  The keys (in descending order of importance) are:
776 *	percent cpu, cpu ticks, state, resident set size, total virtual
777 *	memory usage.  The process states are ordered as follows (from least
778 *	to most important):  WAIT, zombie, sleep, stop, start, run.  The
779 *	array declaration below maps a process state index into a number
780 *	that reflects this ordering.
781 */
782
783static unsigned char sorted_state[] =
784{
785	0,	/* not used		*/
786	3,	/* sleep		*/
787	1,	/* ABANDONED (WAIT)	*/
788	6,	/* run			*/
789	5,	/* start		*/
790	2,	/* zombie		*/
791	4	/* stop			*/
792};
793
794
795#define ORDERKEY_PCTCPU \
796  if (lresult = (long) p2->ki_pctcpu - (long) p1->ki_pctcpu, \
797     (result = lresult > 0 ? 1 : lresult < 0 ? -1 : 0) == 0)
798
799#define ORDERKEY_CPTICKS \
800  if ((result = p2->ki_runtime > p1->ki_runtime ? 1 : \
801		p2->ki_runtime < p1->ki_runtime ? -1 : 0) == 0)
802
803#define ORDERKEY_STATE \
804  if ((result = sorted_state[(unsigned char) p2->ki_stat] - \
805		sorted_state[(unsigned char) p1->ki_stat]) == 0)
806
807#define ORDERKEY_PRIO \
808  if ((result = p2->ki_pri.pri_level - p1->ki_pri.pri_level) == 0)
809
810#define ORDERKEY_RSSIZE \
811  if ((result = p2->ki_rssize - p1->ki_rssize) == 0)
812
813#define ORDERKEY_MEM \
814  if ( (result = PROCSIZE(p2) - PROCSIZE(p1)) == 0 )
815
816/* compare_cpu - the comparison function for sorting by cpu percentage */
817
818int
819#ifdef ORDER
820compare_cpu(struct proc **pp1, struct proc **pp2)
821#else
822proc_compare(struct proc **pp1, struct proc **pp2)
823#endif
824{
825	struct kinfo_proc *p1;
826	struct kinfo_proc *p2;
827	int result;
828	pctcpu lresult;
829
830	/* remove one level of indirection */
831	p1 = *(struct kinfo_proc **) pp1;
832	p2 = *(struct kinfo_proc **) pp2;
833
834	ORDERKEY_PCTCPU
835	ORDERKEY_CPTICKS
836	ORDERKEY_STATE
837	ORDERKEY_PRIO
838	ORDERKEY_RSSIZE
839	ORDERKEY_MEM
840	;
841
842	return (result);
843}
844
845#ifdef ORDER
846/* compare routines */
847int compare_size(), compare_res(), compare_time(), compare_prio();
848
849int (*proc_compares[])() = {
850	compare_cpu,
851	compare_size,
852	compare_res,
853	compare_time,
854	compare_prio,
855	NULL
856};
857
858/* compare_size - the comparison function for sorting by total memory usage */
859
860int
861compare_size(struct proc **pp1, struct proc **pp2)
862{
863	struct kinfo_proc *p1;
864	struct kinfo_proc *p2;
865	int result;
866	pctcpu lresult;
867
868	/* remove one level of indirection */
869	p1 = *(struct kinfo_proc **) pp1;
870	p2 = *(struct kinfo_proc **) pp2;
871
872	ORDERKEY_MEM
873	ORDERKEY_RSSIZE
874	ORDERKEY_PCTCPU
875	ORDERKEY_CPTICKS
876	ORDERKEY_STATE
877	ORDERKEY_PRIO
878	;
879
880	return (result);
881}
882
883/* compare_res - the comparison function for sorting by resident set size */
884
885int
886compare_res(struct proc **pp1, struct proc **pp2)
887{
888	struct kinfo_proc *p1;
889	struct kinfo_proc *p2;
890	int result;
891	pctcpu lresult;
892
893	/* remove one level of indirection */
894	p1 = *(struct kinfo_proc **) pp1;
895	p2 = *(struct kinfo_proc **) pp2;
896
897	ORDERKEY_RSSIZE
898	ORDERKEY_MEM
899	ORDERKEY_PCTCPU
900	ORDERKEY_CPTICKS
901	ORDERKEY_STATE
902	ORDERKEY_PRIO
903	;
904
905	return (result);
906}
907
908/* compare_time - the comparison function for sorting by total cpu time */
909
910int
911compare_time(struct proc **pp1, struct proc **pp2)
912{
913	struct kinfo_proc *p1;
914	struct kinfo_proc *p2;
915	int result;
916	pctcpu lresult;
917
918	/* remove one level of indirection */
919	p1 = *(struct kinfo_proc **) pp1;
920	p2 = *(struct kinfo_proc **) pp2;
921
922	ORDERKEY_CPTICKS
923	ORDERKEY_PCTCPU
924	ORDERKEY_STATE
925	ORDERKEY_PRIO
926	ORDERKEY_RSSIZE
927	ORDERKEY_MEM
928	;
929
930	return (result);
931}
932
933/* compare_prio - the comparison function for sorting by cpu percentage */
934
935int
936compare_prio(struct proc **pp1, struct proc **pp2)
937{
938	struct kinfo_proc *p1;
939	struct kinfo_proc *p2;
940	int result;
941	pctcpu lresult;
942
943	/* remove one level of indirection */
944	p1 = *(struct kinfo_proc **) pp1;
945	p2 = *(struct kinfo_proc **) pp2;
946
947	ORDERKEY_PRIO
948	ORDERKEY_CPTICKS
949	ORDERKEY_PCTCPU
950	ORDERKEY_STATE
951	ORDERKEY_RSSIZE
952	ORDERKEY_MEM
953	;
954
955	return (result);
956}
957#endif
958
959int
960io_compare(struct proc **pp1, struct proc **pp2)
961{
962	long t1, t2;
963
964	t1 = get_io_total((struct kinfo_proc *)*pp1);
965	t2 = get_io_total((struct kinfo_proc *)*pp2);
966	return (t2 - t1);
967}
968/*
969 * proc_owner(pid) - returns the uid that owns process "pid", or -1 if
970 *		the process does not exist.
971 *		It is EXTREMLY IMPORTANT that this function work correctly.
972 *		If top runs setuid root (as in SVR4), then this function
973 *		is the only thing that stands in the way of a serious
974 *		security problem.  It validates requests for the "kill"
975 *		and "renice" commands.
976 */
977
978int
979proc_owner(int pid)
980{
981	int cnt;
982	struct kinfo_proc **prefp;
983	struct kinfo_proc *pp;
984
985	prefp = pref;
986	cnt = pref_len;
987	while (--cnt >= 0)
988	{
989		pp = *prefp++;
990		if (pp->ki_pid == (pid_t)pid)
991		{
992			return ((int)pp->ki_ruid);
993		}
994	}
995	return (-1);
996}
997
998int
999swapmode(int *retavail, int *retfree)
1000{
1001	int n;
1002	int pagesize = getpagesize();
1003	struct kvm_swap swapary[1];
1004
1005	*retavail = 0;
1006	*retfree = 0;
1007
1008#define CONVERT(v)	((quad_t)(v) * pagesize / 1024)
1009
1010	n = kvm_getswapinfo(kd, swapary, 1, 0);
1011	if (n < 0 || swapary[0].ksw_total == 0)
1012		return (0);
1013
1014	*retavail = CONVERT(swapary[0].ksw_total);
1015	*retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);
1016
1017	n = (int)((double)swapary[0].ksw_used * 100.0 /
1018	    (double)swapary[0].ksw_total);
1019	return (n);
1020}
1021