vmstat.c revision 43819
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1980, 1986, 1991, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
3528693Scharnierstatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes#ifndef lint
4128693Scharnier#if 0
421590Srgrimesstatic char sccsid[] = "@(#)vmstat.c	8.1 (Berkeley) 6/6/93";
4328693Scharnier#endif
4428693Scharnierstatic const char rcsid[] =
4543819Sken	"$Id: vmstat.c,v 1.29 1998/10/28 06:41:24 jdp Exp $";
461590Srgrimes#endif /* not lint */
471590Srgrimes
481590Srgrimes#include <sys/param.h>
491590Srgrimes#include <sys/time.h>
501590Srgrimes#include <sys/proc.h>
511590Srgrimes#include <sys/dkstat.h>
521590Srgrimes#include <sys/buf.h>
5312811Sbde#include <sys/uio.h>
541590Srgrimes#include <sys/namei.h>
551590Srgrimes#include <sys/malloc.h>
561590Srgrimes#include <sys/signal.h>
571590Srgrimes#include <sys/fcntl.h>
581590Srgrimes#include <sys/ioctl.h>
591590Srgrimes#include <sys/sysctl.h>
6012804Speter#include <sys/vmmeter.h>
6112811Sbde
6212811Sbde#include <vm/vm_param.h>
6312811Sbde
6428693Scharnier#include <ctype.h>
6528693Scharnier#include <err.h>
6628693Scharnier#include <errno.h>
6728693Scharnier#include <kvm.h>
6828693Scharnier#include <limits.h>
691590Srgrimes#include <nlist.h>
7028693Scharnier#include <paths.h>
711590Srgrimes#include <stdio.h>
721590Srgrimes#include <stdlib.h>
731590Srgrimes#include <string.h>
7430180Sdima#include <sysexits.h>
7528693Scharnier#include <time.h>
7628693Scharnier#include <unistd.h>
7739230Sgibbs#include <devstat.h>
781590Srgrimes
791590Srgrimesstruct nlist namelist[] = {
801590Srgrimes#define	X_CPTIME	0
811590Srgrimes	{ "_cp_time" },
8239230Sgibbs#define X_SUM		1
831590Srgrimes	{ "_cnt" },
8439230Sgibbs#define	X_BOOTTIME	2
851590Srgrimes	{ "_boottime" },
8639230Sgibbs#define X_HZ		3
871590Srgrimes	{ "_hz" },
8839230Sgibbs#define X_STATHZ	4
891590Srgrimes	{ "_stathz" },
9039230Sgibbs#define X_NCHSTATS	5
911590Srgrimes	{ "_nchstats" },
9239230Sgibbs#define	X_INTRNAMES	6
931590Srgrimes	{ "_intrnames" },
9439230Sgibbs#define	X_EINTRNAMES	7
951590Srgrimes	{ "_eintrnames" },
9639230Sgibbs#define	X_INTRCNT	8
971590Srgrimes	{ "_intrcnt" },
9839230Sgibbs#define	X_EINTRCNT	9
991590Srgrimes	{ "_eintrcnt" },
10039230Sgibbs#define	X_KMEMSTATISTICS	10
10130279Sphk	{ "_kmemstatistics" },
10239230Sgibbs#define	X_KMEMBUCKETS	11
1031590Srgrimes	{ "_bucket" },
10430180Sdima#ifdef notyet
10539230Sgibbs#define	X_DEFICIT	12
1061590Srgrimes	{ "_deficit" },
10739230Sgibbs#define	X_FORKSTAT	13
1081590Srgrimes	{ "_forkstat" },
10939230Sgibbs#define X_REC		14
1101590Srgrimes	{ "_rectime" },
11139230Sgibbs#define X_PGIN		15
1121590Srgrimes	{ "_pgintime" },
11339230Sgibbs#define	X_XSTATS	16
1141590Srgrimes	{ "_xstats" },
11539230Sgibbs#define X_END		17
1161590Srgrimes#else
1171590Srgrimes#define X_END		14
1181590Srgrimes#endif
1191590Srgrimes#if defined(hp300) || defined(luna68k)
1201590Srgrimes#define	X_HPDINIT	(X_END)
1211590Srgrimes	{ "_hp_dinit" },
1221590Srgrimes#endif
1231590Srgrimes#ifdef mips
1241590Srgrimes#define	X_SCSI_DINIT	(X_END)
1251590Srgrimes	{ "_scsi_dinit" },
1261590Srgrimes#endif
1271590Srgrimes#ifdef tahoe
1281590Srgrimes#define	X_VBDINIT	(X_END)
1291590Srgrimes	{ "_vbdinit" },
1301590Srgrimes#define	X_CKEYSTATS	(X_END+1)
1311590Srgrimes	{ "_ckeystats" },
1321590Srgrimes#define	X_DKEYSTATS	(X_END+2)
1331590Srgrimes	{ "_dkeystats" },
1341590Srgrimes#endif
1351590Srgrimes#ifdef vax
1361590Srgrimes#define X_MBDINIT	(X_END)
1371590Srgrimes	{ "_mbdinit" },
1381590Srgrimes#define X_UBDINIT	(X_END+1)
1391590Srgrimes	{ "_ubdinit" },
1401590Srgrimes#endif
1411590Srgrimes	{ "" },
1421590Srgrimes};
1431590Srgrimes
14439230Sgibbsstruct statinfo cur, last;
14539498Skenint num_devices, maxshowdevs;
14639498Skenlong generation;
14739230Sgibbsstruct device_selection *dev_select;
14839230Sgibbsint num_selected;
14939230Sgibbsstruct devstat_match *matches;
15039230Sgibbsint num_matches = 0;
15139498Skenint num_devices_specified, num_selections;
15239498Skenlong select_generation;
15339230Sgibbschar **specified_devices;
15439230Sgibbsdevstat_select_mode select_mode;
1551590Srgrimes
1561590Srgrimesstruct	vmmeter sum, osum;
1571590Srgrimes
1581590Srgrimesint	winlines = 20;
15939372Sdillonint	nflag = 0;
1601590Srgrimes
1611590Srgrimeskvm_t *kd;
1621590Srgrimes
1631590Srgrimes#define	FORKSTAT	0x01
1641590Srgrimes#define	INTRSTAT	0x02
1651590Srgrimes#define	MEMSTAT		0x04
1661590Srgrimes#define	SUMSTAT		0x08
1671590Srgrimes#define	TIMESTAT	0x10
1681590Srgrimes#define	VMSTAT		0x20
1691590Srgrimes
17039230Sgibbsvoid	cpustats(), dointr(), domem(), dosum();
1711590Srgrimesvoid	dovmstat(), kread(), usage();
17230180Sdima#ifdef notyet
1731590Srgrimesvoid	dotimes(), doforkst();
1741590Srgrimes#endif
17528693Scharniervoid printhdr __P((void));
17639230Sgibbsstatic void devstats();
1771590Srgrimes
17828693Scharnierint
1791590Srgrimesmain(argc, argv)
1801590Srgrimes	register int argc;
1811590Srgrimes	register char **argv;
1821590Srgrimes{
1831590Srgrimes	register int c, todo;
1841590Srgrimes	u_int interval;
1851590Srgrimes	int reps;
1861590Srgrimes	char *memf, *nlistf;
1871590Srgrimes        char errbuf[_POSIX2_LINE_MAX];
18839230Sgibbs	char *err_str;
1891590Srgrimes
1901590Srgrimes	memf = nlistf = NULL;
1911590Srgrimes	interval = reps = todo = 0;
19239230Sgibbs	maxshowdevs = 3;
19339230Sgibbs	while ((c = getopt(argc, argv, "c:fiM:mN:n:p:stw:")) != -1) {
1941590Srgrimes		switch (c) {
1951590Srgrimes		case 'c':
1961590Srgrimes			reps = atoi(optarg);
1971590Srgrimes			break;
1981590Srgrimes		case 'f':
19930180Sdima#ifdef notyet
2001590Srgrimes			todo |= FORKSTAT;
20130180Sdima#else
20230180Sdima			errx(EX_USAGE, "sorry, -f is not (re)implemented yet");
20330180Sdima#endif
2041590Srgrimes			break;
2051590Srgrimes		case 'i':
2061590Srgrimes			todo |= INTRSTAT;
2071590Srgrimes			break;
2081590Srgrimes		case 'M':
2091590Srgrimes			memf = optarg;
2101590Srgrimes			break;
2111590Srgrimes		case 'm':
2121590Srgrimes			todo |= MEMSTAT;
2131590Srgrimes			break;
2141590Srgrimes		case 'N':
2151590Srgrimes			nlistf = optarg;
2161590Srgrimes			break;
21739230Sgibbs		case 'n':
21839372Sdillon			nflag = 1;
21939230Sgibbs			maxshowdevs = atoi(optarg);
22039230Sgibbs			if (maxshowdevs < 0)
22139230Sgibbs				errx(1, "number of devices %d is < 0",
22239230Sgibbs				     maxshowdevs);
22339230Sgibbs			break;
22439230Sgibbs		case 'p':
22539230Sgibbs			if (buildmatch(optarg, &matches, &num_matches) != 0)
22639230Sgibbs				errx(1, "%s", devstat_errbuf);
22739230Sgibbs			break;
2281590Srgrimes		case 's':
2291590Srgrimes			todo |= SUMSTAT;
2301590Srgrimes			break;
2311590Srgrimes		case 't':
23230180Sdima#ifdef notyet
2331590Srgrimes			todo |= TIMESTAT;
23430180Sdima#else
23530180Sdima			errx(EX_USAGE, "sorry, -t is not (re)implemented yet");
23630180Sdima#endif
2371590Srgrimes			break;
2381590Srgrimes		case 'w':
2391590Srgrimes			interval = atoi(optarg);
2401590Srgrimes			break;
2411590Srgrimes		case '?':
2421590Srgrimes		default:
2431590Srgrimes			usage();
2441590Srgrimes		}
2451590Srgrimes	}
2461590Srgrimes	argc -= optind;
2471590Srgrimes	argv += optind;
2481590Srgrimes
2491590Srgrimes	if (todo == 0)
2501590Srgrimes		todo = VMSTAT;
2511590Srgrimes
2521590Srgrimes	/*
2531590Srgrimes	 * Discard setgid privileges if not the running kernel so that bad
2541590Srgrimes	 * guys can't print interesting stuff from kernel memory.
2551590Srgrimes	 */
2561590Srgrimes	if (nlistf != NULL || memf != NULL)
2571590Srgrimes		setgid(getgid());
2581590Srgrimes
25928693Scharnier	kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
26028693Scharnier	if (kd == 0)
26128693Scharnier		errx(1, "kvm_openfiles: %s", errbuf);
2621590Srgrimes
2631590Srgrimes	if ((c = kvm_nlist(kd, namelist)) != 0) {
2641590Srgrimes		if (c > 0) {
26528693Scharnier			warnx("undefined symbols:");
2661590Srgrimes			for (c = 0;
2671590Srgrimes			    c < sizeof(namelist)/sizeof(namelist[0]); c++)
2681590Srgrimes				if (namelist[c].n_type == 0)
2691590Srgrimes					fprintf(stderr, " %s",
2701590Srgrimes					    namelist[c].n_name);
2711590Srgrimes			(void)fputc('\n', stderr);
2721590Srgrimes		} else
27328693Scharnier			warnx("kvm_nlist: %s", kvm_geterr(kd));
2741590Srgrimes		exit(1);
2751590Srgrimes	}
2761590Srgrimes
2771590Srgrimes	if (todo & VMSTAT) {
2781590Srgrimes		char **getdrivedata();
2791590Srgrimes		struct winsize winsize;
2801590Srgrimes
28143819Sken		/*
28243819Sken		 * Make sure that the userland devstat version matches the
28343819Sken		 * kernel devstat version.  If not, exit and print a
28443819Sken		 * message informing the user of his mistake.
28543819Sken		 */
28643819Sken		if (checkversion() < 0)
28743819Sken			errx(1, "%s", devstat_errbuf);
28843819Sken
28943819Sken
2901590Srgrimes		argv = getdrivedata(argv);
2911590Srgrimes		winsize.ws_row = 0;
2921590Srgrimes		(void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
2931590Srgrimes		if (winsize.ws_row > 0)
2941590Srgrimes			winlines = winsize.ws_row;
2951590Srgrimes
2961590Srgrimes	}
2971590Srgrimes
2981590Srgrimes#define	BACKWARD_COMPATIBILITY
2991590Srgrimes#ifdef	BACKWARD_COMPATIBILITY
3001590Srgrimes	if (*argv) {
3011590Srgrimes		interval = atoi(*argv);
3021590Srgrimes		if (*++argv)
3031590Srgrimes			reps = atoi(*argv);
3041590Srgrimes	}
3051590Srgrimes#endif
3061590Srgrimes
3071590Srgrimes	if (interval) {
3081590Srgrimes		if (!reps)
3091590Srgrimes			reps = -1;
3101590Srgrimes	} else if (reps)
3111590Srgrimes		interval = 1;
3121590Srgrimes
31330180Sdima#ifdef notyet
3141590Srgrimes	if (todo & FORKSTAT)
3151590Srgrimes		doforkst();
3161590Srgrimes#endif
3171590Srgrimes	if (todo & MEMSTAT)
3181590Srgrimes		domem();
3191590Srgrimes	if (todo & SUMSTAT)
3201590Srgrimes		dosum();
32130180Sdima#ifdef notyet
3221590Srgrimes	if (todo & TIMESTAT)
3231590Srgrimes		dotimes();
3241590Srgrimes#endif
3251590Srgrimes	if (todo & INTRSTAT)
3261590Srgrimes		dointr();
3271590Srgrimes	if (todo & VMSTAT)
3281590Srgrimes		dovmstat(interval, reps);
3291590Srgrimes	exit(0);
3301590Srgrimes}
3311590Srgrimes
3321590Srgrimeschar **
3331590Srgrimesgetdrivedata(argv)
3341590Srgrimes	char **argv;
3351590Srgrimes{
3361590Srgrimes	register int i;
3371590Srgrimes	char buf[30];
3381590Srgrimes
33939230Sgibbs	if ((num_devices = getnumdevs()) < 0)
34039230Sgibbs		errx(1, "%s", devstat_errbuf);
3411590Srgrimes
34239230Sgibbs	cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo));
34339230Sgibbs	last.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo));
34439230Sgibbs	bzero(cur.dinfo, sizeof(struct devinfo));
34539230Sgibbs	bzero(last.dinfo, sizeof(struct devinfo));
34639230Sgibbs
34739230Sgibbs	if (getdevs(&cur) == -1)
34839230Sgibbs		errx(1, "%s", devstat_errbuf);
34939230Sgibbs
35039230Sgibbs	num_devices = cur.dinfo->numdevs;
35139230Sgibbs	generation = cur.dinfo->generation;
35239230Sgibbs
35339230Sgibbs	specified_devices = (char **)malloc(sizeof(char *));
35439230Sgibbs	for (num_devices_specified = 0; *argv; ++argv) {
3551590Srgrimes		if (isdigit(**argv))
3561590Srgrimes			break;
35739230Sgibbs		num_devices_specified++;
35839230Sgibbs		specified_devices = (char **)realloc(specified_devices,
35939230Sgibbs						     sizeof(char *) *
36039230Sgibbs						     num_devices_specified);
36139230Sgibbs		specified_devices[num_devices_specified - 1] = *argv;
3621590Srgrimes	}
36339230Sgibbs	dev_select = NULL;
36439230Sgibbs
36539372Sdillon	if (nflag == 0 && maxshowdevs < num_devices_specified)
36639372Sdillon			maxshowdevs = num_devices_specified;
36739372Sdillon
36839230Sgibbs	/*
36939230Sgibbs	 * People are generally only interested in disk statistics when
37039230Sgibbs	 * they're running vmstat.  So, that's what we're going to give
37139230Sgibbs	 * them if they don't specify anything by default.  We'll also give
37239230Sgibbs	 * them any other random devices in the system so that we get to
37339230Sgibbs	 * maxshowdevs devices, if that many devices exist.  If the user
37439230Sgibbs	 * specifies devices on the command line, either through a pattern
37539230Sgibbs	 * match or by naming them explicitly, we will give the user only
37639230Sgibbs	 * those devices.
37739230Sgibbs	 */
37839230Sgibbs	if ((num_devices_specified == 0) && (num_matches == 0)) {
37939230Sgibbs		if (buildmatch("da", &matches, &num_matches) != 0)
38039230Sgibbs			errx(1, "%s", devstat_errbuf);
38139230Sgibbs
38239230Sgibbs		select_mode = DS_SELECT_ADD;
38339230Sgibbs	} else
38439230Sgibbs		select_mode = DS_SELECT_ONLY;
38539230Sgibbs
38639230Sgibbs	/*
38739230Sgibbs	 * At this point, selectdevs will almost surely indicate that the
38839230Sgibbs	 * device list has changed, so we don't look for return values of 0
38939230Sgibbs	 * or 1.  If we get back -1, though, there is an error.
39039230Sgibbs	 */
39139230Sgibbs	if (selectdevs(&dev_select, &num_selected, &num_selections,
39239230Sgibbs		       &select_generation, generation, cur.dinfo->devices,
39339230Sgibbs		       num_devices, matches, num_matches, specified_devices,
39439230Sgibbs		       num_devices_specified, select_mode,
39539230Sgibbs		       maxshowdevs, 0) == -1)
39639230Sgibbs		errx(1, "%s", devstat_errbuf);
39739230Sgibbs
3981590Srgrimes	return(argv);
3991590Srgrimes}
4001590Srgrimes
4011590Srgrimeslong
4021590Srgrimesgetuptime()
4031590Srgrimes{
4041590Srgrimes	static time_t now, boottime;
4051590Srgrimes	time_t uptime;
4061590Srgrimes
4071590Srgrimes	if (boottime == 0)
4081590Srgrimes		kread(X_BOOTTIME, &boottime, sizeof(boottime));
4091590Srgrimes	(void)time(&now);
4101590Srgrimes	uptime = now - boottime;
41128693Scharnier	if (uptime <= 0 || uptime > 60*60*24*365*10)
41228693Scharnier		errx(1, "time makes no sense; namelist must be wrong");
4131590Srgrimes	return(uptime);
4141590Srgrimes}
4151590Srgrimes
4161590Srgrimesint	hz, hdrcnt;
4171590Srgrimes
4181590Srgrimesvoid
4191590Srgrimesdovmstat(interval, reps)
4201590Srgrimes	u_int interval;
4211590Srgrimes	int reps;
4221590Srgrimes{
4231590Srgrimes	struct vmtotal total;
4241590Srgrimes	time_t uptime, halfuptime;
42539230Sgibbs	struct devinfo *tmp_dinfo;
4261590Srgrimes	void needhdr();
4271590Srgrimes	int mib[2], size;
4281590Srgrimes
4291590Srgrimes	uptime = getuptime();
4301590Srgrimes	halfuptime = uptime / 2;
4311590Srgrimes	(void)signal(SIGCONT, needhdr);
4321590Srgrimes
4331590Srgrimes	if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
4341590Srgrimes		kread(X_STATHZ, &hz, sizeof(hz));
4351590Srgrimes	if (!hz)
4361590Srgrimes		kread(X_HZ, &hz, sizeof(hz));
4371590Srgrimes
4381590Srgrimes	for (hdrcnt = 1;;) {
4391590Srgrimes		if (!--hdrcnt)
4401590Srgrimes			printhdr();
44139230Sgibbs		kread(X_CPTIME, cur.cp_time, sizeof(cur.cp_time));
44239230Sgibbs
44339230Sgibbs		tmp_dinfo = last.dinfo;
44439230Sgibbs		last.dinfo = cur.dinfo;
44539230Sgibbs		cur.dinfo = tmp_dinfo;
44639230Sgibbs		last.busy_time = cur.busy_time;
44739230Sgibbs
44839230Sgibbs		/*
44939230Sgibbs		 * Here what we want to do is refresh our device stats.
45039230Sgibbs		 * getdevs() returns 1 when the device list has changed.
45139230Sgibbs		 * If the device list has changed, we want to go through
45239230Sgibbs		 * the selection process again, in case a device that we
45339230Sgibbs		 * were previously displaying has gone away.
45439230Sgibbs		 */
45539230Sgibbs		switch (getdevs(&cur)) {
45639230Sgibbs		case -1:
45739230Sgibbs			errx(1, "%s", devstat_errbuf);
45839230Sgibbs			break;
45939230Sgibbs		case 1: {
46039230Sgibbs			int retval;
46139230Sgibbs
46239230Sgibbs			num_devices = cur.dinfo->numdevs;
46339230Sgibbs			generation = cur.dinfo->generation;
46439230Sgibbs
46539230Sgibbs			retval = selectdevs(&dev_select, &num_selected,
46639230Sgibbs					    &num_selections, &select_generation,
46739230Sgibbs					    generation, cur.dinfo->devices,
46839230Sgibbs					    num_devices, matches, num_matches,
46939230Sgibbs					    specified_devices,
47039230Sgibbs					    num_devices_specified, select_mode,
47139230Sgibbs					    maxshowdevs, 0);
47239230Sgibbs			switch (retval) {
47339230Sgibbs			case -1:
47439230Sgibbs				errx(1, "%s", devstat_errbuf);
47539230Sgibbs				break;
47639230Sgibbs			case 1:
47739230Sgibbs				printhdr();
47839230Sgibbs				break;
47939230Sgibbs			default:
48039230Sgibbs				break;
48139230Sgibbs			}
48239230Sgibbs		}
48339230Sgibbs		default:
48439230Sgibbs			break;
48539230Sgibbs		}
48639230Sgibbs
4871590Srgrimes		kread(X_SUM, &sum, sizeof(sum));
4881590Srgrimes		size = sizeof(total);
4891590Srgrimes		mib[0] = CTL_VM;
4901590Srgrimes		mib[1] = VM_METER;
4911590Srgrimes		if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
4921590Srgrimes			printf("Can't get kerninfo: %s\n", strerror(errno));
4931590Srgrimes			bzero(&total, sizeof(total));
4941590Srgrimes		}
4951590Srgrimes		(void)printf("%2d%2d%2d",
4961590Srgrimes		    total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
4971590Srgrimes#define pgtok(a) ((a) * sum.v_page_size >> 10)
4981590Srgrimes#define	rate(x)	(((x) + halfuptime) / uptime)	/* round */
49923952Sscrappy		(void)printf("%8ld%6ld ",
50028693Scharnier		    (long)pgtok(total.t_avm), (long)pgtok(total.t_free));
50137453Sbde		(void)printf("%4lu ",
50237453Sbde		    (u_long)rate(sum.v_vm_faults - osum.v_vm_faults));
5031590Srgrimes		(void)printf("%3lu ",
50437453Sbde		    (u_long)rate(sum.v_reactivated - osum.v_reactivated));
50537453Sbde		(void)printf("%3lu ",
50637453Sbde		    (u_long)rate(sum.v_swapin + sum.v_vnodein -
5073659Sdg		    (osum.v_swapin + osum.v_vnodein)));
50837453Sbde		(void)printf("%3lu ",
50937453Sbde		    (u_long)rate(sum.v_swapout + sum.v_vnodeout -
5103693Sdg		    (osum.v_swapout + osum.v_vnodeout)));
51137453Sbde		(void)printf("%3lu ",
51237453Sbde		    (u_long)rate(sum.v_tfree - osum.v_tfree));
51337453Sbde		(void)printf("%3lu ",
51437453Sbde		    (u_long)rate(sum.v_pdpages - osum.v_pdpages));
51539230Sgibbs		devstats();
5161590Srgrimes		(void)printf("%4lu %4lu %3lu ",
51737453Sbde		    (u_long)rate(sum.v_intr - osum.v_intr),
51837453Sbde		    (u_long)rate(sum.v_syscall - osum.v_syscall),
51937453Sbde		    (u_long)rate(sum.v_swtch - osum.v_swtch));
5201590Srgrimes		cpustats();
5211590Srgrimes		(void)printf("\n");
5221590Srgrimes		(void)fflush(stdout);
5231590Srgrimes		if (reps >= 0 && --reps <= 0)
5241590Srgrimes			break;
5251590Srgrimes		osum = sum;
5261590Srgrimes		uptime = interval;
5271590Srgrimes		/*
5281590Srgrimes		 * We round upward to avoid losing low-frequency events
5291590Srgrimes		 * (i.e., >= 1 per interval but < 1 per second).
5301590Srgrimes		 */
5313659Sdg		if (interval != 1)
5323659Sdg			halfuptime = (uptime + 1) / 2;
5333659Sdg		else
5343659Sdg			halfuptime = 0;
5351590Srgrimes		(void)sleep(interval);
5361590Srgrimes	}
5371590Srgrimes}
5381590Srgrimes
53928693Scharniervoid
5401590Srgrimesprinthdr()
5411590Srgrimes{
5421590Srgrimes	register int i;
5431590Srgrimes
54439230Sgibbs	(void)printf(" procs      memory     page%*s", 19, "");
54539230Sgibbs	if (num_selected > 1)
5461590Srgrimes		(void)printf("disks %*s  faults      cpu\n",
54739230Sgibbs		   ((num_selected < maxshowdevs) ? num_selected :
54839230Sgibbs		    maxshowdevs ) * 4 - 7, "");
54939230Sgibbs	else if (num_selected == 1)
55039230Sgibbs		(void)printf("disk faults      cpu\n");
5511590Srgrimes	else
55239230Sgibbs		(void)printf("%*s  faults      cpu\n", num_selected * 4, "");
55339230Sgibbs
55423952Sscrappy	(void)printf(" r b w     avm   fre  flt  re  pi  po  fr  sr ");
55539230Sgibbs	for (i = 0; i < num_devices; i++)
55639230Sgibbs		if ((dev_select[i].selected)
55739230Sgibbs		 && (dev_select[i].selected <= maxshowdevs))
55839230Sgibbs			(void)printf("%c%c%d ", dev_select[i].device_name[0],
55939230Sgibbs				     dev_select[i].device_name[1],
56039230Sgibbs				     dev_select[i].unit_number);
5611590Srgrimes	(void)printf("  in   sy  cs us sy id\n");
5621590Srgrimes	hdrcnt = winlines - 2;
5631590Srgrimes}
5641590Srgrimes
5651590Srgrimes/*
5661590Srgrimes * Force a header to be prepended to the next output.
5671590Srgrimes */
5681590Srgrimesvoid
5691590Srgrimesneedhdr()
5701590Srgrimes{
5711590Srgrimes
5721590Srgrimes	hdrcnt = 1;
5731590Srgrimes}
5741590Srgrimes
57530180Sdima#ifdef notyet
5761590Srgrimesvoid
5771590Srgrimesdotimes()
5781590Srgrimes{
5791590Srgrimes	u_int pgintime, rectime;
5801590Srgrimes
5811590Srgrimes	kread(X_REC, &rectime, sizeof(rectime));
5821590Srgrimes	kread(X_PGIN, &pgintime, sizeof(pgintime));
5831590Srgrimes	kread(X_SUM, &sum, sizeof(sum));
5841590Srgrimes	(void)printf("%u reclaims, %u total time (usec)\n",
5851590Srgrimes	    sum.v_pgrec, rectime);
5861590Srgrimes	(void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec);
5871590Srgrimes	(void)printf("\n");
5881590Srgrimes	(void)printf("%u page ins, %u total time (msec)\n",
5891590Srgrimes	    sum.v_pgin, pgintime / 10);
5901590Srgrimes	(void)printf("average: %8.1f msec / page in\n",
5911590Srgrimes	    pgintime / (sum.v_pgin * 10.0));
5921590Srgrimes}
5931590Srgrimes#endif
5941590Srgrimes
59528693Scharnierlong
5961590Srgrimespct(top, bot)
5971590Srgrimes	long top, bot;
5981590Srgrimes{
5991590Srgrimes	long ans;
6001590Srgrimes
6011590Srgrimes	if (bot == 0)
6021590Srgrimes		return(0);
6031590Srgrimes	ans = (quad_t)top * 100 / bot;
6041590Srgrimes	return (ans);
6051590Srgrimes}
6061590Srgrimes
6071590Srgrimes#define	PCT(top, bot) pct((long)(top), (long)(bot))
6081590Srgrimes
6091590Srgrimes#if defined(tahoe)
6101590Srgrimes#include <machine/cpu.h>
6111590Srgrimes#endif
6121590Srgrimes
6131590Srgrimesvoid
6141590Srgrimesdosum()
6151590Srgrimes{
6161590Srgrimes	struct nchstats nchstats;
6171590Srgrimes	long nchtotal;
6181590Srgrimes#if defined(tahoe)
6191590Srgrimes	struct keystats keystats;
6201590Srgrimes#endif
6211590Srgrimes
6221590Srgrimes	kread(X_SUM, &sum, sizeof(sum));
6231590Srgrimes	(void)printf("%9u cpu context switches\n", sum.v_swtch);
6241590Srgrimes	(void)printf("%9u device interrupts\n", sum.v_intr);
6251590Srgrimes	(void)printf("%9u software interrupts\n", sum.v_soft);
6261590Srgrimes#ifdef vax
6271590Srgrimes	(void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma);
6281590Srgrimes#endif
6291590Srgrimes	(void)printf("%9u traps\n", sum.v_trap);
6301590Srgrimes	(void)printf("%9u system calls\n", sum.v_syscall);
6313659Sdg	(void)printf("%9u swap pager pageins\n", sum.v_swapin);
6323693Sdg	(void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin);
6333659Sdg	(void)printf("%9u swap pager pageouts\n", sum.v_swapout);
6343659Sdg	(void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout);
6353659Sdg	(void)printf("%9u vnode pager pageins\n", sum.v_vnodein);
6363693Sdg	(void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin);
6373659Sdg	(void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout);
6383659Sdg	(void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout);
6393693Sdg	(void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups);
6403693Sdg	(void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages);
6411590Srgrimes	(void)printf("%9u pages reactivated\n", sum.v_reactivated);
6427351Sdg	(void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
64334214Sdyson	(void)printf("%9u copy-on-write optimized faults\n", sum.v_cow_optim);
6447351Sdg	(void)printf("%9u zero fill pages zeroed\n", sum.v_zfod);
64534214Sdyson	(void)printf("%9u zero fill pages prezeroed\n", sum.v_ozfod);
6461590Srgrimes	(void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
6471590Srgrimes	(void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
6483693Sdg	(void)printf("%9u pages freed\n", sum.v_tfree);
6491590Srgrimes	(void)printf("%9u pages freed by daemon\n", sum.v_dfree);
6501590Srgrimes	(void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
6511590Srgrimes	(void)printf("%9u pages active\n", sum.v_active_count);
6521590Srgrimes	(void)printf("%9u pages inactive\n", sum.v_inactive_count);
6535463Sdg	(void)printf("%9u pages in VM cache\n", sum.v_cache_count);
6543693Sdg	(void)printf("%9u pages wired down\n", sum.v_wire_count);
6553693Sdg	(void)printf("%9u pages free\n", sum.v_free_count);
6561590Srgrimes	(void)printf("%9u bytes per page\n", sum.v_page_size);
6571590Srgrimes	kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
6581590Srgrimes	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
6591590Srgrimes	    nchstats.ncs_badhits + nchstats.ncs_falsehits +
6601590Srgrimes	    nchstats.ncs_miss + nchstats.ncs_long;
6611590Srgrimes	(void)printf("%9ld total name lookups\n", nchtotal);
6621590Srgrimes	(void)printf(
66328693Scharnier	    "%9s cache hits (%ld%% pos + %ld%% neg) system %ld%% per-directory\n",
6641590Srgrimes	    "", PCT(nchstats.ncs_goodhits, nchtotal),
6651590Srgrimes	    PCT(nchstats.ncs_neghits, nchtotal),
6661590Srgrimes	    PCT(nchstats.ncs_pass2, nchtotal));
66728693Scharnier	(void)printf("%9s deletions %ld%%, falsehits %ld%%, toolong %ld%%\n", "",
6681590Srgrimes	    PCT(nchstats.ncs_badhits, nchtotal),
6691590Srgrimes	    PCT(nchstats.ncs_falsehits, nchtotal),
6701590Srgrimes	    PCT(nchstats.ncs_long, nchtotal));
6711590Srgrimes#if defined(tahoe)
6721590Srgrimes	kread(X_CKEYSTATS, &keystats, sizeof(keystats));
6731590Srgrimes	(void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
6741590Srgrimes	    keystats.ks_allocs, "code cache keys allocated",
6751590Srgrimes	    PCT(keystats.ks_allocfree, keystats.ks_allocs),
6761590Srgrimes	    PCT(keystats.ks_norefs, keystats.ks_allocs),
6771590Srgrimes	    PCT(keystats.ks_taken, keystats.ks_allocs),
6781590Srgrimes	    PCT(keystats.ks_shared, keystats.ks_allocs));
6791590Srgrimes	kread(X_DKEYSTATS, &keystats, sizeof(keystats));
6801590Srgrimes	(void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
6811590Srgrimes	    keystats.ks_allocs, "data cache keys allocated",
6821590Srgrimes	    PCT(keystats.ks_allocfree, keystats.ks_allocs),
6831590Srgrimes	    PCT(keystats.ks_norefs, keystats.ks_allocs),
6841590Srgrimes	    PCT(keystats.ks_taken, keystats.ks_allocs),
6851590Srgrimes	    PCT(keystats.ks_shared, keystats.ks_allocs));
6861590Srgrimes#endif
6871590Srgrimes}
6881590Srgrimes
68930180Sdima#ifdef notyet
6901590Srgrimesvoid
6911590Srgrimesdoforkst()
6921590Srgrimes{
6931590Srgrimes	struct forkstat fks;
6941590Srgrimes
6951590Srgrimes	kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
6961590Srgrimes	(void)printf("%d forks, %d pages, average %.2f\n",
6971590Srgrimes	    fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
6981590Srgrimes	(void)printf("%d vforks, %d pages, average %.2f\n",
6991590Srgrimes	    fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork);
7001590Srgrimes}
7011590Srgrimes#endif
7021590Srgrimes
70339230Sgibbsstatic void
70439230Sgibbsdevstats()
7051590Srgrimes{
7061590Srgrimes	register int dn, state;
70739230Sgibbs	long double transfers_per_second;
70839230Sgibbs	long double busy_seconds;
7091590Srgrimes	long tmp;
71039230Sgibbs
7111590Srgrimes	for (state = 0; state < CPUSTATES; ++state) {
71239230Sgibbs		tmp = cur.cp_time[state];
71339230Sgibbs		cur.cp_time[state] -= last.cp_time[state];
71439230Sgibbs		last.cp_time[state] = tmp;
7151590Srgrimes	}
71639230Sgibbs
71739230Sgibbs	busy_seconds = compute_etime(cur.busy_time, last.busy_time);
71839230Sgibbs
71939230Sgibbs	for (dn = 0; dn < num_devices; dn++) {
72039230Sgibbs		int di;
72139230Sgibbs
72239230Sgibbs		if ((dev_select[dn].selected == 0)
72339230Sgibbs		 || (dev_select[dn].selected > maxshowdevs))
7241590Srgrimes			continue;
72539230Sgibbs
72639230Sgibbs		di = dev_select[dn].position;
72739230Sgibbs
72839230Sgibbs		if (compute_stats(&cur.dinfo->devices[di],
72939230Sgibbs				  &last.dinfo->devices[di], busy_seconds,
73039230Sgibbs				  NULL, NULL, NULL,
73139230Sgibbs				  NULL, &transfers_per_second, NULL,
73239230Sgibbs				  NULL, NULL) != 0)
73339230Sgibbs			errx(1, "%s", devstat_errbuf);
73439230Sgibbs
73539230Sgibbs		printf("%3.0Lf ", transfers_per_second);
7361590Srgrimes	}
7371590Srgrimes}
7381590Srgrimes
7391590Srgrimesvoid
7401590Srgrimescpustats()
7411590Srgrimes{
7421590Srgrimes	register int state;
7431590Srgrimes	double pct, total;
7441590Srgrimes
7451590Srgrimes	total = 0;
7461590Srgrimes	for (state = 0; state < CPUSTATES; ++state)
74739230Sgibbs		total += cur.cp_time[state];
7481590Srgrimes	if (total)
7491590Srgrimes		pct = 100 / total;
7501590Srgrimes	else
7511590Srgrimes		pct = 0;
75239230Sgibbs	(void)printf("%2.0f ", (cur.cp_time[CP_USER] +
75339230Sgibbs				cur.cp_time[CP_NICE]) * pct);
75439230Sgibbs	(void)printf("%2.0f ", (cur.cp_time[CP_SYS] +
75539230Sgibbs				cur.cp_time[CP_INTR]) * pct);
75639230Sgibbs	(void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
7571590Srgrimes}
7581590Srgrimes
7591590Srgrimesvoid
7601590Srgrimesdointr()
7611590Srgrimes{
7621590Srgrimes	register long *intrcnt, inttotal, uptime;
7631590Srgrimes	register int nintr, inamlen;
7641590Srgrimes	register char *intrname;
7651590Srgrimes
7661590Srgrimes	uptime = getuptime();
7671590Srgrimes	nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
7681590Srgrimes	inamlen =
7691590Srgrimes	    namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
7701590Srgrimes	intrcnt = malloc((size_t)nintr);
7711590Srgrimes	intrname = malloc((size_t)inamlen);
77228693Scharnier	if (intrcnt == NULL || intrname == NULL)
77328693Scharnier		errx(1, "malloc");
7741590Srgrimes	kread(X_INTRCNT, intrcnt, (size_t)nintr);
7751590Srgrimes	kread(X_INTRNAMES, intrname, (size_t)inamlen);
7761590Srgrimes	(void)printf("interrupt      total      rate\n");
7771590Srgrimes	inttotal = 0;
7781590Srgrimes	nintr /= sizeof(long);
7791590Srgrimes	while (--nintr >= 0) {
7801590Srgrimes		if (*intrcnt)
7811590Srgrimes			(void)printf("%-12s %8ld %8ld\n", intrname,
7821590Srgrimes			    *intrcnt, *intrcnt / uptime);
7831590Srgrimes		intrname += strlen(intrname) + 1;
7841590Srgrimes		inttotal += *intrcnt++;
7851590Srgrimes	}
7861590Srgrimes	(void)printf("Total        %8ld %8ld\n", inttotal, inttotal / uptime);
7871590Srgrimes}
7881590Srgrimes
7891590Srgrimesvoid
7901590Srgrimesdomem()
7911590Srgrimes{
7921590Srgrimes	register struct kmembuckets *kp;
79330287Sphk	register struct malloc_type *ks;
7941590Srgrimes	register int i, j;
79530279Sphk	int len, size, first, nkms;
7961590Srgrimes	long totuse = 0, totfree = 0, totreq = 0;
79731560Sbde	const char *name;
79837453Sbde	struct malloc_type kmemstats[200], *kmsp;
79930279Sphk	char *kmemnames[200];
80030279Sphk	char buf[1024];
8011590Srgrimes	struct kmembuckets buckets[MINBUCKET + 16];
8021590Srgrimes
8031590Srgrimes	kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
80430279Sphk	kread(X_KMEMSTATISTICS, &kmsp, sizeof(kmsp));
80537453Sbde	for (nkms = 0; nkms < 200 && kmsp != NULL; nkms++) {
80630279Sphk		if (sizeof(kmemstats[0]) != kvm_read(kd, (u_long)kmsp,
80730279Sphk		    &kmemstats[nkms], sizeof(kmemstats[0])))
80837453Sbde			err(1, "kvm_read(%p)", (void *)kmsp);
80930279Sphk		if (sizeof(buf) !=  kvm_read(kd,
81030279Sphk	            (u_long)kmemstats[nkms].ks_shortdesc, buf, sizeof(buf)))
81137453Sbde			err(1, "kvm_read(%p)",
81237453Sbde			    (void *)kmemstats[nkms].ks_shortdesc);
81330279Sphk		kmemstats[nkms].ks_shortdesc = strdup(buf);
81430279Sphk		kmsp = kmemstats[nkms].ks_next;
81530279Sphk	}
8161590Srgrimes	(void)printf("Memory statistics by bucket size\n");
8171590Srgrimes	(void)printf(
8183372Sphk	    "Size   In Use   Free   Requests  HighWater  Couldfree\n");
8191590Srgrimes	for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
8201590Srgrimes		if (kp->kb_calls == 0)
8211590Srgrimes			continue;
8221590Srgrimes		size = 1 << i;
8233372Sphk		if(size < 1024)
8243372Sphk			(void)printf("%4d",size);
8253372Sphk		else
8263372Sphk			(void)printf("%3dK",size>>10);
8278874Srgrimes		(void)printf(" %8ld %6ld %10ld %7ld %10ld\n",
8281590Srgrimes			kp->kb_total - kp->kb_totalfree,
8291590Srgrimes			kp->kb_totalfree, kp->kb_calls,
8301590Srgrimes			kp->kb_highwat, kp->kb_couldfree);
8311590Srgrimes		totfree += size * kp->kb_totalfree;
8321590Srgrimes	}
8331590Srgrimes
8341590Srgrimes	(void)printf("\nMemory usage type by bucket size\n");
8353372Sphk	(void)printf("Size  Type(s)\n");
8361590Srgrimes	kp = &buckets[MINBUCKET];
8371590Srgrimes	for (j =  1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
8381590Srgrimes		if (kp->kb_calls == 0)
8391590Srgrimes			continue;
8401590Srgrimes		first = 1;
8411590Srgrimes		len = 8;
84230279Sphk		for (i = 0, ks = &kmemstats[0]; i < nkms; i++, ks++) {
8431590Srgrimes			if (ks->ks_calls == 0)
8441590Srgrimes				continue;
8451590Srgrimes			if ((ks->ks_size & j) == 0)
8461590Srgrimes				continue;
84730279Sphk			name = ks->ks_shortdesc;
8481590Srgrimes			len += 2 + strlen(name);
8493372Sphk			if (first && j < 1024)
8503372Sphk				printf("%4d  %s", j, name);
8513372Sphk			else if (first)
8523372Sphk				printf("%3dK  %s", j>>10, name);
8531590Srgrimes			else
8541590Srgrimes				printf(",");
8553372Sphk			if (len >= 79) {
8561590Srgrimes				printf("\n\t ");
8571590Srgrimes				len = 10 + strlen(name);
8581590Srgrimes			}
8591590Srgrimes			if (!first)
8601590Srgrimes				printf(" %s", name);
8611590Srgrimes			first = 0;
8621590Srgrimes		}
8631590Srgrimes		printf("\n");
8641590Srgrimes	}
8651590Srgrimes
8661590Srgrimes	(void)printf(
8673372Sphk	    "\nMemory statistics by type                          Type  Kern\n");
8681590Srgrimes	(void)printf(
8693372Sphk"        Type  InUse MemUse HighUse  Limit Requests Limit Limit Size(s)\n");
87030279Sphk	for (i = 0, ks = &kmemstats[0]; i < nkms; i++, ks++) {
8711590Srgrimes		if (ks->ks_calls == 0)
8721590Srgrimes			continue;
8733372Sphk		(void)printf("%13s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
87430279Sphk		    ks->ks_shortdesc,
8751590Srgrimes		    ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
8761590Srgrimes		    (ks->ks_maxused + 1023) / 1024,
8771590Srgrimes		    (ks->ks_limit + 1023) / 1024, ks->ks_calls,
8781590Srgrimes		    ks->ks_limblocks, ks->ks_mapblocks);
8791590Srgrimes		first = 1;
8801590Srgrimes		for (j =  1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
8811590Srgrimes			if ((ks->ks_size & j) == 0)
8821590Srgrimes				continue;
8831590Srgrimes			if (first)
8843372Sphk				printf("  ");
8851590Srgrimes			else
8863372Sphk				printf(",");
8873372Sphk			if(j<1024)
8883372Sphk				printf("%d",j);
8893372Sphk			else
8903372Sphk				printf("%dK",j>>10);
8911590Srgrimes			first = 0;
8921590Srgrimes		}
8931590Srgrimes		printf("\n");
8941590Srgrimes		totuse += ks->ks_memuse;
8951590Srgrimes		totreq += ks->ks_calls;
8961590Srgrimes	}
8971590Srgrimes	(void)printf("\nMemory Totals:  In Use    Free    Requests\n");
8981590Srgrimes	(void)printf("              %7ldK %6ldK    %8ld\n",
8991590Srgrimes	     (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
9001590Srgrimes}
9011590Srgrimes
9021590Srgrimes/*
9031590Srgrimes * kread reads something from the kernel, given its nlist index.
9041590Srgrimes */
9051590Srgrimesvoid
9061590Srgrimeskread(nlx, addr, size)
9071590Srgrimes	int nlx;
9081590Srgrimes	void *addr;
9091590Srgrimes	size_t size;
9101590Srgrimes{
9111590Srgrimes	char *sym;
9121590Srgrimes
91340690Sjdp	if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
9141590Srgrimes		sym = namelist[nlx].n_name;
9151590Srgrimes		if (*sym == '_')
9161590Srgrimes			++sym;
91728693Scharnier		errx(1, "symbol %s not defined", sym);
9181590Srgrimes	}
9191590Srgrimes	if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
9201590Srgrimes		sym = namelist[nlx].n_name;
9211590Srgrimes		if (*sym == '_')
9221590Srgrimes			++sym;
92328693Scharnier		errx(1, "%s: %s", sym, kvm_geterr(kd));
9241590Srgrimes	}
9251590Srgrimes}
9261590Srgrimes
9271590Srgrimesvoid
9281590Srgrimesusage()
9291590Srgrimes{
9301590Srgrimes	(void)fprintf(stderr,
93128693Scharnier"usage: vmstat [-ims] [-c count] [-M core] [-N system] [-w wait] [disks]\n");
9321590Srgrimes	exit(1);
9331590Srgrimes}
934