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