xref: /csrg-svn/usr.bin/vmstat/vmstat.c (revision 38263)
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*38263Smckusick static char sccsid[] = "@(#)vmstat.c	5.15 (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>
34*38263Smckusick #include <sys/time.h>
35*38263Smckusick #include <sys/vnode.h>
36*38263Smckusick #include <ufs/inode.h>
3717262Smckusick #include <sys/namei.h>
3825708Ssam #include <sys/text.h>
3933610Smckusick #include <sys/malloc.h>
4037912Sbostic #include <stdio.h>
4137912Sbostic #include <ctype.h>
4237912Sbostic #include <nlist.h>
4337912Sbostic #include <paths.h>
441155Sbill 
451155Sbill struct nlist nl[] = {
461448Sbill #define	X_CPTIME	0
471448Sbill 	{ "_cp_time" },
481448Sbill #define	X_RATE		1
491155Sbill 	{ "_rate" },
501448Sbill #define X_TOTAL		2
511155Sbill 	{ "_total" },
521448Sbill #define	X_DEFICIT	3
531155Sbill 	{ "_deficit" },
541448Sbill #define	X_FORKSTAT	4
551155Sbill 	{ "_forkstat" },
561448Sbill #define X_SUM		5
571155Sbill 	{ "_sum" },
581448Sbill #define	X_FIRSTFREE	6
591155Sbill 	{ "_firstfree" },
601448Sbill #define	X_MAXFREE	7
611155Sbill 	{ "_maxfree" },
629249Ssam #define	X_BOOTTIME	8
639249Ssam 	{ "_boottime" },
641448Sbill #define	X_DKXFER	9
651448Sbill 	{ "_dk_xfer" },
6610826Ssam #define X_REC		10
671155Sbill 	{ "_rectime" },
6810826Ssam #define X_PGIN		11
691155Sbill 	{ "_pgintime" },
7010826Ssam #define X_HZ		12
713162Stoy 	{ "_hz" },
7218761Ssam #define X_PHZ		13
7315266Ssam 	{ "_phz" },
7415807Smckusick #define X_NCHSTATS	14
7515807Smckusick 	{ "_nchstats" },
7617262Smckusick #define	X_INTRNAMES	15
7717262Smckusick 	{ "_intrnames" },
7817262Smckusick #define	X_EINTRNAMES	16
7917262Smckusick 	{ "_eintrnames" },
8017262Smckusick #define	X_INTRCNT	17
8117262Smckusick 	{ "_intrcnt" },
8217262Smckusick #define	X_EINTRCNT	18
8317262Smckusick 	{ "_eintrcnt" },
8418761Ssam #define	X_DK_NDRIVE	19
8518761Ssam 	{ "_dk_ndrive" },
8625512Ssam #define	X_XSTATS	20
8725512Ssam 	{ "_xstats" },
8833610Smckusick #define	X_KMEMSTAT	21
8933610Smckusick 	{ "_kmemstats" },
9033610Smckusick #define	X_KMEMBUCKETS	22
9133610Smckusick 	{ "_bucket" },
9210826Ssam #ifdef vax
9325708Ssam #define X_MBDINIT	(X_XSTATS+1)
9410826Ssam 	{ "_mbdinit" },
9525708Ssam #define X_UBDINIT	(X_XSTATS+2)
9610826Ssam 	{ "_ubdinit" },
9710826Ssam #endif
9825708Ssam #ifdef tahoe
9925708Ssam #define	X_VBDINIT	(X_XSTATS+1)
10025708Ssam 	{ "_vbdinit" },
10125960Ssam #define	X_CKEYSTATS	(X_XSTATS+2)
10225960Ssam 	{ "_ckeystats" },
10325960Ssam #define	X_DKEYSTATS	(X_XSTATS+3)
10425960Ssam 	{ "_dkeystats" },
10525708Ssam #endif
10610826Ssam 	{ "" },
1071155Sbill };
1081155Sbill 
10918761Ssam char	**dr_name;
11018761Ssam int	*dr_select;
11118761Ssam int	dk_ndrive;
11218761Ssam int	ndrives = 0;
11318761Ssam #ifdef vax
11418761Ssam char	*defdrives[] = { "hp0", "hp1", "hp2",  0 };
11518761Ssam #else
11618761Ssam char	*defdrives[] = { 0 };
11718761Ssam #endif
1181155Sbill double	stat1();
1191155Sbill int	firstfree, maxfree;
1203162Stoy int	hz;
12115266Ssam int	phz;
12215266Ssam int	HZ;
12318761Ssam 
12418761Ssam struct {
1251155Sbill 	int	busy;
1261448Sbill 	long	time[CPUSTATES];
12718761Ssam 	long	*xfer;
1281155Sbill 	struct	vmmeter Rate;
1291155Sbill 	struct	vmtotal	Total;
1301155Sbill 	struct	vmmeter Sum;
1311155Sbill 	struct	forkstat Forkstat;
1321155Sbill 	unsigned rectime;
1331155Sbill 	unsigned pgintime;
1341155Sbill } s, s1, z;
1351155Sbill #define	rate		s.Rate
1361155Sbill #define	total		s.Total
1371155Sbill #define	sum		s.Sum
1381155Sbill #define	forkstat	s.Forkstat
1391155Sbill 
14010826Ssam struct	vmmeter osum;
1411155Sbill int	deficit;
1421155Sbill double	etime;
1431155Sbill int 	mf;
14417262Smckusick time_t	now, boottime;
14517262Smckusick int	printhdr();
14618768Ssam int	lines = 1;
1471155Sbill 
14829664Ssam #define	INTS(x)	((x) - (hz + phz))
14929664Ssam 
1501155Sbill main(argc, argv)
15110826Ssam 	int argc;
15210826Ssam 	char **argv;
1531155Sbill {
1541155Sbill 	extern char *ctime();
15529664Ssam 	register i;
15617262Smckusick 	int iter, nintv, iflag = 0;
1571155Sbill 	long t;
15829664Ssam 	char *arg, **cp, buf[BUFSIZ];
1591155Sbill 
16037912Sbostic 	nlist(_PATH_UNIX, nl);
1611155Sbill 	if(nl[0].n_type == 0) {
16237912Sbostic 		fprintf(stderr, "vmstat: no %s namelist\n", _PATH_UNIX);
1631155Sbill 		exit(1);
1641155Sbill 	}
16537912Sbostic 	mf = open(_PATH_KMEM, 0);
1661155Sbill 	if(mf < 0) {
16737912Sbostic 		fprintf(stderr, "vmstat: cannot open %s\n", _PATH_KMEM);
1681155Sbill 		exit(1);
1691155Sbill 	}
1701155Sbill 	iter = 0;
1711155Sbill 	argc--, argv++;
1721155Sbill 	while (argc>0 && argv[0][0]=='-') {
1731155Sbill 		char *cp = *argv++;
1741155Sbill 		argc--;
1751155Sbill 		while (*++cp) switch (*cp) {
1761155Sbill 
1771155Sbill 		case 't':
1781155Sbill 			dotimes();
1791155Sbill 			exit(0);
18010826Ssam 
1811155Sbill 		case 'z':
1821155Sbill 			close(mf);
18337912Sbostic 			mf = open(_PATH_KMEM, 2);
18418761Ssam 			lseek(mf, (long)nl[X_SUM].n_value, L_SET);
1851155Sbill 			write(mf, &z.Sum, sizeof z.Sum);
1861155Sbill 			exit(0);
1871155Sbill 
1881155Sbill 		case 'f':
1891155Sbill 			doforkst();
1901155Sbill 			exit(0);
1911155Sbill 
19233610Smckusick 		case 'm':
19333610Smckusick 			domem();
19433610Smckusick 			exit(0);
19533610Smckusick 
1961155Sbill 		case 's':
1971155Sbill 			dosum();
1981155Sbill 			exit(0);
1991155Sbill 
20017262Smckusick 		case 'i':
20117262Smckusick 			iflag++;
20217262Smckusick 			break;
20317262Smckusick 
2041155Sbill 		default:
20518761Ssam 			fprintf(stderr,
20633610Smckusick 			    "usage: vmstat [ -fsim ] [ interval ] [ count]\n");
2071155Sbill 			exit(1);
2081155Sbill 		}
2091155Sbill 	}
21018761Ssam 	lseek(mf, (long)nl[X_FIRSTFREE].n_value, L_SET);
2111155Sbill 	read(mf, &firstfree, sizeof firstfree);
21218761Ssam 	lseek(mf, (long)nl[X_MAXFREE].n_value, L_SET);
2131155Sbill 	read(mf, &maxfree, sizeof maxfree);
21418761Ssam 	lseek(mf, (long)nl[X_BOOTTIME].n_value, L_SET);
2159249Ssam 	read(mf, &boottime, sizeof boottime);
21618761Ssam 	lseek(mf, (long)nl[X_HZ].n_value, L_SET);
2173162Stoy 	read(mf, &hz, sizeof hz);
21818761Ssam 	if (nl[X_PHZ].n_value != 0) {
21918761Ssam 		lseek(mf, (long)nl[X_PHZ].n_value, L_SET);
22018761Ssam 		read(mf, &phz, sizeof phz);
22118761Ssam 	}
22215266Ssam 	HZ = phz ? phz : hz;
22330266Sbostic 	if (nl[X_DK_NDRIVE].n_value == 0) {
22429664Ssam 		fprintf(stderr, "dk_ndrive undefined in system\n");
22518761Ssam 		exit(1);
2263162Stoy 	}
22718761Ssam 	lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET);
22818761Ssam 	read(mf, &dk_ndrive, sizeof (dk_ndrive));
22918761Ssam 	if (dk_ndrive <= 0) {
23029664Ssam 		fprintf(stderr, "dk_ndrive %d\n", dk_ndrive);
23118761Ssam 		exit(1);
23218761Ssam 	}
23318761Ssam 	dr_select = (int *)calloc(dk_ndrive, sizeof (int));
23418761Ssam 	dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
23518761Ssam #define	allocate(e, t) \
23618761Ssam     s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
23718761Ssam     s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
23818761Ssam 	allocate(xfer, long);
23918761Ssam 	for (arg = buf, i = 0; i < dk_ndrive; i++) {
24018761Ssam 		dr_name[i] = arg;
24118761Ssam 		sprintf(dr_name[i], "dk%d", i);
24218761Ssam 		arg += strlen(dr_name[i]) + 1;
24318761Ssam 	}
2443162Stoy 	read_names();
2451155Sbill 	time(&now);
2469249Ssam 	nintv = now - boottime;
2471155Sbill 	if (nintv <= 0 || nintv > 60*60*24*365*10) {
24829664Ssam 		fprintf(stderr,
24929664Ssam 		    "Time makes no sense... namelist must be wrong.\n");
2501155Sbill 		exit(1);
2511155Sbill 	}
25217262Smckusick 	if (iflag) {
25317262Smckusick 		dointr(nintv);
25417262Smckusick 		exit(0);
25517262Smckusick 	}
25618761Ssam 	/*
25718761Ssam 	 * Choose drives to be displayed.  Priority
25818761Ssam 	 * goes to (in order) drives supplied as arguments,
25918761Ssam 	 * default drives.  If everything isn't filled
26018761Ssam 	 * in and there are drives not taken care of,
26118761Ssam 	 * display the first few that fit.
26218761Ssam 	 */
26318761Ssam 	ndrives = 0;
26418761Ssam 	while (argc > 0 && !isdigit(argv[0][0])) {
26518761Ssam 		for (i = 0; i < dk_ndrive; i++) {
26618761Ssam 			if (strcmp(dr_name[i], argv[0]))
26718761Ssam 				continue;
26818761Ssam 			dr_select[i] = 1;
26918761Ssam 			ndrives++;
27018761Ssam 		}
27118761Ssam 		argc--, argv++;
27218761Ssam 	}
27318761Ssam 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
27418761Ssam 		if (dr_select[i])
27518761Ssam 			continue;
27618761Ssam 		for (cp = defdrives; *cp; cp++)
27718761Ssam 			if (strcmp(dr_name[i], *cp) == 0) {
27818761Ssam 				dr_select[i] = 1;
27918761Ssam 				ndrives++;
28018761Ssam 				break;
28118761Ssam 			}
28218761Ssam 	}
28318761Ssam 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
28418761Ssam 		if (dr_select[i])
28518761Ssam 			continue;
28618761Ssam 		dr_select[i] = 1;
28718761Ssam 		ndrives++;
28818761Ssam 	}
28918761Ssam 	if (argc > 1)
29018761Ssam 		iter = atoi(argv[1]);
29117262Smckusick 	signal(SIGCONT, printhdr);
2921155Sbill loop:
29318768Ssam 	if (--lines == 0)
29418768Ssam 		printhdr();
29518761Ssam 	lseek(mf, (long)nl[X_CPTIME].n_value, L_SET);
2961448Sbill  	read(mf, s.time, sizeof s.time);
29718761Ssam 	lseek(mf, (long)nl[X_DKXFER].n_value, L_SET);
29818761Ssam 	read(mf, s.xfer, dk_ndrive * sizeof (long));
29918761Ssam 	if (nintv != 1)
30018761Ssam 		lseek(mf, (long)nl[X_SUM].n_value, L_SET);
30118761Ssam 	else
30218761Ssam 		lseek(mf, (long)nl[X_RATE].n_value, L_SET);
30318761Ssam 	read(mf, &rate, sizeof rate);
30418761Ssam 	lseek(mf, (long)nl[X_TOTAL].n_value, L_SET);
3051155Sbill 	read(mf, &total, sizeof total);
30610826Ssam 	osum = sum;
30718761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
30810826Ssam 	read(mf, &sum, sizeof sum);
30918761Ssam 	lseek(mf, (long)nl[X_DEFICIT].n_value, L_SET);
3101155Sbill 	read(mf, &deficit, sizeof deficit);
3111448Sbill 	etime = 0;
31218761Ssam 	for (i=0; i < dk_ndrive; i++) {
3131448Sbill 		t = s.xfer[i];
3141448Sbill 		s.xfer[i] -= s1.xfer[i];
3151448Sbill 		s1.xfer[i] = t;
3161155Sbill 	}
3171155Sbill 	for (i=0; i < CPUSTATES; i++) {
3181448Sbill 		t = s.time[i];
3191448Sbill 		s.time[i] -= s1.time[i];
3201448Sbill 		s1.time[i] = t;
3211448Sbill 		etime += s.time[i];
3221155Sbill 	}
3231155Sbill 	if(etime == 0.)
3241155Sbill 		etime = 1.;
3253162Stoy 	printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw);
32610826Ssam #define pgtok(a) ((a)*NBPG/1024)
32729664Ssam 	printf("%6d%6d", pgtok(total.t_avm), pgtok(total.t_free));
32815266Ssam 	printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
32915266Ssam 	    (rate.v_xsfrec+rate.v_xifrec)/nintv);
33010826Ssam 	printf("%4d", pgtok(rate.v_pgpgin)/nintv);
33110826Ssam 	printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv,
33210826Ssam 	    pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv);
33318761Ssam 	etime /= (float)HZ;
33418761Ssam 	for (i = 0; i < dk_ndrive; i++)
33518761Ssam 		if (dr_select[i])
33618761Ssam 			stats(i);
33715266Ssam 	printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv,
33815266Ssam 	    rate.v_swtch/nintv);
3391155Sbill 	for(i=0; i<CPUSTATES; i++) {
3401155Sbill 		float f = stat1(i);
3411155Sbill 		if (i == 0) {		/* US+NI */
3421155Sbill 			i++;
3431155Sbill 			f += stat1(i);
3441155Sbill 		}
3451155Sbill 		printf("%3.0f", f);
3461155Sbill 	}
3471155Sbill 	printf("\n");
3481155Sbill 	fflush(stdout);
3491155Sbill 	nintv = 1;
35018768Ssam 	if (--iter &&argc > 0) {
3511155Sbill 		sleep(atoi(argv[0]));
3521155Sbill 		goto loop;
3531155Sbill 	}
3541155Sbill }
3551155Sbill 
35617262Smckusick printhdr()
35717262Smckusick {
35818761Ssam 	register int i, j;
35918761Ssam 
36029664Ssam 	printf(" procs     memory              page           ");
36118761Ssam 	i = (ndrives * 3 - 6) / 2;
36218761Ssam 	if (i < 0)
36318761Ssam 		i = 0;
36418761Ssam 	for (j = 0; j < i; j++)
36518761Ssam 		putchar(' ');
36618761Ssam 	printf("faults");
36718761Ssam 	i = ndrives * 3 - 6 - i;
36818761Ssam 	for (j = 0; j < i; j++)
36918761Ssam 		putchar(' ');
37018761Ssam 	printf("               cpu\n");
37129664Ssam 	printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
37218761Ssam 	for (i = 0; i < dk_ndrive; i++)
37318761Ssam 		if (dr_select[i])
37418761Ssam 			printf("%c%c ", dr_name[i][0], dr_name[i][2]);
37518761Ssam 	printf(" in  sy  cs us sy id\n");
37618768Ssam 	lines = 19;
37717262Smckusick }
37817262Smckusick 
3791155Sbill dotimes()
3801155Sbill {
3811155Sbill 
38218761Ssam 	lseek(mf, (long)nl[X_REC].n_value, L_SET);
3831155Sbill 	read(mf, &s.rectime, sizeof s.rectime);
38418761Ssam 	lseek(mf, (long)nl[X_PGIN].n_value, L_SET);
3851155Sbill 	read(mf, &s.pgintime, sizeof s.pgintime);
38618761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
3871155Sbill 	read(mf, &sum, sizeof sum);
3881155Sbill 	printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
3891155Sbill 	printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
3901155Sbill 	printf("\n");
3911155Sbill 	printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
3921155Sbill 	printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
3931155Sbill }
3941155Sbill 
39530069Ssam #if defined(tahoe)
39630069Ssam #include <tahoe/cpu.h>
39730069Ssam #endif
39830069Ssam 
3991155Sbill dosum()
4001155Sbill {
40118761Ssam 	struct nchstats nchstats;
40225960Ssam 	struct xstats xstats;
40315807Smckusick 	long nchtotal;
40425960Ssam #if defined(tahoe)
40525960Ssam 	struct keystats keystats;
40625960Ssam #endif
4071155Sbill 
40818761Ssam 	lseek(mf, (long)nl[X_SUM].n_value, L_SET);
4091155Sbill 	read(mf, &sum, sizeof sum);
4101155Sbill 	printf("%9d swap ins\n", sum.v_swpin);
4111155Sbill 	printf("%9d swap outs\n", sum.v_swpout);
4121155Sbill 	printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
4131155Sbill 	printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
4141155Sbill 	printf("%9d total address trans. faults taken\n", sum.v_faults);
4151155Sbill 	printf("%9d page ins\n", sum.v_pgin);
4161155Sbill 	printf("%9d page outs\n", sum.v_pgout);
4173612Sroot 	printf("%9d pages paged in\n", sum.v_pgpgin);
4183612Sroot 	printf("%9d pages paged out\n", sum.v_pgpgout);
4193612Sroot 	printf("%9d sequential process pages freed\n", sum.v_seqfree);
42012830Ssam 	printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
42129664Ssam 	    pct(sum.v_fastpgrec, sum.v_pgrec));
4221155Sbill 	printf("%9d reclaims from free list\n", sum.v_pgfrec);
4231155Sbill 	printf("%9d intransit blocking page faults\n", sum.v_intrans);
4241155Sbill 	printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
4251155Sbill 	printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
4261155Sbill 	printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
4271155Sbill 	printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
4281155Sbill 	printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
4291155Sbill 	printf("%9d inode text pages found in free list\n", sum.v_xifrec);
4301155Sbill 	printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
4311155Sbill 	printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
4321155Sbill 	printf("%9d pages examined by the clock daemon\n", sum.v_scan);
4331155Sbill 	printf("%9d revolutions of the clock hand\n", sum.v_rev);
4341155Sbill 	printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
4351155Sbill 	printf("%9d cpu context switches\n", sum.v_swtch);
4361155Sbill 	printf("%9d device interrupts\n", sum.v_intr);
43717262Smckusick 	printf("%9d software interrupts\n", sum.v_soft);
43818761Ssam #ifdef vax
43924429Smckusick 	printf("%9d pseudo-dma dz interrupts\n", sum.v_pdma);
44018761Ssam #endif
4411155Sbill 	printf("%9d traps\n", sum.v_trap);
4421155Sbill 	printf("%9d system calls\n", sum.v_syscall);
44315807Smckusick 	lseek(mf, (long)nl[X_NCHSTATS].n_value, 0);
44418761Ssam 	read(mf, &nchstats, sizeof nchstats);
44518761Ssam 	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_badhits +
44618761Ssam 	    nchstats.ncs_falsehits + nchstats.ncs_miss + nchstats.ncs_long;
44715807Smckusick 	printf("%9d total name lookups", nchtotal);
44815807Smckusick 	printf(" (cache hits %d%% system %d%% per-process)\n",
44929664Ssam 	    pct(nchstats.ncs_goodhits, nchtotal),
45029664Ssam 	    pct(nchstats.ncs_pass2, nchtotal));
45116586Ssam 	printf("%9s badhits %d, falsehits %d, toolong %d\n", "",
45218761Ssam 	    nchstats.ncs_badhits, nchstats.ncs_falsehits, nchstats.ncs_long);
45325512Ssam 	lseek(mf, (long)nl[X_XSTATS].n_value, 0);
45425512Ssam 	read(mf, &xstats, sizeof xstats);
45525512Ssam 	printf("%9d total calls to xalloc (cache hits %d%%)\n",
45629664Ssam 	    xstats.alloc, pct(xstats.alloc_cachehit, xstats.alloc));
45725512Ssam 	printf("%9s sticky %d flushed %d unused %d\n", "",
45825512Ssam 	    xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
45925512Ssam 	printf("%9d total calls to xfree", xstats.free);
46025512Ssam 	printf(" (sticky %d cached %d swapped %d)\n",
46125512Ssam 	    xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
46225960Ssam #if defined(tahoe)
46325960Ssam 	lseek(mf, (long)nl[X_CKEYSTATS].n_value, 0);
46425960Ssam 	read(mf, &keystats, sizeof keystats);
46525960Ssam 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
46625960Ssam 	    keystats.ks_allocs, "code cache keys allocated",
46733610Smckusick 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
46829664Ssam 	    pct(keystats.ks_norefs, keystats.ks_allocs),
46929664Ssam 	    pct(keystats.ks_taken, keystats.ks_allocs),
47029664Ssam 	    pct(keystats.ks_shared, keystats.ks_allocs));
47125960Ssam 	lseek(mf, (long)nl[X_DKEYSTATS].n_value, 0);
47225960Ssam 	read(mf, &keystats, sizeof keystats);
47325960Ssam 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
47425960Ssam 	    keystats.ks_allocs, "data cache keys allocated",
47533610Smckusick 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
47629664Ssam 	    pct(keystats.ks_norefs, keystats.ks_allocs),
47729664Ssam 	    pct(keystats.ks_taken, keystats.ks_allocs),
47829664Ssam 	    pct(keystats.ks_shared, keystats.ks_allocs));
47925960Ssam #endif
4801155Sbill }
4811155Sbill 
4821155Sbill doforkst()
4831155Sbill {
4841155Sbill 
48518761Ssam 	lseek(mf, (long)nl[X_FORKSTAT].n_value, L_SET);
4861155Sbill 	read(mf, &forkstat, sizeof forkstat);
4871155Sbill 	printf("%d forks, %d pages, average=%.2f\n",
4881155Sbill 		forkstat.cntfork, forkstat.sizfork,
4891155Sbill 		(float) forkstat.sizfork / forkstat.cntfork);
4901155Sbill 	printf("%d vforks, %d pages, average=%.2f\n",
4911155Sbill 		forkstat.cntvfork, forkstat.sizvfork,
4921155Sbill 		(float)forkstat.sizvfork / forkstat.cntvfork);
4931155Sbill }
4941155Sbill 
4951155Sbill stats(dn)
4961155Sbill {
4971155Sbill 
49818761Ssam 	if (dn >= dk_ndrive) {
4991155Sbill 		printf("  0");
5001155Sbill 		return;
5011155Sbill 	}
5021448Sbill 	printf("%3.0f", s.xfer[dn]/etime);
5031155Sbill }
5041155Sbill 
5051155Sbill double
5061155Sbill stat1(row)
5071155Sbill {
5081448Sbill 	double t;
5091448Sbill 	register i;
5101155Sbill 
5111155Sbill 	t = 0;
5121155Sbill 	for(i=0; i<CPUSTATES; i++)
5131448Sbill 		t += s.time[i];
5141448Sbill 	if(t == 0.)
5151448Sbill 		t = 1.;
5161448Sbill 	return(s.time[row]*100./t);
5171155Sbill }
5181155Sbill 
5191155Sbill pct(top, bot)
5201155Sbill {
5211155Sbill 
5221155Sbill 	if (bot == 0)
5231155Sbill 		return (0);
5241155Sbill 	return ((top * 100) / bot);
5251155Sbill }
5263162Stoy 
52717262Smckusick dointr(nintv)
52817262Smckusick {
52917262Smckusick 	int nintr, inttotal;
53017262Smckusick 	long *intrcnt;
53117262Smckusick 	char *intrname, *malloc();
53217262Smckusick 
53317262Smckusick 	nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long);
53417262Smckusick 	intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value -
53517262Smckusick 		nl[X_INTRCNT].n_value);
53617262Smckusick 	intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
53717262Smckusick 	if (intrcnt == NULL || intrname == NULL) {
53817262Smckusick 		fprintf(stderr, "vmstat: out of memory\n");
53917262Smckusick 		exit(9);
54017262Smckusick 	}
54118761Ssam 	lseek(mf, (long)nl[X_INTRCNT].n_value, L_SET);
54217262Smckusick 	read(mf, intrcnt, nintr * sizeof (long));
54318761Ssam 	lseek(mf, (long)nl[X_INTRNAMES].n_value, L_SET);
54417262Smckusick 	read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
54517262Smckusick 	printf("interrupt      total      rate\n");
54617262Smckusick 	inttotal = 0;
54717262Smckusick 	while (nintr--) {
54817262Smckusick 		if (*intrcnt)
54917262Smckusick 			printf("%-12s %8ld %8ld\n", intrname,
55017262Smckusick 			    *intrcnt, *intrcnt / nintv);
55117262Smckusick 		intrname += strlen(intrname) + 1;
55217262Smckusick 		inttotal += *intrcnt++;
55317262Smckusick 	}
55417262Smckusick 	printf("Total        %8ld %8ld\n", inttotal, inttotal / nintv);
55517262Smckusick }
55617262Smckusick 
55733610Smckusick /*
55833610Smckusick  * These names must be kept in sync with
55933610Smckusick  * the types defined in <sys/malloc.h>.
56033610Smckusick  */
56133610Smckusick char *kmemnames[] = {
56236510Smarc 	"free",		/* 0 M_FREE */
56336510Smarc 	"mbuf",		/* 1 M_MBUF */
56436510Smarc 	"devbuf",	/* 2 M_DEVBUF */
56536510Smarc 	"socket",	/* 3 M_SOCKET */
56636510Smarc 	"pcb",		/* 4 M_PCB */
56736510Smarc 	"routetbl",	/* 5 M_RTABLE */
56836510Smarc 	"hosttbl",	/* 6 M_HTABLE */
56936510Smarc 	"fragtbl",	/* 7 M_FTABLE */
57036510Smarc 	"zombie",	/* 8 M_ZOMBIE */
57136510Smarc 	"ifaddr",	/* 9 M_IFADDR */
57236510Smarc 	"soopts",	/* 10 M_SOOPTS */
57336510Smarc 	"soname",	/* 11 M_SONAME */
57436510Smarc 	"namei",	/* 12 M_NAMEI */
57536510Smarc 	"gprof",	/* 13 M_GPROF */
57636510Smarc 	"ioctlops",	/* 14 M_IOCTLOPS */
57736510Smarc 	"superblk",	/* 15 M_SUPERBLK */
57836510Smarc 	"cred",		/* 16 M_CRED */
57936510Smarc 	"pgrp",		/* 17 M_PGRP */
58036510Smarc 	"session",	/* 18 M_SESSION */
58136513Smarc 	"iov",		/* 19 M_IOV */
58238262Smckusick 	"mount",	/* 20 M_MOUNT */
58338262Smckusick 	"fhandle",	/* 21 M_FHANDLE */
58438262Smckusick 	"NFS req",	/* 22 M_NFSREQ */
58538262Smckusick 	"NFS mount",	/* 23 M_NFSMNT */
58636510Smarc 	0, 0, 0, 0, 0,
58736510Smarc 	0, 0, 0, 0, 0,
58836510Smarc 	0, 0, 0, 0, 0,
58936510Smarc 	0, 0, 0, 0, 0,
59036510Smarc 	0, 0, 0, 0, 0,
59136510Smarc 	"temp",		/* 49 M_TEMP */
59233610Smckusick };
59333610Smckusick 
59433610Smckusick domem()
59533610Smckusick {
59633610Smckusick 	struct kmemstats kmemstats[M_LAST];
59733610Smckusick 	struct kmembuckets buckets[MINBUCKET + 16];
59833610Smckusick 	register struct kmembuckets *kp;
59933610Smckusick 	register struct kmemstats *ks;
60033610Smckusick 	int i;
60133610Smckusick 
60233610Smckusick 	lseek(mf, (long)nl[X_KMEMBUCKETS].n_value, L_SET);
60333610Smckusick 	read(mf, buckets, sizeof buckets);
60433610Smckusick 	printf("Memory statistics by bucket size\n");
60533610Smckusick 	printf("    Size   In Use   Free   Requests  HighWater  Couldfree\n");
60633610Smckusick 	for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
60733610Smckusick 		if (kp->kb_calls == 0)
60833610Smckusick 			continue;
60933610Smckusick 		printf("%8d%9d%7d%11d%8d%11d\n", 1 << i,
61033610Smckusick 			kp->kb_total - kp->kb_totalfree,
61133610Smckusick 			kp->kb_totalfree, kp->kb_calls,
61233610Smckusick 			kp->kb_highwat, kp->kb_couldfree);
61333610Smckusick 
61433610Smckusick 	}
61533610Smckusick 	lseek(mf, (long)nl[X_KMEMSTAT].n_value, L_SET);
61633610Smckusick 	read(mf, kmemstats, sizeof kmemstats);
61733610Smckusick 	printf("Memory statistics by type\n");
61833610Smckusick 	printf("     Type   In Use  MemUse   HighUse  Limit  Requests %s\n",
61933610Smckusick 		"TypeLimit KernLimit");
62033610Smckusick 	for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
62133610Smckusick 		if (ks->ks_calls == 0)
62233610Smckusick 			continue;
62333610Smckusick 		printf("%10s%7d%8dK%9dK%6dK%9d%7d%10d\n",
62433610Smckusick 			kmemnames[i] ? kmemnames[i] : "undefined",
62533610Smckusick 			ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
62633610Smckusick 			(ks->ks_maxused + 1023) / 1024,
62733610Smckusick 			(ks->ks_limit + 1023) / 1024, ks->ks_calls,
62833610Smckusick 			ks->ks_limblocks, ks->ks_mapblocks);
62933610Smckusick 	}
63033610Smckusick }
63133610Smckusick 
63218761Ssam #define steal(where, var) \
63318761Ssam 	lseek(mf, where, L_SET); read(mf, &var, sizeof var);
6343162Stoy /*
6353162Stoy  * Read the drive names out of kmem.
6363162Stoy  */
63710826Ssam #ifdef vax
63818761Ssam #include <vaxuba/ubavar.h>
63918761Ssam #include <vaxmba/mbavar.h>
64018761Ssam 
6413162Stoy read_names()
6423162Stoy {
6433162Stoy 	struct mba_device mdev;
6443162Stoy 	register struct mba_device *mp;
6453162Stoy 	struct mba_driver mdrv;
6463162Stoy 	short two_char;
6473162Stoy 	char *cp = (char *) &two_char;
6483162Stoy 	struct uba_device udev, *up;
6493162Stoy 	struct uba_driver udrv;
6503162Stoy 
6513162Stoy 	mp = (struct mba_device *) nl[X_MBDINIT].n_value;
6523162Stoy 	up = (struct uba_device *) nl[X_UBDINIT].n_value;
6533492Sroot 	if (up == 0) {
65410826Ssam 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
6553162Stoy 		exit(1);
6563162Stoy 	}
6573492Sroot 	if (mp) for (;;) {
6583162Stoy 		steal(mp++, mdev);
6593162Stoy 		if (mdev.mi_driver == 0)
6603162Stoy 			break;
6613162Stoy 		if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
6623162Stoy 			continue;
6633162Stoy 		steal(mdev.mi_driver, mdrv);
6643162Stoy 		steal(mdrv.md_dname, two_char);
66518761Ssam 		sprintf(dr_name[mdev.mi_dk], "%c%c%d",
66618761Ssam 		    cp[0], cp[1], mdev.mi_unit);
6673162Stoy 	}
6683492Sroot 	for (;;) {
6693162Stoy 		steal(up++, udev);
6703162Stoy 		if (udev.ui_driver == 0)
6713162Stoy 			break;
6723162Stoy 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
6733162Stoy 			continue;
6743162Stoy 		steal(udev.ui_driver, udrv);
6753162Stoy 		steal(udrv.ud_dname, two_char);
67618761Ssam 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
67718761Ssam 		    cp[0], cp[1], udev.ui_unit);
6783162Stoy 	}
6793162Stoy }
68010826Ssam #endif
68125708Ssam 
68225708Ssam #ifdef tahoe
68325708Ssam #include <tahoevba/vbavar.h>
68425708Ssam 
68525708Ssam /*
68625708Ssam  * Read the drive names out of kmem.
68725708Ssam  */
68825708Ssam read_names()
68925708Ssam {
69025708Ssam 	struct vba_device udev, *up;
69125708Ssam 	struct vba_driver udrv;
69225708Ssam 	short two_char;
69325708Ssam 	char *cp = (char *)&two_char;
69425708Ssam 
69525708Ssam 	up = (struct vba_device *) nl[X_VBDINIT].n_value;
69625708Ssam 	if (up == 0) {
69725708Ssam 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
69825708Ssam 		exit(1);
69925708Ssam 	}
70025708Ssam 	for (;;) {
70125708Ssam 		steal(up++, udev);
70225708Ssam 		if (udev.ui_driver == 0)
70325708Ssam 			break;
70425708Ssam 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
70525708Ssam 			continue;
70625708Ssam 		steal(udev.ui_driver, udrv);
70725708Ssam 		steal(udrv.ud_dname, two_char);
70825708Ssam 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
70925708Ssam 		     cp[0], cp[1], udev.ui_unit);
71025708Ssam 	}
71125708Ssam }
71225708Ssam #endif
713