xref: /csrg-svn/usr.bin/vmstat/vmstat.c (revision 36513)
121585Sdist /*
221585Sdist  * Copyright (c) 1980 Regents of the University of California.
321585Sdist  * All rights reserved.  The Berkeley software License Agreement
421585Sdist  * specifies the terms and conditions for redistribution.
521585Sdist  */
621585Sdist 
710826Ssam #ifndef lint
821585Sdist char copyright[] =
921585Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1021585Sdist  All rights reserved.\n";
1121585Sdist #endif not lint
1210826Ssam 
1321585Sdist #ifndef lint
14*36513Smarc static char sccsid[] = "@(#)vmstat.c	5.11 (Berkeley) 01/05/89";
1521585Sdist #endif not lint
1621585Sdist 
171155Sbill #include <stdio.h>
1818761Ssam #include <ctype.h>
1918761Ssam #include <nlist.h>
2018761Ssam 
211155Sbill #include <sys/param.h>
2218761Ssam #include <sys/file.h>
231155Sbill #include <sys/vm.h>
2429664Ssam #include <sys/dkstat.h>
253162Stoy #include <sys/buf.h>
2615807Smckusick #include <sys/dir.h>
2718761Ssam #include <sys/inode.h>
2817262Smckusick #include <sys/namei.h>
2925708Ssam #include <sys/text.h>
3033610Smckusick #include <sys/malloc.h>
311155Sbill 
321155Sbill struct nlist nl[] = {
331448Sbill #define	X_CPTIME	0
341448Sbill 	{ "_cp_time" },
351448Sbill #define	X_RATE		1
361155Sbill 	{ "_rate" },
371448Sbill #define X_TOTAL		2
381155Sbill 	{ "_total" },
391448Sbill #define	X_DEFICIT	3
401155Sbill 	{ "_deficit" },
411448Sbill #define	X_FORKSTAT	4
421155Sbill 	{ "_forkstat" },
431448Sbill #define X_SUM		5
441155Sbill 	{ "_sum" },
451448Sbill #define	X_FIRSTFREE	6
461155Sbill 	{ "_firstfree" },
471448Sbill #define	X_MAXFREE	7
481155Sbill 	{ "_maxfree" },
499249Ssam #define	X_BOOTTIME	8
509249Ssam 	{ "_boottime" },
511448Sbill #define	X_DKXFER	9
521448Sbill 	{ "_dk_xfer" },
5310826Ssam #define X_REC		10
541155Sbill 	{ "_rectime" },
5510826Ssam #define X_PGIN		11
561155Sbill 	{ "_pgintime" },
5710826Ssam #define X_HZ		12
583162Stoy 	{ "_hz" },
5918761Ssam #define X_PHZ		13
6015266Ssam 	{ "_phz" },
6115807Smckusick #define X_NCHSTATS	14
6215807Smckusick 	{ "_nchstats" },
6317262Smckusick #define	X_INTRNAMES	15
6417262Smckusick 	{ "_intrnames" },
6517262Smckusick #define	X_EINTRNAMES	16
6617262Smckusick 	{ "_eintrnames" },
6717262Smckusick #define	X_INTRCNT	17
6817262Smckusick 	{ "_intrcnt" },
6917262Smckusick #define	X_EINTRCNT	18
7017262Smckusick 	{ "_eintrcnt" },
7118761Ssam #define	X_DK_NDRIVE	19
7218761Ssam 	{ "_dk_ndrive" },
7325512Ssam #define	X_XSTATS	20
7425512Ssam 	{ "_xstats" },
7533610Smckusick #define	X_KMEMSTAT	21
7633610Smckusick 	{ "_kmemstats" },
7733610Smckusick #define	X_KMEMBUCKETS	22
7833610Smckusick 	{ "_bucket" },
7910826Ssam #ifdef vax
8025708Ssam #define X_MBDINIT	(X_XSTATS+1)
8110826Ssam 	{ "_mbdinit" },
8225708Ssam #define X_UBDINIT	(X_XSTATS+2)
8310826Ssam 	{ "_ubdinit" },
8410826Ssam #endif
8525708Ssam #ifdef tahoe
8625708Ssam #define	X_VBDINIT	(X_XSTATS+1)
8725708Ssam 	{ "_vbdinit" },
8825960Ssam #define	X_CKEYSTATS	(X_XSTATS+2)
8925960Ssam 	{ "_ckeystats" },
9025960Ssam #define	X_DKEYSTATS	(X_XSTATS+3)
9125960Ssam 	{ "_dkeystats" },
9225708Ssam #endif
9310826Ssam 	{ "" },
941155Sbill };
951155Sbill 
9618761Ssam char	**dr_name;
9718761Ssam int	*dr_select;
9818761Ssam int	dk_ndrive;
9918761Ssam int	ndrives = 0;
10018761Ssam #ifdef vax
10118761Ssam char	*defdrives[] = { "hp0", "hp1", "hp2",  0 };
10218761Ssam #else
10318761Ssam char	*defdrives[] = { 0 };
10418761Ssam #endif
1051155Sbill double	stat1();
1061155Sbill int	firstfree, maxfree;
1073162Stoy int	hz;
10815266Ssam int	phz;
10915266Ssam int	HZ;
11018761Ssam 
11118761Ssam struct {
1121155Sbill 	int	busy;
1131448Sbill 	long	time[CPUSTATES];
11418761Ssam 	long	*xfer;
1151155Sbill 	struct	vmmeter Rate;
1161155Sbill 	struct	vmtotal	Total;
1171155Sbill 	struct	vmmeter Sum;
1181155Sbill 	struct	forkstat Forkstat;
1191155Sbill 	unsigned rectime;
1201155Sbill 	unsigned pgintime;
1211155Sbill } s, s1, z;
1221155Sbill #define	rate		s.Rate
1231155Sbill #define	total		s.Total
1241155Sbill #define	sum		s.Sum
1251155Sbill #define	forkstat	s.Forkstat
1261155Sbill 
12710826Ssam struct	vmmeter osum;
1281155Sbill int	deficit;
1291155Sbill double	etime;
1301155Sbill int 	mf;
13117262Smckusick time_t	now, boottime;
13217262Smckusick int	printhdr();
13318768Ssam int	lines = 1;
1341155Sbill 
13529664Ssam #define	INTS(x)	((x) - (hz + phz))
13629664Ssam 
1371155Sbill main(argc, argv)
13810826Ssam 	int argc;
13910826Ssam 	char **argv;
1401155Sbill {
1411155Sbill 	extern char *ctime();
14229664Ssam 	register i;
14317262Smckusick 	int iter, nintv, iflag = 0;
1441155Sbill 	long t;
14529664Ssam 	char *arg, **cp, buf[BUFSIZ];
1461155Sbill 
1471155Sbill 	nlist("/vmunix", nl);
1481155Sbill 	if(nl[0].n_type == 0) {
14929664Ssam 		fprintf(stderr, "no /vmunix namelist\n");
1501155Sbill 		exit(1);
1511155Sbill 	}
1521155Sbill 	mf = open("/dev/kmem", 0);
1531155Sbill 	if(mf < 0) {
15429664Ssam 		fprintf(stderr, "cannot open /dev/kmem\n");
1551155Sbill 		exit(1);
1561155Sbill 	}
1571155Sbill 	iter = 0;
1581155Sbill 	argc--, argv++;
1591155Sbill 	while (argc>0 && argv[0][0]=='-') {
1601155Sbill 		char *cp = *argv++;
1611155Sbill 		argc--;
1621155Sbill 		while (*++cp) switch (*cp) {
1631155Sbill 
1641155Sbill 		case 't':
1651155Sbill 			dotimes();
1661155Sbill 			exit(0);
16710826Ssam 
1681155Sbill 		case 'z':
1691155Sbill 			close(mf);
1701155Sbill 			mf = open("/dev/kmem", 2);
17118761Ssam 			lseek(mf, (long)nl[X_SUM].n_value, L_SET);
1721155Sbill 			write(mf, &z.Sum, sizeof z.Sum);
1731155Sbill 			exit(0);
1741155Sbill 
1751155Sbill 		case 'f':
1761155Sbill 			doforkst();
1771155Sbill 			exit(0);
1781155Sbill 
17933610Smckusick 		case 'm':
18033610Smckusick 			domem();
18133610Smckusick 			exit(0);
18233610Smckusick 
1831155Sbill 		case 's':
1841155Sbill 			dosum();
1851155Sbill 			exit(0);
1861155Sbill 
18717262Smckusick 		case 'i':
18817262Smckusick 			iflag++;
18917262Smckusick 			break;
19017262Smckusick 
1911155Sbill 		default:
19218761Ssam 			fprintf(stderr,
19333610Smckusick 			    "usage: vmstat [ -fsim ] [ interval ] [ count]\n");
1941155Sbill 			exit(1);
1951155Sbill 		}
1961155Sbill 	}
19718761Ssam 	lseek(mf, (long)nl[X_FIRSTFREE].n_value, L_SET);
1981155Sbill 	read(mf, &firstfree, sizeof firstfree);
19918761Ssam 	lseek(mf, (long)nl[X_MAXFREE].n_value, L_SET);
2001155Sbill 	read(mf, &maxfree, sizeof maxfree);
20118761Ssam 	lseek(mf, (long)nl[X_BOOTTIME].n_value, L_SET);
2029249Ssam 	read(mf, &boottime, sizeof boottime);
20318761Ssam 	lseek(mf, (long)nl[X_HZ].n_value, L_SET);
2043162Stoy 	read(mf, &hz, sizeof hz);
20518761Ssam 	if (nl[X_PHZ].n_value != 0) {
20618761Ssam 		lseek(mf, (long)nl[X_PHZ].n_value, L_SET);
20718761Ssam 		read(mf, &phz, sizeof phz);
20818761Ssam 	}
20915266Ssam 	HZ = phz ? phz : hz;
21030266Sbostic 	if (nl[X_DK_NDRIVE].n_value == 0) {
21129664Ssam 		fprintf(stderr, "dk_ndrive undefined in system\n");
21218761Ssam 		exit(1);
2133162Stoy 	}
21418761Ssam 	lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET);
21518761Ssam 	read(mf, &dk_ndrive, sizeof (dk_ndrive));
21618761Ssam 	if (dk_ndrive <= 0) {
21729664Ssam 		fprintf(stderr, "dk_ndrive %d\n", dk_ndrive);
21818761Ssam 		exit(1);
21918761Ssam 	}
22018761Ssam 	dr_select = (int *)calloc(dk_ndrive, sizeof (int));
22118761Ssam 	dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
22218761Ssam #define	allocate(e, t) \
22318761Ssam     s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
22418761Ssam     s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
22518761Ssam 	allocate(xfer, long);
22618761Ssam 	for (arg = buf, i = 0; i < dk_ndrive; i++) {
22718761Ssam 		dr_name[i] = arg;
22818761Ssam 		sprintf(dr_name[i], "dk%d", i);
22918761Ssam 		arg += strlen(dr_name[i]) + 1;
23018761Ssam 	}
2313162Stoy 	read_names();
2321155Sbill 	time(&now);
2339249Ssam 	nintv = now - boottime;
2341155Sbill 	if (nintv <= 0 || nintv > 60*60*24*365*10) {
23529664Ssam 		fprintf(stderr,
23629664Ssam 		    "Time makes no sense... namelist must be wrong.\n");
2371155Sbill 		exit(1);
2381155Sbill 	}
23917262Smckusick 	if (iflag) {
24017262Smckusick 		dointr(nintv);
24117262Smckusick 		exit(0);
24217262Smckusick 	}
24318761Ssam 	/*
24418761Ssam 	 * Choose drives to be displayed.  Priority
24518761Ssam 	 * goes to (in order) drives supplied as arguments,
24618761Ssam 	 * default drives.  If everything isn't filled
24718761Ssam 	 * in and there are drives not taken care of,
24818761Ssam 	 * display the first few that fit.
24918761Ssam 	 */
25018761Ssam 	ndrives = 0;
25118761Ssam 	while (argc > 0 && !isdigit(argv[0][0])) {
25218761Ssam 		for (i = 0; i < dk_ndrive; i++) {
25318761Ssam 			if (strcmp(dr_name[i], argv[0]))
25418761Ssam 				continue;
25518761Ssam 			dr_select[i] = 1;
25618761Ssam 			ndrives++;
25718761Ssam 		}
25818761Ssam 		argc--, argv++;
25918761Ssam 	}
26018761Ssam 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
26118761Ssam 		if (dr_select[i])
26218761Ssam 			continue;
26318761Ssam 		for (cp = defdrives; *cp; cp++)
26418761Ssam 			if (strcmp(dr_name[i], *cp) == 0) {
26518761Ssam 				dr_select[i] = 1;
26618761Ssam 				ndrives++;
26718761Ssam 				break;
26818761Ssam 			}
26918761Ssam 	}
27018761Ssam 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
27118761Ssam 		if (dr_select[i])
27218761Ssam 			continue;
27318761Ssam 		dr_select[i] = 1;
27418761Ssam 		ndrives++;
27518761Ssam 	}
27618761Ssam 	if (argc > 1)
27718761Ssam 		iter = atoi(argv[1]);
27817262Smckusick 	signal(SIGCONT, printhdr);
2791155Sbill loop:
28018768Ssam 	if (--lines == 0)
28118768Ssam 		printhdr();
28218761Ssam 	lseek(mf, (long)nl[X_CPTIME].n_value, L_SET);
2831448Sbill  	read(mf, s.time, sizeof s.time);
28418761Ssam 	lseek(mf, (long)nl[X_DKXFER].n_value, L_SET);
28518761Ssam 	read(mf, s.xfer, dk_ndrive * sizeof (long));
28618761Ssam 	if (nintv != 1)
28718761Ssam 		lseek(mf, (long)nl[X_SUM].n_value, L_SET);
28818761Ssam 	else
28918761Ssam 		lseek(mf, (long)nl[X_RATE].n_value, L_SET);
29018761Ssam 	read(mf, &rate, sizeof rate);
29118761Ssam 	lseek(mf, (long)nl[X_TOTAL].n_value, L_SET);
2921155Sbill 	read(mf, &total, sizeof total);
29310826Ssam 	osum = sum;
29418761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
29510826Ssam 	read(mf, &sum, sizeof sum);
29618761Ssam 	lseek(mf, (long)nl[X_DEFICIT].n_value, L_SET);
2971155Sbill 	read(mf, &deficit, sizeof deficit);
2981448Sbill 	etime = 0;
29918761Ssam 	for (i=0; i < dk_ndrive; i++) {
3001448Sbill 		t = s.xfer[i];
3011448Sbill 		s.xfer[i] -= s1.xfer[i];
3021448Sbill 		s1.xfer[i] = t;
3031155Sbill 	}
3041155Sbill 	for (i=0; i < CPUSTATES; i++) {
3051448Sbill 		t = s.time[i];
3061448Sbill 		s.time[i] -= s1.time[i];
3071448Sbill 		s1.time[i] = t;
3081448Sbill 		etime += s.time[i];
3091155Sbill 	}
3101155Sbill 	if(etime == 0.)
3111155Sbill 		etime = 1.;
3123162Stoy 	printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw);
31310826Ssam #define pgtok(a) ((a)*NBPG/1024)
31429664Ssam 	printf("%6d%6d", pgtok(total.t_avm), pgtok(total.t_free));
31515266Ssam 	printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
31615266Ssam 	    (rate.v_xsfrec+rate.v_xifrec)/nintv);
31710826Ssam 	printf("%4d", pgtok(rate.v_pgpgin)/nintv);
31810826Ssam 	printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv,
31910826Ssam 	    pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv);
32018761Ssam 	etime /= (float)HZ;
32118761Ssam 	for (i = 0; i < dk_ndrive; i++)
32218761Ssam 		if (dr_select[i])
32318761Ssam 			stats(i);
32415266Ssam 	printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv,
32515266Ssam 	    rate.v_swtch/nintv);
3261155Sbill 	for(i=0; i<CPUSTATES; i++) {
3271155Sbill 		float f = stat1(i);
3281155Sbill 		if (i == 0) {		/* US+NI */
3291155Sbill 			i++;
3301155Sbill 			f += stat1(i);
3311155Sbill 		}
3321155Sbill 		printf("%3.0f", f);
3331155Sbill 	}
3341155Sbill 	printf("\n");
3351155Sbill 	fflush(stdout);
3361155Sbill 	nintv = 1;
33718768Ssam 	if (--iter &&argc > 0) {
3381155Sbill 		sleep(atoi(argv[0]));
3391155Sbill 		goto loop;
3401155Sbill 	}
3411155Sbill }
3421155Sbill 
34317262Smckusick printhdr()
34417262Smckusick {
34518761Ssam 	register int i, j;
34618761Ssam 
34729664Ssam 	printf(" procs     memory              page           ");
34818761Ssam 	i = (ndrives * 3 - 6) / 2;
34918761Ssam 	if (i < 0)
35018761Ssam 		i = 0;
35118761Ssam 	for (j = 0; j < i; j++)
35218761Ssam 		putchar(' ');
35318761Ssam 	printf("faults");
35418761Ssam 	i = ndrives * 3 - 6 - i;
35518761Ssam 	for (j = 0; j < i; j++)
35618761Ssam 		putchar(' ');
35718761Ssam 	printf("               cpu\n");
35829664Ssam 	printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
35918761Ssam 	for (i = 0; i < dk_ndrive; i++)
36018761Ssam 		if (dr_select[i])
36118761Ssam 			printf("%c%c ", dr_name[i][0], dr_name[i][2]);
36218761Ssam 	printf(" in  sy  cs us sy id\n");
36318768Ssam 	lines = 19;
36417262Smckusick }
36517262Smckusick 
3661155Sbill dotimes()
3671155Sbill {
3681155Sbill 
36918761Ssam 	lseek(mf, (long)nl[X_REC].n_value, L_SET);
3701155Sbill 	read(mf, &s.rectime, sizeof s.rectime);
37118761Ssam 	lseek(mf, (long)nl[X_PGIN].n_value, L_SET);
3721155Sbill 	read(mf, &s.pgintime, sizeof s.pgintime);
37318761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
3741155Sbill 	read(mf, &sum, sizeof sum);
3751155Sbill 	printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
3761155Sbill 	printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
3771155Sbill 	printf("\n");
3781155Sbill 	printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
3791155Sbill 	printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
3801155Sbill }
3811155Sbill 
38230069Ssam #if defined(tahoe)
38330069Ssam #include <tahoe/cpu.h>
38430069Ssam #endif
38530069Ssam 
3861155Sbill dosum()
3871155Sbill {
38818761Ssam 	struct nchstats nchstats;
38925960Ssam 	struct xstats xstats;
39015807Smckusick 	long nchtotal;
39125960Ssam #if defined(tahoe)
39225960Ssam 	struct keystats keystats;
39325960Ssam #endif
3941155Sbill 
39518761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
3961155Sbill 	read(mf, &sum, sizeof sum);
3971155Sbill 	printf("%9d swap ins\n", sum.v_swpin);
3981155Sbill 	printf("%9d swap outs\n", sum.v_swpout);
3991155Sbill 	printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
4001155Sbill 	printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
4011155Sbill 	printf("%9d total address trans. faults taken\n", sum.v_faults);
4021155Sbill 	printf("%9d page ins\n", sum.v_pgin);
4031155Sbill 	printf("%9d page outs\n", sum.v_pgout);
4043612Sroot 	printf("%9d pages paged in\n", sum.v_pgpgin);
4053612Sroot 	printf("%9d pages paged out\n", sum.v_pgpgout);
4063612Sroot 	printf("%9d sequential process pages freed\n", sum.v_seqfree);
40712830Ssam 	printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
40829664Ssam 	    pct(sum.v_fastpgrec, sum.v_pgrec));
4091155Sbill 	printf("%9d reclaims from free list\n", sum.v_pgfrec);
4101155Sbill 	printf("%9d intransit blocking page faults\n", sum.v_intrans);
4111155Sbill 	printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
4121155Sbill 	printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
4131155Sbill 	printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
4141155Sbill 	printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
4151155Sbill 	printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
4161155Sbill 	printf("%9d inode text pages found in free list\n", sum.v_xifrec);
4171155Sbill 	printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
4181155Sbill 	printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
4191155Sbill 	printf("%9d pages examined by the clock daemon\n", sum.v_scan);
4201155Sbill 	printf("%9d revolutions of the clock hand\n", sum.v_rev);
4211155Sbill 	printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
4221155Sbill 	printf("%9d cpu context switches\n", sum.v_swtch);
4231155Sbill 	printf("%9d device interrupts\n", sum.v_intr);
42417262Smckusick 	printf("%9d software interrupts\n", sum.v_soft);
42518761Ssam #ifdef vax
42624429Smckusick 	printf("%9d pseudo-dma dz interrupts\n", sum.v_pdma);
42718761Ssam #endif
4281155Sbill 	printf("%9d traps\n", sum.v_trap);
4291155Sbill 	printf("%9d system calls\n", sum.v_syscall);
43015807Smckusick 	lseek(mf, (long)nl[X_NCHSTATS].n_value, 0);
43118761Ssam 	read(mf, &nchstats, sizeof nchstats);
43218761Ssam 	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_badhits +
43318761Ssam 	    nchstats.ncs_falsehits + nchstats.ncs_miss + nchstats.ncs_long;
43415807Smckusick 	printf("%9d total name lookups", nchtotal);
43515807Smckusick 	printf(" (cache hits %d%% system %d%% per-process)\n",
43629664Ssam 	    pct(nchstats.ncs_goodhits, nchtotal),
43729664Ssam 	    pct(nchstats.ncs_pass2, nchtotal));
43816586Ssam 	printf("%9s badhits %d, falsehits %d, toolong %d\n", "",
43918761Ssam 	    nchstats.ncs_badhits, nchstats.ncs_falsehits, nchstats.ncs_long);
44025512Ssam 	lseek(mf, (long)nl[X_XSTATS].n_value, 0);
44125512Ssam 	read(mf, &xstats, sizeof xstats);
44225512Ssam 	printf("%9d total calls to xalloc (cache hits %d%%)\n",
44329664Ssam 	    xstats.alloc, pct(xstats.alloc_cachehit, xstats.alloc));
44425512Ssam 	printf("%9s sticky %d flushed %d unused %d\n", "",
44525512Ssam 	    xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
44625512Ssam 	printf("%9d total calls to xfree", xstats.free);
44725512Ssam 	printf(" (sticky %d cached %d swapped %d)\n",
44825512Ssam 	    xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
44925960Ssam #if defined(tahoe)
45025960Ssam 	lseek(mf, (long)nl[X_CKEYSTATS].n_value, 0);
45125960Ssam 	read(mf, &keystats, sizeof keystats);
45225960Ssam 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
45325960Ssam 	    keystats.ks_allocs, "code cache keys allocated",
45433610Smckusick 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
45529664Ssam 	    pct(keystats.ks_norefs, keystats.ks_allocs),
45629664Ssam 	    pct(keystats.ks_taken, keystats.ks_allocs),
45729664Ssam 	    pct(keystats.ks_shared, keystats.ks_allocs));
45825960Ssam 	lseek(mf, (long)nl[X_DKEYSTATS].n_value, 0);
45925960Ssam 	read(mf, &keystats, sizeof keystats);
46025960Ssam 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
46125960Ssam 	    keystats.ks_allocs, "data cache keys allocated",
46233610Smckusick 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
46329664Ssam 	    pct(keystats.ks_norefs, keystats.ks_allocs),
46429664Ssam 	    pct(keystats.ks_taken, keystats.ks_allocs),
46529664Ssam 	    pct(keystats.ks_shared, keystats.ks_allocs));
46625960Ssam #endif
4671155Sbill }
4681155Sbill 
4691155Sbill doforkst()
4701155Sbill {
4711155Sbill 
47218761Ssam 	lseek(mf, (long)nl[X_FORKSTAT].n_value, L_SET);
4731155Sbill 	read(mf, &forkstat, sizeof forkstat);
4741155Sbill 	printf("%d forks, %d pages, average=%.2f\n",
4751155Sbill 		forkstat.cntfork, forkstat.sizfork,
4761155Sbill 		(float) forkstat.sizfork / forkstat.cntfork);
4771155Sbill 	printf("%d vforks, %d pages, average=%.2f\n",
4781155Sbill 		forkstat.cntvfork, forkstat.sizvfork,
4791155Sbill 		(float)forkstat.sizvfork / forkstat.cntvfork);
4801155Sbill }
4811155Sbill 
4821155Sbill stats(dn)
4831155Sbill {
4841155Sbill 
48518761Ssam 	if (dn >= dk_ndrive) {
4861155Sbill 		printf("  0");
4871155Sbill 		return;
4881155Sbill 	}
4891448Sbill 	printf("%3.0f", s.xfer[dn]/etime);
4901155Sbill }
4911155Sbill 
4921155Sbill double
4931155Sbill stat1(row)
4941155Sbill {
4951448Sbill 	double t;
4961448Sbill 	register i;
4971155Sbill 
4981155Sbill 	t = 0;
4991155Sbill 	for(i=0; i<CPUSTATES; i++)
5001448Sbill 		t += s.time[i];
5011448Sbill 	if(t == 0.)
5021448Sbill 		t = 1.;
5031448Sbill 	return(s.time[row]*100./t);
5041155Sbill }
5051155Sbill 
5061155Sbill pct(top, bot)
5071155Sbill {
5081155Sbill 
5091155Sbill 	if (bot == 0)
5101155Sbill 		return (0);
5111155Sbill 	return ((top * 100) / bot);
5121155Sbill }
5133162Stoy 
51417262Smckusick dointr(nintv)
51517262Smckusick {
51617262Smckusick 	int nintr, inttotal;
51717262Smckusick 	long *intrcnt;
51817262Smckusick 	char *intrname, *malloc();
51917262Smckusick 
52017262Smckusick 	nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long);
52117262Smckusick 	intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value -
52217262Smckusick 		nl[X_INTRCNT].n_value);
52317262Smckusick 	intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
52417262Smckusick 	if (intrcnt == NULL || intrname == NULL) {
52517262Smckusick 		fprintf(stderr, "vmstat: out of memory\n");
52617262Smckusick 		exit(9);
52717262Smckusick 	}
52818761Ssam 	lseek(mf, (long)nl[X_INTRCNT].n_value, L_SET);
52917262Smckusick 	read(mf, intrcnt, nintr * sizeof (long));
53018761Ssam 	lseek(mf, (long)nl[X_INTRNAMES].n_value, L_SET);
53117262Smckusick 	read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
53217262Smckusick 	printf("interrupt      total      rate\n");
53317262Smckusick 	inttotal = 0;
53417262Smckusick 	while (nintr--) {
53517262Smckusick 		if (*intrcnt)
53617262Smckusick 			printf("%-12s %8ld %8ld\n", intrname,
53717262Smckusick 			    *intrcnt, *intrcnt / nintv);
53817262Smckusick 		intrname += strlen(intrname) + 1;
53917262Smckusick 		inttotal += *intrcnt++;
54017262Smckusick 	}
54117262Smckusick 	printf("Total        %8ld %8ld\n", inttotal, inttotal / nintv);
54217262Smckusick }
54317262Smckusick 
54433610Smckusick /*
54533610Smckusick  * These names must be kept in sync with
54633610Smckusick  * the types defined in <sys/malloc.h>.
54733610Smckusick  */
54833610Smckusick char *kmemnames[] = {
54936510Smarc 	"free",		/* 0 M_FREE */
55036510Smarc 	"mbuf",		/* 1 M_MBUF */
55136510Smarc 	"devbuf",	/* 2 M_DEVBUF */
55236510Smarc 	"socket",	/* 3 M_SOCKET */
55336510Smarc 	"pcb",		/* 4 M_PCB */
55436510Smarc 	"routetbl",	/* 5 M_RTABLE */
55536510Smarc 	"hosttbl",	/* 6 M_HTABLE */
55636510Smarc 	"fragtbl",	/* 7 M_FTABLE */
55736510Smarc 	"zombie",	/* 8 M_ZOMBIE */
55836510Smarc 	"ifaddr",	/* 9 M_IFADDR */
55936510Smarc 	"soopts",	/* 10 M_SOOPTS */
56036510Smarc 	"soname",	/* 11 M_SONAME */
56136510Smarc 	"namei",	/* 12 M_NAMEI */
56236510Smarc 	"gprof",	/* 13 M_GPROF */
56336510Smarc 	"ioctlops",	/* 14 M_IOCTLOPS */
56436510Smarc 	"superblk",	/* 15 M_SUPERBLK */
56536510Smarc 	"cred",		/* 16 M_CRED */
56636510Smarc 	"pgrp",		/* 17 M_PGRP */
56736510Smarc 	"session",	/* 18 M_SESSION */
568*36513Smarc 	"iov",		/* 19 M_IOV */
56936510Smarc 	0, 0, 0, 0, 0,
57036510Smarc 	0, 0, 0, 0, 0,
57136510Smarc 	0, 0, 0, 0, 0,
57236510Smarc 	0, 0, 0, 0, 0,
57336510Smarc 	0, 0, 0, 0, 0,
574*36513Smarc 	0, 0, 0, 0,
57536510Smarc 	"temp",		/* 49 M_TEMP */
57633610Smckusick };
57733610Smckusick 
57833610Smckusick domem()
57933610Smckusick {
58033610Smckusick 	struct kmemstats kmemstats[M_LAST];
58133610Smckusick 	struct kmembuckets buckets[MINBUCKET + 16];
58233610Smckusick 	register struct kmembuckets *kp;
58333610Smckusick 	register struct kmemstats *ks;
58433610Smckusick 	int i;
58533610Smckusick 
58633610Smckusick 	lseek(mf, (long)nl[X_KMEMBUCKETS].n_value, L_SET);
58733610Smckusick 	read(mf, buckets, sizeof buckets);
58833610Smckusick 	printf("Memory statistics by bucket size\n");
58933610Smckusick 	printf("    Size   In Use   Free   Requests  HighWater  Couldfree\n");
59033610Smckusick 	for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
59133610Smckusick 		if (kp->kb_calls == 0)
59233610Smckusick 			continue;
59333610Smckusick 		printf("%8d%9d%7d%11d%8d%11d\n", 1 << i,
59433610Smckusick 			kp->kb_total - kp->kb_totalfree,
59533610Smckusick 			kp->kb_totalfree, kp->kb_calls,
59633610Smckusick 			kp->kb_highwat, kp->kb_couldfree);
59733610Smckusick 
59833610Smckusick 	}
59933610Smckusick 	lseek(mf, (long)nl[X_KMEMSTAT].n_value, L_SET);
60033610Smckusick 	read(mf, kmemstats, sizeof kmemstats);
60133610Smckusick 	printf("Memory statistics by type\n");
60233610Smckusick 	printf("     Type   In Use  MemUse   HighUse  Limit  Requests %s\n",
60333610Smckusick 		"TypeLimit KernLimit");
60433610Smckusick 	for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
60533610Smckusick 		if (ks->ks_calls == 0)
60633610Smckusick 			continue;
60733610Smckusick 		printf("%10s%7d%8dK%9dK%6dK%9d%7d%10d\n",
60833610Smckusick 			kmemnames[i] ? kmemnames[i] : "undefined",
60933610Smckusick 			ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
61033610Smckusick 			(ks->ks_maxused + 1023) / 1024,
61133610Smckusick 			(ks->ks_limit + 1023) / 1024, ks->ks_calls,
61233610Smckusick 			ks->ks_limblocks, ks->ks_mapblocks);
61333610Smckusick 	}
61433610Smckusick }
61533610Smckusick 
61618761Ssam #define steal(where, var) \
61718761Ssam 	lseek(mf, where, L_SET); read(mf, &var, sizeof var);
6183162Stoy /*
6193162Stoy  * Read the drive names out of kmem.
6203162Stoy  */
62110826Ssam #ifdef vax
62218761Ssam #include <vaxuba/ubavar.h>
62318761Ssam #include <vaxmba/mbavar.h>
62418761Ssam 
6253162Stoy read_names()
6263162Stoy {
6273162Stoy 	struct mba_device mdev;
6283162Stoy 	register struct mba_device *mp;
6293162Stoy 	struct mba_driver mdrv;
6303162Stoy 	short two_char;
6313162Stoy 	char *cp = (char *) &two_char;
6323162Stoy 	struct uba_device udev, *up;
6333162Stoy 	struct uba_driver udrv;
6343162Stoy 
6353162Stoy 	mp = (struct mba_device *) nl[X_MBDINIT].n_value;
6363162Stoy 	up = (struct uba_device *) nl[X_UBDINIT].n_value;
6373492Sroot 	if (up == 0) {
63810826Ssam 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
6393162Stoy 		exit(1);
6403162Stoy 	}
6413492Sroot 	if (mp) for (;;) {
6423162Stoy 		steal(mp++, mdev);
6433162Stoy 		if (mdev.mi_driver == 0)
6443162Stoy 			break;
6453162Stoy 		if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
6463162Stoy 			continue;
6473162Stoy 		steal(mdev.mi_driver, mdrv);
6483162Stoy 		steal(mdrv.md_dname, two_char);
64918761Ssam 		sprintf(dr_name[mdev.mi_dk], "%c%c%d",
65018761Ssam 		    cp[0], cp[1], mdev.mi_unit);
6513162Stoy 	}
6523492Sroot 	for (;;) {
6533162Stoy 		steal(up++, udev);
6543162Stoy 		if (udev.ui_driver == 0)
6553162Stoy 			break;
6563162Stoy 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
6573162Stoy 			continue;
6583162Stoy 		steal(udev.ui_driver, udrv);
6593162Stoy 		steal(udrv.ud_dname, two_char);
66018761Ssam 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
66118761Ssam 		    cp[0], cp[1], udev.ui_unit);
6623162Stoy 	}
6633162Stoy }
66410826Ssam #endif
66525708Ssam 
66625708Ssam #ifdef tahoe
66725708Ssam #include <tahoevba/vbavar.h>
66825708Ssam 
66925708Ssam /*
67025708Ssam  * Read the drive names out of kmem.
67125708Ssam  */
67225708Ssam read_names()
67325708Ssam {
67425708Ssam 	struct vba_device udev, *up;
67525708Ssam 	struct vba_driver udrv;
67625708Ssam 	short two_char;
67725708Ssam 	char *cp = (char *)&two_char;
67825708Ssam 
67925708Ssam 	up = (struct vba_device *) nl[X_VBDINIT].n_value;
68025708Ssam 	if (up == 0) {
68125708Ssam 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
68225708Ssam 		exit(1);
68325708Ssam 	}
68425708Ssam 	for (;;) {
68525708Ssam 		steal(up++, udev);
68625708Ssam 		if (udev.ui_driver == 0)
68725708Ssam 			break;
68825708Ssam 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
68925708Ssam 			continue;
69025708Ssam 		steal(udev.ui_driver, udrv);
69125708Ssam 		steal(udrv.ud_dname, two_char);
69225708Ssam 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
69325708Ssam 		     cp[0], cp[1], udev.ui_unit);
69425708Ssam 	}
69525708Ssam }
69625708Ssam #endif
697