xref: /csrg-svn/usr.bin/vmstat/vmstat.c (revision 38262)
121585Sdist /*
236580Sbostic  * Copyright (c) 1980 The Regents of the University of California.
336580Sbostic  * All rights reserved.
436580Sbostic  *
536580Sbostic  * Redistribution and use in source and binary forms are permitted
636580Sbostic  * provided that the above copyright notice and this paragraph are
736580Sbostic  * duplicated in all such forms and that any documentation,
836580Sbostic  * advertising materials, and other materials related to such
936580Sbostic  * distribution and use acknowledge that the software was developed
1036580Sbostic  * by the University of California, Berkeley.  The name of the
1136580Sbostic  * University may not be used to endorse or promote products derived
1236580Sbostic  * from this software without specific prior written permission.
1336580Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1436580Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1536580Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621585Sdist  */
1721585Sdist 
1810826Ssam #ifndef lint
1921585Sdist char copyright[] =
2036580Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\
2121585Sdist  All rights reserved.\n";
2236580Sbostic #endif /* not lint */
2310826Ssam 
2421585Sdist #ifndef lint
25*38262Smckusick static char sccsid[] = "@(#)vmstat.c	5.14 (Berkeley) 06/08/89";
2636580Sbostic #endif /* not lint */
2721585Sdist 
281155Sbill #include <sys/param.h>
2918761Ssam #include <sys/file.h>
301155Sbill #include <sys/vm.h>
3129664Ssam #include <sys/dkstat.h>
323162Stoy #include <sys/buf.h>
3315807Smckusick #include <sys/dir.h>
3418761Ssam #include <sys/inode.h>
3517262Smckusick #include <sys/namei.h>
3625708Ssam #include <sys/text.h>
3733610Smckusick #include <sys/malloc.h>
3837912Sbostic #include <stdio.h>
3937912Sbostic #include <ctype.h>
4037912Sbostic #include <nlist.h>
4137912Sbostic #include <paths.h>
421155Sbill 
431155Sbill struct nlist nl[] = {
441448Sbill #define	X_CPTIME	0
451448Sbill 	{ "_cp_time" },
461448Sbill #define	X_RATE		1
471155Sbill 	{ "_rate" },
481448Sbill #define X_TOTAL		2
491155Sbill 	{ "_total" },
501448Sbill #define	X_DEFICIT	3
511155Sbill 	{ "_deficit" },
521448Sbill #define	X_FORKSTAT	4
531155Sbill 	{ "_forkstat" },
541448Sbill #define X_SUM		5
551155Sbill 	{ "_sum" },
561448Sbill #define	X_FIRSTFREE	6
571155Sbill 	{ "_firstfree" },
581448Sbill #define	X_MAXFREE	7
591155Sbill 	{ "_maxfree" },
609249Ssam #define	X_BOOTTIME	8
619249Ssam 	{ "_boottime" },
621448Sbill #define	X_DKXFER	9
631448Sbill 	{ "_dk_xfer" },
6410826Ssam #define X_REC		10
651155Sbill 	{ "_rectime" },
6610826Ssam #define X_PGIN		11
671155Sbill 	{ "_pgintime" },
6810826Ssam #define X_HZ		12
693162Stoy 	{ "_hz" },
7018761Ssam #define X_PHZ		13
7115266Ssam 	{ "_phz" },
7215807Smckusick #define X_NCHSTATS	14
7315807Smckusick 	{ "_nchstats" },
7417262Smckusick #define	X_INTRNAMES	15
7517262Smckusick 	{ "_intrnames" },
7617262Smckusick #define	X_EINTRNAMES	16
7717262Smckusick 	{ "_eintrnames" },
7817262Smckusick #define	X_INTRCNT	17
7917262Smckusick 	{ "_intrcnt" },
8017262Smckusick #define	X_EINTRCNT	18
8117262Smckusick 	{ "_eintrcnt" },
8218761Ssam #define	X_DK_NDRIVE	19
8318761Ssam 	{ "_dk_ndrive" },
8425512Ssam #define	X_XSTATS	20
8525512Ssam 	{ "_xstats" },
8633610Smckusick #define	X_KMEMSTAT	21
8733610Smckusick 	{ "_kmemstats" },
8833610Smckusick #define	X_KMEMBUCKETS	22
8933610Smckusick 	{ "_bucket" },
9010826Ssam #ifdef vax
9125708Ssam #define X_MBDINIT	(X_XSTATS+1)
9210826Ssam 	{ "_mbdinit" },
9325708Ssam #define X_UBDINIT	(X_XSTATS+2)
9410826Ssam 	{ "_ubdinit" },
9510826Ssam #endif
9625708Ssam #ifdef tahoe
9725708Ssam #define	X_VBDINIT	(X_XSTATS+1)
9825708Ssam 	{ "_vbdinit" },
9925960Ssam #define	X_CKEYSTATS	(X_XSTATS+2)
10025960Ssam 	{ "_ckeystats" },
10125960Ssam #define	X_DKEYSTATS	(X_XSTATS+3)
10225960Ssam 	{ "_dkeystats" },
10325708Ssam #endif
10410826Ssam 	{ "" },
1051155Sbill };
1061155Sbill 
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
11418761Ssam char	*defdrives[] = { 0 };
11518761Ssam #endif
1161155Sbill double	stat1();
1171155Sbill int	firstfree, maxfree;
1183162Stoy int	hz;
11915266Ssam int	phz;
12015266Ssam int	HZ;
12118761Ssam 
12218761Ssam struct {
1231155Sbill 	int	busy;
1241448Sbill 	long	time[CPUSTATES];
12518761Ssam 	long	*xfer;
1261155Sbill 	struct	vmmeter Rate;
1271155Sbill 	struct	vmtotal	Total;
1281155Sbill 	struct	vmmeter Sum;
1291155Sbill 	struct	forkstat Forkstat;
1301155Sbill 	unsigned rectime;
1311155Sbill 	unsigned pgintime;
1321155Sbill } s, s1, z;
1331155Sbill #define	rate		s.Rate
1341155Sbill #define	total		s.Total
1351155Sbill #define	sum		s.Sum
1361155Sbill #define	forkstat	s.Forkstat
1371155Sbill 
13810826Ssam struct	vmmeter osum;
1391155Sbill int	deficit;
1401155Sbill double	etime;
1411155Sbill int 	mf;
14217262Smckusick time_t	now, boottime;
14317262Smckusick int	printhdr();
14418768Ssam int	lines = 1;
1451155Sbill 
14629664Ssam #define	INTS(x)	((x) - (hz + phz))
14729664Ssam 
1481155Sbill main(argc, argv)
14910826Ssam 	int argc;
15010826Ssam 	char **argv;
1511155Sbill {
1521155Sbill 	extern char *ctime();
15329664Ssam 	register i;
15417262Smckusick 	int iter, nintv, iflag = 0;
1551155Sbill 	long t;
15629664Ssam 	char *arg, **cp, buf[BUFSIZ];
1571155Sbill 
15837912Sbostic 	nlist(_PATH_UNIX, nl);
1591155Sbill 	if(nl[0].n_type == 0) {
16037912Sbostic 		fprintf(stderr, "vmstat: no %s namelist\n", _PATH_UNIX);
1611155Sbill 		exit(1);
1621155Sbill 	}
16337912Sbostic 	mf = open(_PATH_KMEM, 0);
1641155Sbill 	if(mf < 0) {
16537912Sbostic 		fprintf(stderr, "vmstat: cannot open %s\n", _PATH_KMEM);
1661155Sbill 		exit(1);
1671155Sbill 	}
1681155Sbill 	iter = 0;
1691155Sbill 	argc--, argv++;
1701155Sbill 	while (argc>0 && argv[0][0]=='-') {
1711155Sbill 		char *cp = *argv++;
1721155Sbill 		argc--;
1731155Sbill 		while (*++cp) switch (*cp) {
1741155Sbill 
1751155Sbill 		case 't':
1761155Sbill 			dotimes();
1771155Sbill 			exit(0);
17810826Ssam 
1791155Sbill 		case 'z':
1801155Sbill 			close(mf);
18137912Sbostic 			mf = open(_PATH_KMEM, 2);
18218761Ssam 			lseek(mf, (long)nl[X_SUM].n_value, L_SET);
1831155Sbill 			write(mf, &z.Sum, sizeof z.Sum);
1841155Sbill 			exit(0);
1851155Sbill 
1861155Sbill 		case 'f':
1871155Sbill 			doforkst();
1881155Sbill 			exit(0);
1891155Sbill 
19033610Smckusick 		case 'm':
19133610Smckusick 			domem();
19233610Smckusick 			exit(0);
19333610Smckusick 
1941155Sbill 		case 's':
1951155Sbill 			dosum();
1961155Sbill 			exit(0);
1971155Sbill 
19817262Smckusick 		case 'i':
19917262Smckusick 			iflag++;
20017262Smckusick 			break;
20117262Smckusick 
2021155Sbill 		default:
20318761Ssam 			fprintf(stderr,
20433610Smckusick 			    "usage: vmstat [ -fsim ] [ interval ] [ count]\n");
2051155Sbill 			exit(1);
2061155Sbill 		}
2071155Sbill 	}
20818761Ssam 	lseek(mf, (long)nl[X_FIRSTFREE].n_value, L_SET);
2091155Sbill 	read(mf, &firstfree, sizeof firstfree);
21018761Ssam 	lseek(mf, (long)nl[X_MAXFREE].n_value, L_SET);
2111155Sbill 	read(mf, &maxfree, sizeof maxfree);
21218761Ssam 	lseek(mf, (long)nl[X_BOOTTIME].n_value, L_SET);
2139249Ssam 	read(mf, &boottime, sizeof boottime);
21418761Ssam 	lseek(mf, (long)nl[X_HZ].n_value, L_SET);
2153162Stoy 	read(mf, &hz, sizeof hz);
21618761Ssam 	if (nl[X_PHZ].n_value != 0) {
21718761Ssam 		lseek(mf, (long)nl[X_PHZ].n_value, L_SET);
21818761Ssam 		read(mf, &phz, sizeof phz);
21918761Ssam 	}
22015266Ssam 	HZ = phz ? phz : hz;
22130266Sbostic 	if (nl[X_DK_NDRIVE].n_value == 0) {
22229664Ssam 		fprintf(stderr, "dk_ndrive undefined in system\n");
22318761Ssam 		exit(1);
2243162Stoy 	}
22518761Ssam 	lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET);
22618761Ssam 	read(mf, &dk_ndrive, sizeof (dk_ndrive));
22718761Ssam 	if (dk_ndrive <= 0) {
22829664Ssam 		fprintf(stderr, "dk_ndrive %d\n", dk_ndrive);
22918761Ssam 		exit(1);
23018761Ssam 	}
23118761Ssam 	dr_select = (int *)calloc(dk_ndrive, sizeof (int));
23218761Ssam 	dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
23318761Ssam #define	allocate(e, t) \
23418761Ssam     s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
23518761Ssam     s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
23618761Ssam 	allocate(xfer, long);
23718761Ssam 	for (arg = buf, i = 0; i < dk_ndrive; i++) {
23818761Ssam 		dr_name[i] = arg;
23918761Ssam 		sprintf(dr_name[i], "dk%d", i);
24018761Ssam 		arg += strlen(dr_name[i]) + 1;
24118761Ssam 	}
2423162Stoy 	read_names();
2431155Sbill 	time(&now);
2449249Ssam 	nintv = now - boottime;
2451155Sbill 	if (nintv <= 0 || nintv > 60*60*24*365*10) {
24629664Ssam 		fprintf(stderr,
24729664Ssam 		    "Time makes no sense... namelist must be wrong.\n");
2481155Sbill 		exit(1);
2491155Sbill 	}
25017262Smckusick 	if (iflag) {
25117262Smckusick 		dointr(nintv);
25217262Smckusick 		exit(0);
25317262Smckusick 	}
25418761Ssam 	/*
25518761Ssam 	 * Choose drives to be displayed.  Priority
25618761Ssam 	 * goes to (in order) drives supplied as arguments,
25718761Ssam 	 * default drives.  If everything isn't filled
25818761Ssam 	 * in and there are drives not taken care of,
25918761Ssam 	 * display the first few that fit.
26018761Ssam 	 */
26118761Ssam 	ndrives = 0;
26218761Ssam 	while (argc > 0 && !isdigit(argv[0][0])) {
26318761Ssam 		for (i = 0; i < dk_ndrive; i++) {
26418761Ssam 			if (strcmp(dr_name[i], argv[0]))
26518761Ssam 				continue;
26618761Ssam 			dr_select[i] = 1;
26718761Ssam 			ndrives++;
26818761Ssam 		}
26918761Ssam 		argc--, argv++;
27018761Ssam 	}
27118761Ssam 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
27218761Ssam 		if (dr_select[i])
27318761Ssam 			continue;
27418761Ssam 		for (cp = defdrives; *cp; cp++)
27518761Ssam 			if (strcmp(dr_name[i], *cp) == 0) {
27618761Ssam 				dr_select[i] = 1;
27718761Ssam 				ndrives++;
27818761Ssam 				break;
27918761Ssam 			}
28018761Ssam 	}
28118761Ssam 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
28218761Ssam 		if (dr_select[i])
28318761Ssam 			continue;
28418761Ssam 		dr_select[i] = 1;
28518761Ssam 		ndrives++;
28618761Ssam 	}
28718761Ssam 	if (argc > 1)
28818761Ssam 		iter = atoi(argv[1]);
28917262Smckusick 	signal(SIGCONT, printhdr);
2901155Sbill loop:
29118768Ssam 	if (--lines == 0)
29218768Ssam 		printhdr();
29318761Ssam 	lseek(mf, (long)nl[X_CPTIME].n_value, L_SET);
2941448Sbill  	read(mf, s.time, sizeof s.time);
29518761Ssam 	lseek(mf, (long)nl[X_DKXFER].n_value, L_SET);
29618761Ssam 	read(mf, s.xfer, dk_ndrive * sizeof (long));
29718761Ssam 	if (nintv != 1)
29818761Ssam 		lseek(mf, (long)nl[X_SUM].n_value, L_SET);
29918761Ssam 	else
30018761Ssam 		lseek(mf, (long)nl[X_RATE].n_value, L_SET);
30118761Ssam 	read(mf, &rate, sizeof rate);
30218761Ssam 	lseek(mf, (long)nl[X_TOTAL].n_value, L_SET);
3031155Sbill 	read(mf, &total, sizeof total);
30410826Ssam 	osum = sum;
30518761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
30610826Ssam 	read(mf, &sum, sizeof sum);
30718761Ssam 	lseek(mf, (long)nl[X_DEFICIT].n_value, L_SET);
3081155Sbill 	read(mf, &deficit, sizeof deficit);
3091448Sbill 	etime = 0;
31018761Ssam 	for (i=0; i < dk_ndrive; i++) {
3111448Sbill 		t = s.xfer[i];
3121448Sbill 		s.xfer[i] -= s1.xfer[i];
3131448Sbill 		s1.xfer[i] = t;
3141155Sbill 	}
3151155Sbill 	for (i=0; i < CPUSTATES; i++) {
3161448Sbill 		t = s.time[i];
3171448Sbill 		s.time[i] -= s1.time[i];
3181448Sbill 		s1.time[i] = t;
3191448Sbill 		etime += s.time[i];
3201155Sbill 	}
3211155Sbill 	if(etime == 0.)
3221155Sbill 		etime = 1.;
3233162Stoy 	printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw);
32410826Ssam #define pgtok(a) ((a)*NBPG/1024)
32529664Ssam 	printf("%6d%6d", pgtok(total.t_avm), pgtok(total.t_free));
32615266Ssam 	printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
32715266Ssam 	    (rate.v_xsfrec+rate.v_xifrec)/nintv);
32810826Ssam 	printf("%4d", pgtok(rate.v_pgpgin)/nintv);
32910826Ssam 	printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv,
33010826Ssam 	    pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv);
33118761Ssam 	etime /= (float)HZ;
33218761Ssam 	for (i = 0; i < dk_ndrive; i++)
33318761Ssam 		if (dr_select[i])
33418761Ssam 			stats(i);
33515266Ssam 	printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv,
33615266Ssam 	    rate.v_swtch/nintv);
3371155Sbill 	for(i=0; i<CPUSTATES; i++) {
3381155Sbill 		float f = stat1(i);
3391155Sbill 		if (i == 0) {		/* US+NI */
3401155Sbill 			i++;
3411155Sbill 			f += stat1(i);
3421155Sbill 		}
3431155Sbill 		printf("%3.0f", f);
3441155Sbill 	}
3451155Sbill 	printf("\n");
3461155Sbill 	fflush(stdout);
3471155Sbill 	nintv = 1;
34818768Ssam 	if (--iter &&argc > 0) {
3491155Sbill 		sleep(atoi(argv[0]));
3501155Sbill 		goto loop;
3511155Sbill 	}
3521155Sbill }
3531155Sbill 
35417262Smckusick printhdr()
35517262Smckusick {
35618761Ssam 	register int i, j;
35718761Ssam 
35829664Ssam 	printf(" procs     memory              page           ");
35918761Ssam 	i = (ndrives * 3 - 6) / 2;
36018761Ssam 	if (i < 0)
36118761Ssam 		i = 0;
36218761Ssam 	for (j = 0; j < i; j++)
36318761Ssam 		putchar(' ');
36418761Ssam 	printf("faults");
36518761Ssam 	i = ndrives * 3 - 6 - i;
36618761Ssam 	for (j = 0; j < i; j++)
36718761Ssam 		putchar(' ');
36818761Ssam 	printf("               cpu\n");
36929664Ssam 	printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
37018761Ssam 	for (i = 0; i < dk_ndrive; i++)
37118761Ssam 		if (dr_select[i])
37218761Ssam 			printf("%c%c ", dr_name[i][0], dr_name[i][2]);
37318761Ssam 	printf(" in  sy  cs us sy id\n");
37418768Ssam 	lines = 19;
37517262Smckusick }
37617262Smckusick 
3771155Sbill dotimes()
3781155Sbill {
3791155Sbill 
38018761Ssam 	lseek(mf, (long)nl[X_REC].n_value, L_SET);
3811155Sbill 	read(mf, &s.rectime, sizeof s.rectime);
38218761Ssam 	lseek(mf, (long)nl[X_PGIN].n_value, L_SET);
3831155Sbill 	read(mf, &s.pgintime, sizeof s.pgintime);
38418761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
3851155Sbill 	read(mf, &sum, sizeof sum);
3861155Sbill 	printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
3871155Sbill 	printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
3881155Sbill 	printf("\n");
3891155Sbill 	printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
3901155Sbill 	printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
3911155Sbill }
3921155Sbill 
39330069Ssam #if defined(tahoe)
39430069Ssam #include <tahoe/cpu.h>
39530069Ssam #endif
39630069Ssam 
3971155Sbill dosum()
3981155Sbill {
39918761Ssam 	struct nchstats nchstats;
40025960Ssam 	struct xstats xstats;
40115807Smckusick 	long nchtotal;
40225960Ssam #if defined(tahoe)
40325960Ssam 	struct keystats keystats;
40425960Ssam #endif
4051155Sbill 
40618761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
4071155Sbill 	read(mf, &sum, sizeof sum);
4081155Sbill 	printf("%9d swap ins\n", sum.v_swpin);
4091155Sbill 	printf("%9d swap outs\n", sum.v_swpout);
4101155Sbill 	printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
4111155Sbill 	printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
4121155Sbill 	printf("%9d total address trans. faults taken\n", sum.v_faults);
4131155Sbill 	printf("%9d page ins\n", sum.v_pgin);
4141155Sbill 	printf("%9d page outs\n", sum.v_pgout);
4153612Sroot 	printf("%9d pages paged in\n", sum.v_pgpgin);
4163612Sroot 	printf("%9d pages paged out\n", sum.v_pgpgout);
4173612Sroot 	printf("%9d sequential process pages freed\n", sum.v_seqfree);
41812830Ssam 	printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
41929664Ssam 	    pct(sum.v_fastpgrec, sum.v_pgrec));
4201155Sbill 	printf("%9d reclaims from free list\n", sum.v_pgfrec);
4211155Sbill 	printf("%9d intransit blocking page faults\n", sum.v_intrans);
4221155Sbill 	printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
4231155Sbill 	printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
4241155Sbill 	printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
4251155Sbill 	printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
4261155Sbill 	printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
4271155Sbill 	printf("%9d inode text pages found in free list\n", sum.v_xifrec);
4281155Sbill 	printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
4291155Sbill 	printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
4301155Sbill 	printf("%9d pages examined by the clock daemon\n", sum.v_scan);
4311155Sbill 	printf("%9d revolutions of the clock hand\n", sum.v_rev);
4321155Sbill 	printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
4331155Sbill 	printf("%9d cpu context switches\n", sum.v_swtch);
4341155Sbill 	printf("%9d device interrupts\n", sum.v_intr);
43517262Smckusick 	printf("%9d software interrupts\n", sum.v_soft);
43618761Ssam #ifdef vax
43724429Smckusick 	printf("%9d pseudo-dma dz interrupts\n", sum.v_pdma);
43818761Ssam #endif
4391155Sbill 	printf("%9d traps\n", sum.v_trap);
4401155Sbill 	printf("%9d system calls\n", sum.v_syscall);
44115807Smckusick 	lseek(mf, (long)nl[X_NCHSTATS].n_value, 0);
44218761Ssam 	read(mf, &nchstats, sizeof nchstats);
44318761Ssam 	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_badhits +
44418761Ssam 	    nchstats.ncs_falsehits + nchstats.ncs_miss + nchstats.ncs_long;
44515807Smckusick 	printf("%9d total name lookups", nchtotal);
44615807Smckusick 	printf(" (cache hits %d%% system %d%% per-process)\n",
44729664Ssam 	    pct(nchstats.ncs_goodhits, nchtotal),
44829664Ssam 	    pct(nchstats.ncs_pass2, nchtotal));
44916586Ssam 	printf("%9s badhits %d, falsehits %d, toolong %d\n", "",
45018761Ssam 	    nchstats.ncs_badhits, nchstats.ncs_falsehits, nchstats.ncs_long);
45125512Ssam 	lseek(mf, (long)nl[X_XSTATS].n_value, 0);
45225512Ssam 	read(mf, &xstats, sizeof xstats);
45325512Ssam 	printf("%9d total calls to xalloc (cache hits %d%%)\n",
45429664Ssam 	    xstats.alloc, pct(xstats.alloc_cachehit, xstats.alloc));
45525512Ssam 	printf("%9s sticky %d flushed %d unused %d\n", "",
45625512Ssam 	    xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
45725512Ssam 	printf("%9d total calls to xfree", xstats.free);
45825512Ssam 	printf(" (sticky %d cached %d swapped %d)\n",
45925512Ssam 	    xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
46025960Ssam #if defined(tahoe)
46125960Ssam 	lseek(mf, (long)nl[X_CKEYSTATS].n_value, 0);
46225960Ssam 	read(mf, &keystats, sizeof keystats);
46325960Ssam 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
46425960Ssam 	    keystats.ks_allocs, "code cache keys allocated",
46533610Smckusick 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
46629664Ssam 	    pct(keystats.ks_norefs, keystats.ks_allocs),
46729664Ssam 	    pct(keystats.ks_taken, keystats.ks_allocs),
46829664Ssam 	    pct(keystats.ks_shared, keystats.ks_allocs));
46925960Ssam 	lseek(mf, (long)nl[X_DKEYSTATS].n_value, 0);
47025960Ssam 	read(mf, &keystats, sizeof keystats);
47125960Ssam 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
47225960Ssam 	    keystats.ks_allocs, "data cache keys allocated",
47333610Smckusick 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
47429664Ssam 	    pct(keystats.ks_norefs, keystats.ks_allocs),
47529664Ssam 	    pct(keystats.ks_taken, keystats.ks_allocs),
47629664Ssam 	    pct(keystats.ks_shared, keystats.ks_allocs));
47725960Ssam #endif
4781155Sbill }
4791155Sbill 
4801155Sbill doforkst()
4811155Sbill {
4821155Sbill 
48318761Ssam 	lseek(mf, (long)nl[X_FORKSTAT].n_value, L_SET);
4841155Sbill 	read(mf, &forkstat, sizeof forkstat);
4851155Sbill 	printf("%d forks, %d pages, average=%.2f\n",
4861155Sbill 		forkstat.cntfork, forkstat.sizfork,
4871155Sbill 		(float) forkstat.sizfork / forkstat.cntfork);
4881155Sbill 	printf("%d vforks, %d pages, average=%.2f\n",
4891155Sbill 		forkstat.cntvfork, forkstat.sizvfork,
4901155Sbill 		(float)forkstat.sizvfork / forkstat.cntvfork);
4911155Sbill }
4921155Sbill 
4931155Sbill stats(dn)
4941155Sbill {
4951155Sbill 
49618761Ssam 	if (dn >= dk_ndrive) {
4971155Sbill 		printf("  0");
4981155Sbill 		return;
4991155Sbill 	}
5001448Sbill 	printf("%3.0f", s.xfer[dn]/etime);
5011155Sbill }
5021155Sbill 
5031155Sbill double
5041155Sbill stat1(row)
5051155Sbill {
5061448Sbill 	double t;
5071448Sbill 	register i;
5081155Sbill 
5091155Sbill 	t = 0;
5101155Sbill 	for(i=0; i<CPUSTATES; i++)
5111448Sbill 		t += s.time[i];
5121448Sbill 	if(t == 0.)
5131448Sbill 		t = 1.;
5141448Sbill 	return(s.time[row]*100./t);
5151155Sbill }
5161155Sbill 
5171155Sbill pct(top, bot)
5181155Sbill {
5191155Sbill 
5201155Sbill 	if (bot == 0)
5211155Sbill 		return (0);
5221155Sbill 	return ((top * 100) / bot);
5231155Sbill }
5243162Stoy 
52517262Smckusick dointr(nintv)
52617262Smckusick {
52717262Smckusick 	int nintr, inttotal;
52817262Smckusick 	long *intrcnt;
52917262Smckusick 	char *intrname, *malloc();
53017262Smckusick 
53117262Smckusick 	nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long);
53217262Smckusick 	intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value -
53317262Smckusick 		nl[X_INTRCNT].n_value);
53417262Smckusick 	intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
53517262Smckusick 	if (intrcnt == NULL || intrname == NULL) {
53617262Smckusick 		fprintf(stderr, "vmstat: out of memory\n");
53717262Smckusick 		exit(9);
53817262Smckusick 	}
53918761Ssam 	lseek(mf, (long)nl[X_INTRCNT].n_value, L_SET);
54017262Smckusick 	read(mf, intrcnt, nintr * sizeof (long));
54118761Ssam 	lseek(mf, (long)nl[X_INTRNAMES].n_value, L_SET);
54217262Smckusick 	read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
54317262Smckusick 	printf("interrupt      total      rate\n");
54417262Smckusick 	inttotal = 0;
54517262Smckusick 	while (nintr--) {
54617262Smckusick 		if (*intrcnt)
54717262Smckusick 			printf("%-12s %8ld %8ld\n", intrname,
54817262Smckusick 			    *intrcnt, *intrcnt / nintv);
54917262Smckusick 		intrname += strlen(intrname) + 1;
55017262Smckusick 		inttotal += *intrcnt++;
55117262Smckusick 	}
55217262Smckusick 	printf("Total        %8ld %8ld\n", inttotal, inttotal / nintv);
55317262Smckusick }
55417262Smckusick 
55533610Smckusick /*
55633610Smckusick  * These names must be kept in sync with
55733610Smckusick  * the types defined in <sys/malloc.h>.
55833610Smckusick  */
55933610Smckusick char *kmemnames[] = {
56036510Smarc 	"free",		/* 0 M_FREE */
56136510Smarc 	"mbuf",		/* 1 M_MBUF */
56236510Smarc 	"devbuf",	/* 2 M_DEVBUF */
56336510Smarc 	"socket",	/* 3 M_SOCKET */
56436510Smarc 	"pcb",		/* 4 M_PCB */
56536510Smarc 	"routetbl",	/* 5 M_RTABLE */
56636510Smarc 	"hosttbl",	/* 6 M_HTABLE */
56736510Smarc 	"fragtbl",	/* 7 M_FTABLE */
56836510Smarc 	"zombie",	/* 8 M_ZOMBIE */
56936510Smarc 	"ifaddr",	/* 9 M_IFADDR */
57036510Smarc 	"soopts",	/* 10 M_SOOPTS */
57136510Smarc 	"soname",	/* 11 M_SONAME */
57236510Smarc 	"namei",	/* 12 M_NAMEI */
57336510Smarc 	"gprof",	/* 13 M_GPROF */
57436510Smarc 	"ioctlops",	/* 14 M_IOCTLOPS */
57536510Smarc 	"superblk",	/* 15 M_SUPERBLK */
57636510Smarc 	"cred",		/* 16 M_CRED */
57736510Smarc 	"pgrp",		/* 17 M_PGRP */
57836510Smarc 	"session",	/* 18 M_SESSION */
57936513Smarc 	"iov",		/* 19 M_IOV */
580*38262Smckusick 	"mount",	/* 20 M_MOUNT */
581*38262Smckusick 	"fhandle",	/* 21 M_FHANDLE */
582*38262Smckusick 	"NFS req",	/* 22 M_NFSREQ */
583*38262Smckusick 	"NFS mount",	/* 23 M_NFSMNT */
58436510Smarc 	0, 0, 0, 0, 0,
58536510Smarc 	0, 0, 0, 0, 0,
58636510Smarc 	0, 0, 0, 0, 0,
58736510Smarc 	0, 0, 0, 0, 0,
58836510Smarc 	0, 0, 0, 0, 0,
58936510Smarc 	"temp",		/* 49 M_TEMP */
59033610Smckusick };
59133610Smckusick 
59233610Smckusick domem()
59333610Smckusick {
59433610Smckusick 	struct kmemstats kmemstats[M_LAST];
59533610Smckusick 	struct kmembuckets buckets[MINBUCKET + 16];
59633610Smckusick 	register struct kmembuckets *kp;
59733610Smckusick 	register struct kmemstats *ks;
59833610Smckusick 	int i;
59933610Smckusick 
60033610Smckusick 	lseek(mf, (long)nl[X_KMEMBUCKETS].n_value, L_SET);
60133610Smckusick 	read(mf, buckets, sizeof buckets);
60233610Smckusick 	printf("Memory statistics by bucket size\n");
60333610Smckusick 	printf("    Size   In Use   Free   Requests  HighWater  Couldfree\n");
60433610Smckusick 	for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
60533610Smckusick 		if (kp->kb_calls == 0)
60633610Smckusick 			continue;
60733610Smckusick 		printf("%8d%9d%7d%11d%8d%11d\n", 1 << i,
60833610Smckusick 			kp->kb_total - kp->kb_totalfree,
60933610Smckusick 			kp->kb_totalfree, kp->kb_calls,
61033610Smckusick 			kp->kb_highwat, kp->kb_couldfree);
61133610Smckusick 
61233610Smckusick 	}
61333610Smckusick 	lseek(mf, (long)nl[X_KMEMSTAT].n_value, L_SET);
61433610Smckusick 	read(mf, kmemstats, sizeof kmemstats);
61533610Smckusick 	printf("Memory statistics by type\n");
61633610Smckusick 	printf("     Type   In Use  MemUse   HighUse  Limit  Requests %s\n",
61733610Smckusick 		"TypeLimit KernLimit");
61833610Smckusick 	for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
61933610Smckusick 		if (ks->ks_calls == 0)
62033610Smckusick 			continue;
62133610Smckusick 		printf("%10s%7d%8dK%9dK%6dK%9d%7d%10d\n",
62233610Smckusick 			kmemnames[i] ? kmemnames[i] : "undefined",
62333610Smckusick 			ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
62433610Smckusick 			(ks->ks_maxused + 1023) / 1024,
62533610Smckusick 			(ks->ks_limit + 1023) / 1024, ks->ks_calls,
62633610Smckusick 			ks->ks_limblocks, ks->ks_mapblocks);
62733610Smckusick 	}
62833610Smckusick }
62933610Smckusick 
63018761Ssam #define steal(where, var) \
63118761Ssam 	lseek(mf, where, L_SET); read(mf, &var, sizeof var);
6323162Stoy /*
6333162Stoy  * Read the drive names out of kmem.
6343162Stoy  */
63510826Ssam #ifdef vax
63618761Ssam #include <vaxuba/ubavar.h>
63718761Ssam #include <vaxmba/mbavar.h>
63818761Ssam 
6393162Stoy read_names()
6403162Stoy {
6413162Stoy 	struct mba_device mdev;
6423162Stoy 	register struct mba_device *mp;
6433162Stoy 	struct mba_driver mdrv;
6443162Stoy 	short two_char;
6453162Stoy 	char *cp = (char *) &two_char;
6463162Stoy 	struct uba_device udev, *up;
6473162Stoy 	struct uba_driver udrv;
6483162Stoy 
6493162Stoy 	mp = (struct mba_device *) nl[X_MBDINIT].n_value;
6503162Stoy 	up = (struct uba_device *) nl[X_UBDINIT].n_value;
6513492Sroot 	if (up == 0) {
65210826Ssam 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
6533162Stoy 		exit(1);
6543162Stoy 	}
6553492Sroot 	if (mp) for (;;) {
6563162Stoy 		steal(mp++, mdev);
6573162Stoy 		if (mdev.mi_driver == 0)
6583162Stoy 			break;
6593162Stoy 		if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
6603162Stoy 			continue;
6613162Stoy 		steal(mdev.mi_driver, mdrv);
6623162Stoy 		steal(mdrv.md_dname, two_char);
66318761Ssam 		sprintf(dr_name[mdev.mi_dk], "%c%c%d",
66418761Ssam 		    cp[0], cp[1], mdev.mi_unit);
6653162Stoy 	}
6663492Sroot 	for (;;) {
6673162Stoy 		steal(up++, udev);
6683162Stoy 		if (udev.ui_driver == 0)
6693162Stoy 			break;
6703162Stoy 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
6713162Stoy 			continue;
6723162Stoy 		steal(udev.ui_driver, udrv);
6733162Stoy 		steal(udrv.ud_dname, two_char);
67418761Ssam 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
67518761Ssam 		    cp[0], cp[1], udev.ui_unit);
6763162Stoy 	}
6773162Stoy }
67810826Ssam #endif
67925708Ssam 
68025708Ssam #ifdef tahoe
68125708Ssam #include <tahoevba/vbavar.h>
68225708Ssam 
68325708Ssam /*
68425708Ssam  * Read the drive names out of kmem.
68525708Ssam  */
68625708Ssam read_names()
68725708Ssam {
68825708Ssam 	struct vba_device udev, *up;
68925708Ssam 	struct vba_driver udrv;
69025708Ssam 	short two_char;
69125708Ssam 	char *cp = (char *)&two_char;
69225708Ssam 
69325708Ssam 	up = (struct vba_device *) nl[X_VBDINIT].n_value;
69425708Ssam 	if (up == 0) {
69525708Ssam 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
69625708Ssam 		exit(1);
69725708Ssam 	}
69825708Ssam 	for (;;) {
69925708Ssam 		steal(up++, udev);
70025708Ssam 		if (udev.ui_driver == 0)
70125708Ssam 			break;
70225708Ssam 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
70325708Ssam 			continue;
70425708Ssam 		steal(udev.ui_driver, udrv);
70525708Ssam 		steal(udrv.ud_dname, two_char);
70625708Ssam 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
70725708Ssam 		     cp[0], cp[1], udev.ui_unit);
70825708Ssam 	}
70925708Ssam }
71025708Ssam #endif
711