xref: /csrg-svn/usr.bin/vmstat/vmstat.c (revision 46892)
121585Sdist /*
236580Sbostic  * Copyright (c) 1980 The Regents of the University of California.
336580Sbostic  * All rights reserved.
436580Sbostic  *
542784Sbostic  * %sccs.include.redist.c%
621585Sdist  */
721585Sdist 
810826Ssam #ifndef lint
921585Sdist char copyright[] =
1036580Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
1121585Sdist  All rights reserved.\n";
1236580Sbostic #endif /* not lint */
1310826Ssam 
1421585Sdist #ifndef lint
15*46892Sbostic static char sccsid[] = "@(#)vmstat.c	5.24 (Berkeley) 03/02/91";
1636580Sbostic #endif /* not lint */
1721585Sdist 
181155Sbill #include <sys/param.h>
1918761Ssam #include <sys/file.h>
201155Sbill #include <sys/vm.h>
21*46892Sbostic #include <sys/user.h>
2229664Ssam #include <sys/dkstat.h>
233162Stoy #include <sys/buf.h>
2417262Smckusick #include <sys/namei.h>
2525708Ssam #include <sys/text.h>
2633610Smckusick #include <sys/malloc.h>
2737912Sbostic #include <ctype.h>
2845834Sbostic #include <errno.h>
2945834Sbostic #include <kvm.h>
3037912Sbostic #include <nlist.h>
3145834Sbostic #include <stdio.h>
3245834Sbostic #include <stdlib.h>
3345834Sbostic #include <string.h>
3437912Sbostic #include <paths.h>
351155Sbill 
361155Sbill struct nlist nl[] = {
371448Sbill #define	X_CPTIME	0
381448Sbill 	{ "_cp_time" },
391448Sbill #define	X_RATE		1
401155Sbill 	{ "_rate" },
411448Sbill #define X_TOTAL		2
421155Sbill 	{ "_total" },
431448Sbill #define	X_DEFICIT	3
441155Sbill 	{ "_deficit" },
451448Sbill #define	X_FORKSTAT	4
461155Sbill 	{ "_forkstat" },
471448Sbill #define X_SUM		5
481155Sbill 	{ "_sum" },
491448Sbill #define	X_FIRSTFREE	6
501155Sbill 	{ "_firstfree" },
511448Sbill #define	X_MAXFREE	7
521155Sbill 	{ "_maxfree" },
539249Ssam #define	X_BOOTTIME	8
549249Ssam 	{ "_boottime" },
551448Sbill #define	X_DKXFER	9
561448Sbill 	{ "_dk_xfer" },
5710826Ssam #define X_REC		10
581155Sbill 	{ "_rectime" },
5910826Ssam #define X_PGIN		11
601155Sbill 	{ "_pgintime" },
6110826Ssam #define X_HZ		12
623162Stoy 	{ "_hz" },
6318761Ssam #define X_PHZ		13
6415266Ssam 	{ "_phz" },
6515807Smckusick #define X_NCHSTATS	14
6615807Smckusick 	{ "_nchstats" },
6717262Smckusick #define	X_INTRNAMES	15
6817262Smckusick 	{ "_intrnames" },
6917262Smckusick #define	X_EINTRNAMES	16
7017262Smckusick 	{ "_eintrnames" },
7117262Smckusick #define	X_INTRCNT	17
7217262Smckusick 	{ "_intrcnt" },
7317262Smckusick #define	X_EINTRCNT	18
7417262Smckusick 	{ "_eintrcnt" },
7518761Ssam #define	X_DK_NDRIVE	19
7618761Ssam 	{ "_dk_ndrive" },
7725512Ssam #define	X_XSTATS	20
7825512Ssam 	{ "_xstats" },
7933610Smckusick #define	X_KMEMSTAT	21
8033610Smckusick 	{ "_kmemstats" },
8133610Smckusick #define	X_KMEMBUCKETS	22
8233610Smckusick 	{ "_bucket" },
8342952Sbostic #define X_END		22
8410826Ssam #ifdef vax
8542952Sbostic #define X_MBDINIT	(X_END+1)
8610826Ssam 	{ "_mbdinit" },
8742952Sbostic #define X_UBDINIT	(X_END+2)
8810826Ssam 	{ "_ubdinit" },
8910826Ssam #endif
9025708Ssam #ifdef tahoe
9142952Sbostic #define	X_VBDINIT	(X_END+1)
9225708Ssam 	{ "_vbdinit" },
9342952Sbostic #define	X_CKEYSTATS	(X_END+2)
9425960Ssam 	{ "_ckeystats" },
9542952Sbostic #define	X_DKEYSTATS	(X_END+3)
9625960Ssam 	{ "_dkeystats" },
9725708Ssam #endif
9842952Sbostic #ifdef hp300
9942952Sbostic #define	X_HPDINIT	(X_END+1)
10042952Sbostic 	{ "_hp_dinit" },
10142952Sbostic #endif
10210826Ssam 	{ "" },
1031155Sbill };
1041155Sbill 
10545834Sbostic char	*vmunix = _PATH_UNIX;
10645834Sbostic char	*kmem = NULL;
10718761Ssam char	**dr_name;
10818761Ssam int	*dr_select;
10918761Ssam int	dk_ndrive;
11018761Ssam int	ndrives = 0;
11118761Ssam #ifdef vax
11218761Ssam char	*defdrives[] = { "hp0", "hp1", "hp2",  0 };
11318761Ssam #else
11442952Sbostic #ifdef hp300
11542952Sbostic char	*defdrives[] = { "rd0", "rd1", "rd2",  0 };
11642952Sbostic #else
11718761Ssam char	*defdrives[] = { 0 };
11818761Ssam #endif
11942952Sbostic #endif
1201155Sbill double	stat1();
1211155Sbill int	firstfree, maxfree;
1223162Stoy int	hz;
12315266Ssam int	phz;
12415266Ssam int	HZ;
12518761Ssam 
12618761Ssam struct {
1271155Sbill 	int	busy;
1281448Sbill 	long	time[CPUSTATES];
12918761Ssam 	long	*xfer;
1301155Sbill 	struct	vmmeter Rate;
1311155Sbill 	struct	vmtotal	Total;
1321155Sbill 	struct	vmmeter Sum;
1331155Sbill 	struct	forkstat Forkstat;
1341155Sbill 	unsigned rectime;
1351155Sbill 	unsigned pgintime;
13645834Sbostic } s, s1;
1371155Sbill #define	rate		s.Rate
1381155Sbill #define	total		s.Total
1391155Sbill #define	sum		s.Sum
1401155Sbill #define	forkstat	s.Forkstat
1411155Sbill 
14210826Ssam struct	vmmeter osum;
1431155Sbill int	deficit;
1441155Sbill double	etime;
14517262Smckusick time_t	now, boottime;
14618768Ssam int	lines = 1;
14745834Sbostic void	printhdr();
14845834Sbostic long	lseek();
1491155Sbill 
15029664Ssam #define	INTS(x)	((x) - (hz + phz))
15129664Ssam 
15245834Sbostic #define	FORKSTAT	0x01
15345834Sbostic #define	INTRSTAT	0x02
15445834Sbostic #define	MEMSTAT		0x04
15545834Sbostic #define	SUMSTAT		0x08
15645834Sbostic #define	TIMESTAT	0x10
15745834Sbostic #define	VMSTAT		0x20
15845834Sbostic #define	ZEROOUT		0x40
15945834Sbostic 
1601155Sbill main(argc, argv)
16145834Sbostic 	register int argc;
16245834Sbostic 	register char **argv;
1631155Sbill {
16445834Sbostic 	register int c, i, todo = 0;
16545834Sbostic 	extern int optind;
16645834Sbostic 	extern char *optarg;
1671155Sbill 
16845834Sbostic 	while ((c = getopt(argc, argv, "fik:mstu:z")) != EOF) {
16945834Sbostic 		switch (c) {
17045834Sbostic 		case 'f':
17145834Sbostic 			todo |= FORKSTAT;
17245834Sbostic 			break;
17345834Sbostic 		case 'i':
17445834Sbostic 			todo |= INTRSTAT;
17545834Sbostic 			break;
17645834Sbostic 		case 'k':
17745834Sbostic 			kmem = optarg;
17845834Sbostic 			break;
17945834Sbostic 		case 'm':
18045834Sbostic 			todo |= MEMSTAT;
18145834Sbostic 			break;
18245834Sbostic 		case 's':
18345834Sbostic 			todo |= SUMSTAT;
18445834Sbostic 			break;
18545834Sbostic 		case 't':
18645834Sbostic 			todo |= TIMESTAT;
18745834Sbostic 			break;
18845834Sbostic 		case 'u':
18945834Sbostic 			vmunix = optarg;
19045834Sbostic 			break;
19145834Sbostic 		case 'z':
19245834Sbostic 			todo |= ZEROOUT;
19345834Sbostic 			break;
19445834Sbostic 		case '?':
19545834Sbostic 			usage();
19645834Sbostic 			/* NOTREACHED */
19745834Sbostic 		default:
19845834Sbostic 			(void) fprintf(stderr,
19945834Sbostic 			    "vmstat: internal error in options\n");
20045834Sbostic 			exit(1);
20145834Sbostic 			/* NOTREACHED */
20245834Sbostic 		}
20345834Sbostic 	}
20445834Sbostic 
20545834Sbostic 	/*
20645834Sbostic 	 * Zeroing the statistics is fundamentally different
20745834Sbostic 	 * (and really belongs in a separate program).
20845834Sbostic 	 */
20945834Sbostic 	if (todo & ZEROOUT) {
21045834Sbostic 		if (todo & ~ZEROOUT || kmem)
21145834Sbostic 			usage();
21245834Sbostic 		nl[0].n_name = nl[X_SUM].n_name;
21345834Sbostic 		nl[1].n_name = 0;
21445834Sbostic 		if (nlist(vmunix, nl) || nl[0].n_type == 0) {
21545834Sbostic 			(void) fprintf(stderr,
21645834Sbostic 			    "vmstat: cannot get symbol %s from %s\n",
21745834Sbostic 			    nl[0].n_name, vmunix);
21845834Sbostic 			exit(1);
21945834Sbostic 		}
22045834Sbostic 		if ((i = open(kmem = _PATH_KMEM, 2)) < 0) {
22145834Sbostic 			(void) fprintf(stderr, "vmstat: cannot write %s: %s\n",
22245834Sbostic 			    kmem, strerror(errno));
22345834Sbostic 			exit(1);
22445834Sbostic 		}
22545834Sbostic 		(void) lseek(i, (long)nl[0].n_value, L_SET);
22645834Sbostic 		if (write(i, (char *)&s.Sum, sizeof s.Sum) != sizeof s.Sum) {
22745834Sbostic 			(void) fprintf(stderr, "vmstat: write(%s): %s\n",
22845834Sbostic 			    kmem, strerror(errno));
22945834Sbostic 			exit(1);
23045834Sbostic 		}
23145834Sbostic 		exit(0);
23245834Sbostic 	}
23345834Sbostic 
23445834Sbostic 	if (todo == 0)
23545834Sbostic 		todo = VMSTAT;
23645834Sbostic 
23745834Sbostic 	if (kvm_openfiles(vmunix, kmem, (char *)NULL) < 0) {
23845834Sbostic 		(void) fprintf(stderr,
23945834Sbostic 		    "vmstat: kvm_openfiles(%s, %s, NULL): %s\n",
24045834Sbostic 		    vmunix, kmem ? kmem : "NULL", kvm_geterr());
2411155Sbill 		exit(1);
2421155Sbill 	}
24345834Sbostic 
24445834Sbostic 	(void) kvm_nlist(nl);
24545834Sbostic 	if (nl[0].n_type == 0) {
24645834Sbostic 		(void) fprintf(stderr, "vmstat: %s: no namelist\n",
24745834Sbostic 		    vmunix);
2481155Sbill 		exit(1);
2491155Sbill 	}
2501155Sbill 
25145834Sbostic 	/*
25245834Sbostic 	 * Fork, memory, sum, and time statistics do not need everything.
25345834Sbostic 	 */
25445834Sbostic 	if (todo & FORKSTAT)
25545834Sbostic 		doforkst();
25645834Sbostic 	if (todo & MEMSTAT)
25745834Sbostic 		domem();
25845834Sbostic 	if (todo & SUMSTAT)
25945834Sbostic 		dosum();
26045834Sbostic 	if (todo & TIMESTAT)
26145834Sbostic 		dotimes();
26245834Sbostic 	if (todo & INTRSTAT)
26345834Sbostic 		dointr();
26445834Sbostic 	if (todo & VMSTAT) {
26545834Sbostic 		/*
26645834Sbostic 		 * Read drive names, decide which drives to report, etc.
26745834Sbostic 		 */
26845834Sbostic 		argc -= optind;
26945834Sbostic 		argv += optind;
27045834Sbostic 		i = getdrivedata(argc, argv);
27145834Sbostic 		argc -= i;
27245834Sbostic 		argv += i;
27345834Sbostic 		dovmstat(argc > 0 ? atoi(argv[0]) : 0,
27445834Sbostic 			 argc > 1 ? atoi(argv[1]) : 0);
27545834Sbostic 	}
27645834Sbostic 	exit(0);
27745834Sbostic }
27810826Ssam 
27945834Sbostic usage()
28045834Sbostic {
2811155Sbill 
28245834Sbostic 	(void) fprintf(stderr,
28345834Sbostic "usage: vmstat [-fimst]\n\tvmstat [drive-list] [interval [count]]\n\tvmstat -z\n");
28445834Sbostic 	exit(1);
28545834Sbostic }
28633610Smckusick 
28745834Sbostic /*
28845834Sbostic  * kread reads something from the kernel, given its nlist index.
28945834Sbostic  */
29045834Sbostic void
29145834Sbostic kread(nlx, addr, size)
29245834Sbostic 	int nlx;
29345834Sbostic 	char *addr;
29445834Sbostic 	size_t size;
29545834Sbostic {
29645834Sbostic 	char *sym;
2971155Sbill 
29845834Sbostic 	if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) {
29945834Sbostic 		sym = nl[nlx].n_name;
30045834Sbostic 		if (*sym == '_')
30145834Sbostic 			sym++;
30245834Sbostic 		(void) fprintf(stderr,
30345834Sbostic 		    "vmstat: symbol `%s' not defined in %s\n", sym, vmunix);
30445834Sbostic 		exit(1);
3051155Sbill 	}
30645834Sbostic 	if (kvm_read(nl[nlx].n_value, addr, size) != size) {
30745834Sbostic 		sym = nl[nlx].n_name;
30845834Sbostic 		if (*sym == '_')
30945834Sbostic 			sym++;
31045834Sbostic 		(void) fprintf(stderr,
31145834Sbostic 		    "vmstat: error reading `%s': %s\n", sym, kvm_geterr());
31245834Sbostic 		exit(1);
31318761Ssam 	}
31445834Sbostic }
31545834Sbostic 
31645834Sbostic getdrivedata(argc, argv)
31745834Sbostic 	int argc;
31845834Sbostic 	char **argv;
31945834Sbostic {
32045834Sbostic 	register int i;
32145834Sbostic 	register char **cp;
32245834Sbostic 	int ret;
32345834Sbostic 	char buf[30];
32445834Sbostic 
32545834Sbostic 	kread(X_FIRSTFREE, (char *)&firstfree, sizeof firstfree);
32645834Sbostic 	kread(X_MAXFREE, (char *)&maxfree, sizeof maxfree);
32745834Sbostic 	kread(X_HZ, (char *)&hz, sizeof hz);
32845834Sbostic 	if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0)
32945834Sbostic 		kread(X_PHZ, (char *)&phz, sizeof phz);
33015266Ssam 	HZ = phz ? phz : hz;
33145834Sbostic 	kread(X_DK_NDRIVE, (char *)&dk_ndrive, sizeof dk_ndrive);
33218761Ssam 	if (dk_ndrive <= 0) {
33345834Sbostic 		(void) fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive);
33418761Ssam 		exit(1);
33518761Ssam 	}
33645834Sbostic 	dr_select = (int *)calloc((size_t)dk_ndrive, sizeof (int));
33745834Sbostic 	dr_name = (char **)malloc((size_t)dk_ndrive * sizeof (char *));
33845834Sbostic 	for (i = 0; i < dk_ndrive; i++)
33945834Sbostic 		dr_name[i] = NULL;
34045834Sbostic 	s.xfer = (long *)calloc((size_t)dk_ndrive, sizeof (long));
34145834Sbostic 	s1.xfer = (long *)calloc((size_t)dk_ndrive, sizeof (long));
3423162Stoy 	read_names();
34345834Sbostic 	for (i = 0; i < dk_ndrive; i++) {
34445834Sbostic 		if (dr_name[i] == NULL) {
34545834Sbostic 			(void) sprintf(buf, "??%d", i);
34645834Sbostic 			dr_name[i] = strdup(buf);
34745834Sbostic 		}
3481155Sbill 	}
34945834Sbostic 
35018761Ssam 	/*
35118761Ssam 	 * Choose drives to be displayed.  Priority
35218761Ssam 	 * goes to (in order) drives supplied as arguments,
35318761Ssam 	 * default drives.  If everything isn't filled
35418761Ssam 	 * in and there are drives not taken care of,
35518761Ssam 	 * display the first few that fit.
35618761Ssam 	 */
35745834Sbostic 	ret = 0;
35818761Ssam 	ndrives = 0;
35918761Ssam 	while (argc > 0 && !isdigit(argv[0][0])) {
36018761Ssam 		for (i = 0; i < dk_ndrive; i++) {
36118761Ssam 			if (strcmp(dr_name[i], argv[0]))
36218761Ssam 				continue;
36318761Ssam 			dr_select[i] = 1;
36418761Ssam 			ndrives++;
36545834Sbostic 			break;
36618761Ssam 		}
36745834Sbostic 		ret++;
36818761Ssam 		argc--, argv++;
36918761Ssam 	}
37018761Ssam 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
37118761Ssam 		if (dr_select[i])
37218761Ssam 			continue;
37318761Ssam 		for (cp = defdrives; *cp; cp++)
37418761Ssam 			if (strcmp(dr_name[i], *cp) == 0) {
37518761Ssam 				dr_select[i] = 1;
37618761Ssam 				ndrives++;
37718761Ssam 				break;
37818761Ssam 			}
37918761Ssam 	}
38018761Ssam 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
38118761Ssam 		if (dr_select[i])
38218761Ssam 			continue;
38318761Ssam 		dr_select[i] = 1;
38418761Ssam 		ndrives++;
38518761Ssam 	}
38645834Sbostic 	return (ret);
38745834Sbostic }
38845834Sbostic 
38945834Sbostic long
39045834Sbostic getuptime()
39145834Sbostic {
39245834Sbostic 	time_t time();
39345834Sbostic 	long uptime;
39445834Sbostic 
39545834Sbostic 	if (boottime == 0)
39645834Sbostic 		kread(X_BOOTTIME, (char *)&boottime, sizeof boottime);
39745834Sbostic 	(void) time(&now);
39845834Sbostic 	uptime = now - boottime;
39945834Sbostic 	if (uptime <= 0 || uptime > 60*60*24*365*10) {
40045834Sbostic 		(void) fprintf(stderr,
40145834Sbostic 		    "vmstat: time makes no sense; namelist must be wrong.\n");
40245834Sbostic 		exit(1);
40345834Sbostic 	}
40445834Sbostic 	return (uptime);
40545834Sbostic }
40645834Sbostic 
40745834Sbostic dovmstat(sleeptime, iter)
40845834Sbostic 	int sleeptime, iter;
40945834Sbostic {
41045834Sbostic 	register int i;
41145834Sbostic 	long interval, t;
41245834Sbostic 
41345834Sbostic 	interval = getuptime();
41445834Sbostic 	(void) signal(SIGCONT, printhdr);
4151155Sbill loop:
41618768Ssam 	if (--lines == 0)
41718768Ssam 		printhdr();
41845834Sbostic 	kread(X_CPTIME, (char *)s.time, sizeof s.time);
41945834Sbostic 	kread(X_DKXFER, (char *)s.xfer, sizeof *s.xfer * dk_ndrive);
42045834Sbostic 	if (interval != 1)
42145834Sbostic 		kread(X_SUM, (char *)&rate, sizeof rate);
42218761Ssam 	else
42345834Sbostic 		kread(X_RATE, (char *)&rate, sizeof rate);
42445834Sbostic 	kread(X_TOTAL, (char *)&total, sizeof total);
42510826Ssam 	osum = sum;
42645834Sbostic 	kread(X_SUM, (char *)&sum, sizeof sum);
42745834Sbostic 	kread(X_DEFICIT, (char *)&deficit, sizeof deficit);
4281448Sbill 	etime = 0;
42945834Sbostic 	for (i = 0; i < dk_ndrive; i++) {
4301448Sbill 		t = s.xfer[i];
4311448Sbill 		s.xfer[i] -= s1.xfer[i];
4321448Sbill 		s1.xfer[i] = t;
4331155Sbill 	}
43445834Sbostic 	for (i = 0; i < CPUSTATES; i++) {
4351448Sbill 		t = s.time[i];
4361448Sbill 		s.time[i] -= s1.time[i];
4371448Sbill 		s1.time[i] = t;
4381448Sbill 		etime += s.time[i];
4391155Sbill 	}
44045834Sbostic 	if (etime == 0.)
4411155Sbill 		etime = 1.;
44245834Sbostic 	(void) printf("%2d%2d%2d",
44345834Sbostic 	    total.t_rq, total.t_dw + total.t_pw, total.t_sw);
44445834Sbostic #define pgtok(a) ((a)*NBPG >> 10)
44545834Sbostic 	(void) printf("%6ld%6ld", pgtok(total.t_avm), pgtok(total.t_free));
44645834Sbostic 	(void) printf("%4lu%3lu",
44745834Sbostic 	    (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec)) / interval,
44845834Sbostic 	    (rate.v_xsfrec+rate.v_xifrec) / interval);
44945834Sbostic 	(void) printf("%4lu", pgtok(rate.v_pgpgin) / interval);
45045834Sbostic 	(void) printf("%4lu%4lu%4d%4lu", pgtok(rate.v_pgpgout) / interval,
45145834Sbostic 	    pgtok(rate.v_dfree) / interval,
45245834Sbostic 	    pgtok(deficit), rate.v_scan / interval);
45318761Ssam 	etime /= (float)HZ;
45418761Ssam 	for (i = 0; i < dk_ndrive; i++)
45518761Ssam 		if (dr_select[i])
45618761Ssam 			stats(i);
45745834Sbostic 	(void) printf("%4lu%4lu%4lu", INTS(rate.v_intr / interval),
45845834Sbostic 	    rate.v_syscall / interval, rate.v_swtch / interval);
45945834Sbostic 	for(i = 0; i < CPUSTATES; i++) {
4601155Sbill 		float f = stat1(i);
4611155Sbill 		if (i == 0) {		/* US+NI */
4621155Sbill 			i++;
4631155Sbill 			f += stat1(i);
4641155Sbill 		}
46545834Sbostic 		(void) printf("%3.0f", f);
4661155Sbill 	}
46745834Sbostic 	(void) printf("\n");
46845834Sbostic 	(void) fflush(stdout);
46945834Sbostic 	interval = 1;
47045834Sbostic 	if (iter && --iter == 0)
47145834Sbostic 		return;
47245834Sbostic 	if (sleeptime) {
47345834Sbostic 		sleep((unsigned)sleeptime);
4741155Sbill 		goto loop;
4751155Sbill 	}
4761155Sbill }
4771155Sbill 
47845834Sbostic void
47917262Smckusick printhdr()
48017262Smckusick {
48118761Ssam 	register int i, j;
48218761Ssam 
48345834Sbostic 	(void) printf(" procs     memory              page           ");
48418761Ssam 	i = (ndrives * 3 - 6) / 2;
48518761Ssam 	if (i < 0)
48618761Ssam 		i = 0;
48718761Ssam 	for (j = 0; j < i; j++)
48845834Sbostic 		(void) putchar(' ');
48945834Sbostic 	(void) printf("faults");
49018761Ssam 	i = ndrives * 3 - 6 - i;
49118761Ssam 	for (j = 0; j < i; j++)
49245834Sbostic 		(void) putchar(' ');
49345834Sbostic 	(void) printf("               cpu\n");
49445834Sbostic 	(void) printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
49518761Ssam 	for (i = 0; i < dk_ndrive; i++)
49618761Ssam 		if (dr_select[i])
49745834Sbostic 			(void) printf("%c%c ", dr_name[i][0],
49845834Sbostic 			    dr_name[i][strlen(dr_name[i]) - 1]);
49945834Sbostic 	(void) printf(" in  sy  cs us sy id\n");
50018768Ssam 	lines = 19;
50117262Smckusick }
50217262Smckusick 
5031155Sbill dotimes()
5041155Sbill {
5051155Sbill 
50645834Sbostic 	kread(X_REC, (char *)&s.rectime, sizeof s.rectime);
50745834Sbostic 	kread(X_PGIN, (char *)&s.pgintime, sizeof s.pgintime);
50845834Sbostic 	kread(X_SUM, (char *)&sum, sizeof sum);
50945834Sbostic 	(void) printf("%u reclaims, %u total time (usec)\n",
51045834Sbostic 	    sum.v_pgrec, s.rectime);
51145834Sbostic 	(void) printf("average: %u usec / reclaim\n", s.rectime / sum.v_pgrec);
51245834Sbostic 	(void) printf("\n");
51345834Sbostic 	(void) printf("%u page ins, %u total time (msec)\n",
51445834Sbostic 	    sum.v_pgin, s.pgintime / 10);
51545834Sbostic 	(void) printf("average: %8.1f msec / page in\n",
51645834Sbostic 	    s.pgintime / (sum.v_pgin * 10.0));
5171155Sbill }
5181155Sbill 
51945834Sbostic pct(top, bot)
52045834Sbostic 	long top, bot;
52145834Sbostic {
52245834Sbostic 
52345834Sbostic 	if (bot == 0)
52445834Sbostic 		return (0);
52545834Sbostic 	return ((top * 100) / bot);
52645834Sbostic }
52745834Sbostic 
52845834Sbostic #define	PCT(top, bot) pct((long)(top), (long)(bot))
52945834Sbostic 
53030069Ssam #if defined(tahoe)
53145834Sbostic #include <machine/cpu.h>
53230069Ssam #endif
53330069Ssam 
5341155Sbill dosum()
5351155Sbill {
53618761Ssam 	struct nchstats nchstats;
53725960Ssam 	struct xstats xstats;
53815807Smckusick 	long nchtotal;
53925960Ssam #if defined(tahoe)
54025960Ssam 	struct keystats keystats;
54125960Ssam #endif
5421155Sbill 
54345834Sbostic 	kread(X_SUM, (char *)&sum, sizeof sum);
54445834Sbostic 	(void) printf("%9u swap ins\n", sum.v_swpin);
54545834Sbostic 	(void) printf("%9u swap outs\n", sum.v_swpout);
54645834Sbostic 	(void) printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
54745834Sbostic 	(void) printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
54845834Sbostic 	(void) printf("%9u total address trans. faults taken\n", sum.v_faults);
54945834Sbostic 	(void) printf("%9u page ins\n", sum.v_pgin);
55045834Sbostic 	(void) printf("%9u page outs\n", sum.v_pgout);
55145834Sbostic 	(void) printf("%9u pages paged in\n", sum.v_pgpgin);
55245834Sbostic 	(void) printf("%9u pages paged out\n", sum.v_pgpgout);
55345834Sbostic 	(void) printf("%9u sequential process pages freed\n", sum.v_seqfree);
55445834Sbostic 	(void) printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec,
55545834Sbostic 	    PCT(sum.v_fastpgrec, sum.v_pgrec));
55645834Sbostic 	(void) printf("%9u reclaims from free list\n", sum.v_pgfrec);
55745834Sbostic 	(void) printf("%9u intransit blocking page faults\n", sum.v_intrans);
55845834Sbostic 	(void) printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
55945834Sbostic 	(void) printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
56045834Sbostic 	(void) printf("%9u executable fill pages created\n",
56145834Sbostic 	    sum.v_nexfod / CLSIZE);
56245834Sbostic 	(void) printf("%9u executable fill page faults\n",
56345834Sbostic 	    sum.v_exfod / CLSIZE);
56445834Sbostic 	(void) printf("%9u swap text pages found in free list\n",
56545834Sbostic 	    sum.v_xsfrec);
56645834Sbostic 	(void) printf("%9u inode text pages found in free list\n",
56745834Sbostic 	    sum.v_xifrec);
56845834Sbostic 	(void) printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE);
56945834Sbostic 	(void) printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE);
57045834Sbostic 	(void) printf("%9u pages examined by the clock daemon\n", sum.v_scan);
57145834Sbostic 	(void) printf("%9u revolutions of the clock hand\n", sum.v_rev);
57245834Sbostic 	(void) printf("%9u pages freed by the clock daemon\n",
57345834Sbostic 	    sum.v_dfree / CLSIZE);
57445834Sbostic 	(void) printf("%9u cpu context switches\n", sum.v_swtch);
57545834Sbostic 	(void) printf("%9u device interrupts\n", sum.v_intr);
57645834Sbostic 	(void) printf("%9u software interrupts\n", sum.v_soft);
57718761Ssam #ifdef vax
57845834Sbostic 	(void) printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma);
57918761Ssam #endif
58045834Sbostic 	(void) printf("%9u traps\n", sum.v_trap);
58145834Sbostic 	(void) printf("%9u system calls\n", sum.v_syscall);
58245834Sbostic 	kread(X_NCHSTATS, (char *)&nchstats, sizeof nchstats);
58338773Smckusick 	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
58438773Smckusick 	    nchstats.ncs_badhits + nchstats.ncs_falsehits +
58538773Smckusick 	    nchstats.ncs_miss + nchstats.ncs_long;
58645834Sbostic 	(void) printf("%9ld total name lookups\n", nchtotal);
58745834Sbostic 	(void) printf(
58845834Sbostic 	    "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
58945834Sbostic 	    "", PCT(nchstats.ncs_goodhits, nchtotal),
59045834Sbostic 	    PCT(nchstats.ncs_neghits, nchtotal),
59145834Sbostic 	    PCT(nchstats.ncs_pass2, nchtotal));
59245834Sbostic 	(void) printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
59345834Sbostic 	    PCT(nchstats.ncs_badhits, nchtotal),
59445834Sbostic 	    PCT(nchstats.ncs_falsehits, nchtotal),
59545834Sbostic 	    PCT(nchstats.ncs_long, nchtotal));
59645834Sbostic 	kread(X_XSTATS, (char *)&xstats, sizeof xstats);
59745834Sbostic 	(void) printf("%9lu total calls to xalloc (cache hits %d%%)\n",
59845834Sbostic 	    xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc));
59945834Sbostic 	(void) printf("%9s sticky %lu flushed %lu unused %lu\n", "",
60025512Ssam 	    xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
60145834Sbostic 	(void) printf("%9lu total calls to xfree", xstats.free);
60245834Sbostic 	(void) printf(" (sticky %lu cached %lu swapped %lu)\n",
60325512Ssam 	    xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
60425960Ssam #if defined(tahoe)
60545834Sbostic 	kread(X_CKEYSTATS, (char *)&keystats, sizeof keystats);
60645834Sbostic 	(void) printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
60725960Ssam 	    keystats.ks_allocs, "code cache keys allocated",
60845834Sbostic 	    PCT(keystats.ks_allocfree, keystats.ks_allocs),
60945834Sbostic 	    PCT(keystats.ks_norefs, keystats.ks_allocs),
61045834Sbostic 	    PCT(keystats.ks_taken, keystats.ks_allocs),
61145834Sbostic 	    PCT(keystats.ks_shared, keystats.ks_allocs));
61245834Sbostic 	kread(X_DKEYSTATS, (char *)&keystats, sizeof keystats);
61345834Sbostic 	(void) printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
61425960Ssam 	    keystats.ks_allocs, "data cache keys allocated",
61545834Sbostic 	    PCT(keystats.ks_allocfree, keystats.ks_allocs),
61645834Sbostic 	    PCT(keystats.ks_norefs, keystats.ks_allocs),
61745834Sbostic 	    PCT(keystats.ks_taken, keystats.ks_allocs),
61845834Sbostic 	    PCT(keystats.ks_shared, keystats.ks_allocs));
61925960Ssam #endif
6201155Sbill }
6211155Sbill 
6221155Sbill doforkst()
6231155Sbill {
6241155Sbill 
62545834Sbostic 	kread(X_FORKSTAT, (char *)&forkstat, sizeof forkstat);
62645834Sbostic 	(void) printf("%d forks, %d pages, average=%.2f\n",
6271155Sbill 		forkstat.cntfork, forkstat.sizfork,
6281155Sbill 		(float) forkstat.sizfork / forkstat.cntfork);
62945834Sbostic 	(void) printf("%d vforks, %d pages, average=%.2f\n",
6301155Sbill 		forkstat.cntvfork, forkstat.sizvfork,
6311155Sbill 		(float)forkstat.sizvfork / forkstat.cntvfork);
6321155Sbill }
6331155Sbill 
6341155Sbill stats(dn)
6351155Sbill {
6361155Sbill 
63718761Ssam 	if (dn >= dk_ndrive) {
63845834Sbostic 		(void) printf("  0");
6391155Sbill 		return;
6401155Sbill 	}
64145834Sbostic 	(void) printf("%3.0f", s.xfer[dn]/etime);
6421155Sbill }
6431155Sbill 
6441155Sbill double
6451155Sbill stat1(row)
6461155Sbill {
6471448Sbill 	double t;
6481448Sbill 	register i;
6491155Sbill 
6501155Sbill 	t = 0;
6511155Sbill 	for(i=0; i<CPUSTATES; i++)
6521448Sbill 		t += s.time[i];
6531448Sbill 	if(t == 0.)
6541448Sbill 		t = 1.;
6551448Sbill 	return(s.time[row]*100./t);
6561155Sbill }
6571155Sbill 
65845834Sbostic dointr()
6591155Sbill {
66045834Sbostic 	register int nintr, inamlen;
66145834Sbostic 	register long *intrcnt, inttotal, uptime = getuptime();
66245834Sbostic 	register char *intrname;
6631155Sbill 
66445834Sbostic 	nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value;
66545834Sbostic 	inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value;
66645834Sbostic 	intrcnt = (long *)malloc((size_t)nintr);
66745834Sbostic 	intrname = malloc((size_t)inamlen);
66817262Smckusick 	if (intrcnt == NULL || intrname == NULL) {
66945834Sbostic 		(void) fprintf(stderr, "vmstat: %s.\n", strerror(errno));
67017262Smckusick 		exit(9);
67117262Smckusick 	}
67245834Sbostic 	kread(X_INTRCNT, (char *)intrcnt, (size_t)nintr);
67345834Sbostic 	kread(X_INTRNAMES, intrname, (size_t)inamlen);
67445834Sbostic 	(void) printf("interrupt      total      rate\n");
67517262Smckusick 	inttotal = 0;
67645834Sbostic 	nintr /= sizeof(long);
67745834Sbostic 	while (--nintr >= 0) {
67817262Smckusick 		if (*intrcnt)
67945834Sbostic 			(void) printf("%-12s %8ld %8ld\n", intrname,
68045834Sbostic 			    *intrcnt, *intrcnt / uptime);
68117262Smckusick 		intrname += strlen(intrname) + 1;
68217262Smckusick 		inttotal += *intrcnt++;
68317262Smckusick 	}
68445834Sbostic 	(void) printf("Total        %8ld %8ld\n", inttotal, inttotal / uptime);
68517262Smckusick }
68617262Smckusick 
68733610Smckusick /*
68845152Smckusick  * These names are defined in <sys/malloc.h>.
68933610Smckusick  */
69045152Smckusick char *kmemnames[] = INITKMEMNAMES;
69133610Smckusick 
69233610Smckusick domem()
69333610Smckusick {
69445834Sbostic 	register struct kmembuckets *kp;
69545834Sbostic 	register struct kmemstats *ks;
69645834Sbostic 	register int i;
69733610Smckusick 	struct kmemstats kmemstats[M_LAST];
69833610Smckusick 	struct kmembuckets buckets[MINBUCKET + 16];
69933610Smckusick 
70045834Sbostic 	kread(X_KMEMBUCKETS, (char *)buckets, sizeof buckets);
70145834Sbostic 	(void) printf("Memory statistics by bucket size\n");
70245834Sbostic 	(void) printf(
70345834Sbostic 	    "    Size   In Use   Free   Requests  HighWater  Couldfree\n");
70433610Smckusick 	for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
70533610Smckusick 		if (kp->kb_calls == 0)
70633610Smckusick 			continue;
70745834Sbostic 		(void) printf("%8d%9ld%7ld%11ld%8ld%11ld\n", 1 << i,
70833610Smckusick 			kp->kb_total - kp->kb_totalfree,
70933610Smckusick 			kp->kb_totalfree, kp->kb_calls,
71033610Smckusick 			kp->kb_highwat, kp->kb_couldfree);
71133610Smckusick 
71233610Smckusick 	}
71345834Sbostic 	kread(X_KMEMSTAT, (char *)kmemstats, sizeof kmemstats);
71445834Sbostic 	(void) printf("Memory statistics by type\n");
71545834Sbostic 	(void) printf("\
71645834Sbostic      Type   In Use  MemUse   HighUse  Limit  Requests TypeLimit KernLimit\n");
71733610Smckusick 	for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
71833610Smckusick 		if (ks->ks_calls == 0)
71933610Smckusick 			continue;
72045834Sbostic 		(void) printf("%10s%7ld%8ldK%9ldK%6ldK%9ld%7u%10u\n",
72133610Smckusick 			kmemnames[i] ? kmemnames[i] : "undefined",
72233610Smckusick 			ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
72333610Smckusick 			(ks->ks_maxused + 1023) / 1024,
72433610Smckusick 			(ks->ks_limit + 1023) / 1024, ks->ks_calls,
72533610Smckusick 			ks->ks_limblocks, ks->ks_mapblocks);
72633610Smckusick 	}
72733610Smckusick }
72833610Smckusick 
7293162Stoy /*
7303162Stoy  * Read the drive names out of kmem.
7313162Stoy  */
73210826Ssam #ifdef vax
73345834Sbostic #include <uba/ubavar.h>
73445834Sbostic #include <mba/mbavar.h>
73518761Ssam 
7363162Stoy read_names()
7373162Stoy {
73845834Sbostic 	register char *p;
73945834Sbostic 	unsigned long mp, up;
7403162Stoy 	struct mba_device mdev;
7413162Stoy 	struct mba_driver mdrv;
74245834Sbostic 	struct uba_device udev;
7433162Stoy 	struct uba_driver udrv;
74445834Sbostic 	char name[10];
74545834Sbostic 	static char buf[BUFSIZ];
7463162Stoy 
74745834Sbostic 	mp = nl[X_MBDINIT].n_value;
74845834Sbostic 	up = nl[X_UBDINIT].n_value;
74945834Sbostic 	if (mp == 0 && up == 0) {
75045834Sbostic 		(void) fprintf(stderr,
75145834Sbostic 		    "vmstat: disk init info not in namelist\n");
7523162Stoy 		exit(1);
7533162Stoy 	}
75445834Sbostic 	p = buf;
75545834Sbostic 	if (mp) for (;; mp += sizeof mdev) {
75645834Sbostic 		(void) kvm_read((u_long)mp, (char *)&mdev, sizeof mdev);
7573162Stoy 		if (mdev.mi_driver == 0)
7583162Stoy 			break;
7593162Stoy 		if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
7603162Stoy 			continue;
76145834Sbostic 		(void) kvm_read((u_long)mdev.mi_driver,
76245834Sbostic 		    (char *)&mdrv, sizeof mdrv);
76345834Sbostic 		(void) kvm_read((u_long)mdrv.md_dname, name, sizeof name);
76445834Sbostic 		dr_name[mdev.mi_dk] = p;
76545834Sbostic 		p += sprintf(p, "%s%d", name, mdev.mi_unit);
7663162Stoy 	}
76745834Sbostic 	if (up) for (;; up += sizeof udev) {
76845834Sbostic 		(void) kvm_read(up, (char *)&udev, sizeof udev);
7693162Stoy 		if (udev.ui_driver == 0)
7703162Stoy 			break;
7713162Stoy 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
7723162Stoy 			continue;
77345834Sbostic 		(void) kvm_read((u_long)udev.ui_driver,
77445834Sbostic 		    (char *)&udrv, sizeof udrv);
77545834Sbostic 		(void) kvm_read((u_long)udrv.ud_dname, name, sizeof name);
77645834Sbostic 		dr_name[udev.ui_dk] = p;
77745834Sbostic 		p += sprintf(p, "%s%d", name, udev.ui_unit);
7783162Stoy 	}
7793162Stoy }
78010826Ssam #endif
78125708Ssam 
78225708Ssam #ifdef tahoe
783*46892Sbostic #include <tahoe/vba/vbavar.h>
78425708Ssam 
78525708Ssam /*
78625708Ssam  * Read the drive names out of kmem.
78725708Ssam  */
78825708Ssam read_names()
78925708Ssam {
79045834Sbostic 	register char *p;
79125708Ssam 	struct vba_device udev, *up;
79225708Ssam 	struct vba_driver udrv;
79345834Sbostic 	char name[10];
79445834Sbostic 	static char buf[BUFSIZ];
79525708Ssam 
79625708Ssam 	up = (struct vba_device *) nl[X_VBDINIT].n_value;
79725708Ssam 	if (up == 0) {
79845834Sbostic 		(void) fprintf(stderr,
79945834Sbostic 		    "vmstat: disk init info not in namelist\n");
80025708Ssam 		exit(1);
80125708Ssam 	}
80245834Sbostic 	p = buf;
80345834Sbostic 	for (;; up += sizeof udev) {
80445834Sbostic 		(void) kvm_read(up, (char *)&udev, sizeof udev);
80525708Ssam 		if (udev.ui_driver == 0)
80625708Ssam 			break;
80725708Ssam 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
80825708Ssam 			continue;
80945834Sbostic 		(void) kvm_read((u_long)udev.ui_driver,
81045834Sbostic 		    (char *)&udrv, sizeof udrv);
81145834Sbostic 		(void) kvm_read((u_long)udrv.ud_dname, name, sizeof name);
81245834Sbostic 		dr_name[udev.ui_dk] = p;
81345834Sbostic 		p += sprintf(p, "%s%d", name, udev.ui_unit);
81425708Ssam 	}
81525708Ssam }
81625708Ssam #endif
81742952Sbostic 
81842952Sbostic #ifdef hp300
819*46892Sbostic #include <hp300/dev/device.h>
82042952Sbostic 
82142952Sbostic read_names()
82242952Sbostic {
82345834Sbostic 	register char *p;
82445834Sbostic 	register u_long hp;
825*46892Sbostic 	static char buf[BUFSIZ];
82642952Sbostic 	struct hp_device hdev;
82742952Sbostic 	struct driver hdrv;
828*46892Sbostic 	char name[10];
82942952Sbostic 
83045834Sbostic 	hp = nl[X_HPDINIT].n_value;
83142952Sbostic 	if (hp == 0) {
83245834Sbostic 		(void) fprintf(stderr,
83345834Sbostic 		    "vmstat: disk init info not in namelist\n");
83442952Sbostic 		exit(1);
83542952Sbostic 	}
83645834Sbostic 	p = buf;
83745834Sbostic 	for (;; hp += sizeof hdev) {
83845834Sbostic 		(void) kvm_read(hp, (char *)&hdev, sizeof hdev);
83942952Sbostic 		if (hdev.hp_driver == 0)
84042952Sbostic 			break;
84145834Sbostic 		if (hdev.hp_dk < 0 || hdev.hp_alive == 0)
84242952Sbostic 			continue;
84345834Sbostic 		(void) kvm_read((u_long)hdev.hp_driver,
84445834Sbostic 		    (char *)&hdrv, sizeof hdrv);
84545834Sbostic 		(void) kvm_read((u_long)hdrv.d_name, name, sizeof name);
84645834Sbostic 		dr_name[hdev.hp_dk] = p;
84745834Sbostic 		p += sprintf(p, "%s%d", name, hdev.hp_unit);
84842952Sbostic 	}
84942952Sbostic }
85042952Sbostic #endif
851