xref: /csrg-svn/usr.bin/vmstat/vmstat.c (revision 38773)
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*38773Smckusick static char sccsid[] = "@(#)vmstat.c	5.16 (Berkeley) 08/26/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>
3438263Smckusick #include <sys/time.h>
3538263Smckusick #include <sys/vnode.h>
3638263Smckusick #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);
445*38773Smckusick 	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
446*38773Smckusick 	    nchstats.ncs_badhits + nchstats.ncs_falsehits +
447*38773Smckusick 	    nchstats.ncs_miss + nchstats.ncs_long;
448*38773Smckusick 	printf("%9d total name lookups\n", nchtotal);
449*38773Smckusick 	printf("%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
450*38773Smckusick 	    "", pct(nchstats.ncs_goodhits, nchtotal),
451*38773Smckusick 	    pct(nchstats.ncs_neghits, nchtotal),
45229664Ssam 	    pct(nchstats.ncs_pass2, nchtotal));
453*38773Smckusick 	printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
454*38773Smckusick 	    pct(nchstats.ncs_badhits, nchtotal),
455*38773Smckusick 	    pct(nchstats.ncs_falsehits, nchtotal),
456*38773Smckusick 	    pct(nchstats.ncs_long, nchtotal));
45725512Ssam 	lseek(mf, (long)nl[X_XSTATS].n_value, 0);
45825512Ssam 	read(mf, &xstats, sizeof xstats);
45925512Ssam 	printf("%9d total calls to xalloc (cache hits %d%%)\n",
46029664Ssam 	    xstats.alloc, pct(xstats.alloc_cachehit, xstats.alloc));
46125512Ssam 	printf("%9s sticky %d flushed %d unused %d\n", "",
46225512Ssam 	    xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
46325512Ssam 	printf("%9d total calls to xfree", xstats.free);
46425512Ssam 	printf(" (sticky %d cached %d swapped %d)\n",
46525512Ssam 	    xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
46625960Ssam #if defined(tahoe)
46725960Ssam 	lseek(mf, (long)nl[X_CKEYSTATS].n_value, 0);
46825960Ssam 	read(mf, &keystats, sizeof keystats);
46925960Ssam 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
47025960Ssam 	    keystats.ks_allocs, "code cache keys allocated",
47133610Smckusick 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
47229664Ssam 	    pct(keystats.ks_norefs, keystats.ks_allocs),
47329664Ssam 	    pct(keystats.ks_taken, keystats.ks_allocs),
47429664Ssam 	    pct(keystats.ks_shared, keystats.ks_allocs));
47525960Ssam 	lseek(mf, (long)nl[X_DKEYSTATS].n_value, 0);
47625960Ssam 	read(mf, &keystats, sizeof keystats);
47725960Ssam 	printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
47825960Ssam 	    keystats.ks_allocs, "data cache keys allocated",
47933610Smckusick 	    pct(keystats.ks_allocfree, keystats.ks_allocs),
48029664Ssam 	    pct(keystats.ks_norefs, keystats.ks_allocs),
48129664Ssam 	    pct(keystats.ks_taken, keystats.ks_allocs),
48229664Ssam 	    pct(keystats.ks_shared, keystats.ks_allocs));
48325960Ssam #endif
4841155Sbill }
4851155Sbill 
4861155Sbill doforkst()
4871155Sbill {
4881155Sbill 
48918761Ssam 	lseek(mf, (long)nl[X_FORKSTAT].n_value, L_SET);
4901155Sbill 	read(mf, &forkstat, sizeof forkstat);
4911155Sbill 	printf("%d forks, %d pages, average=%.2f\n",
4921155Sbill 		forkstat.cntfork, forkstat.sizfork,
4931155Sbill 		(float) forkstat.sizfork / forkstat.cntfork);
4941155Sbill 	printf("%d vforks, %d pages, average=%.2f\n",
4951155Sbill 		forkstat.cntvfork, forkstat.sizvfork,
4961155Sbill 		(float)forkstat.sizvfork / forkstat.cntvfork);
4971155Sbill }
4981155Sbill 
4991155Sbill stats(dn)
5001155Sbill {
5011155Sbill 
50218761Ssam 	if (dn >= dk_ndrive) {
5031155Sbill 		printf("  0");
5041155Sbill 		return;
5051155Sbill 	}
5061448Sbill 	printf("%3.0f", s.xfer[dn]/etime);
5071155Sbill }
5081155Sbill 
5091155Sbill double
5101155Sbill stat1(row)
5111155Sbill {
5121448Sbill 	double t;
5131448Sbill 	register i;
5141155Sbill 
5151155Sbill 	t = 0;
5161155Sbill 	for(i=0; i<CPUSTATES; i++)
5171448Sbill 		t += s.time[i];
5181448Sbill 	if(t == 0.)
5191448Sbill 		t = 1.;
5201448Sbill 	return(s.time[row]*100./t);
5211155Sbill }
5221155Sbill 
5231155Sbill pct(top, bot)
5241155Sbill {
5251155Sbill 
5261155Sbill 	if (bot == 0)
5271155Sbill 		return (0);
5281155Sbill 	return ((top * 100) / bot);
5291155Sbill }
5303162Stoy 
53117262Smckusick dointr(nintv)
53217262Smckusick {
53317262Smckusick 	int nintr, inttotal;
53417262Smckusick 	long *intrcnt;
53517262Smckusick 	char *intrname, *malloc();
53617262Smckusick 
53717262Smckusick 	nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long);
53817262Smckusick 	intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value -
53917262Smckusick 		nl[X_INTRCNT].n_value);
54017262Smckusick 	intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
54117262Smckusick 	if (intrcnt == NULL || intrname == NULL) {
54217262Smckusick 		fprintf(stderr, "vmstat: out of memory\n");
54317262Smckusick 		exit(9);
54417262Smckusick 	}
54518761Ssam 	lseek(mf, (long)nl[X_INTRCNT].n_value, L_SET);
54617262Smckusick 	read(mf, intrcnt, nintr * sizeof (long));
54718761Ssam 	lseek(mf, (long)nl[X_INTRNAMES].n_value, L_SET);
54817262Smckusick 	read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
54917262Smckusick 	printf("interrupt      total      rate\n");
55017262Smckusick 	inttotal = 0;
55117262Smckusick 	while (nintr--) {
55217262Smckusick 		if (*intrcnt)
55317262Smckusick 			printf("%-12s %8ld %8ld\n", intrname,
55417262Smckusick 			    *intrcnt, *intrcnt / nintv);
55517262Smckusick 		intrname += strlen(intrname) + 1;
55617262Smckusick 		inttotal += *intrcnt++;
55717262Smckusick 	}
55817262Smckusick 	printf("Total        %8ld %8ld\n", inttotal, inttotal / nintv);
55917262Smckusick }
56017262Smckusick 
56133610Smckusick /*
56233610Smckusick  * These names must be kept in sync with
56333610Smckusick  * the types defined in <sys/malloc.h>.
56433610Smckusick  */
56533610Smckusick char *kmemnames[] = {
56636510Smarc 	"free",		/* 0 M_FREE */
56736510Smarc 	"mbuf",		/* 1 M_MBUF */
56836510Smarc 	"devbuf",	/* 2 M_DEVBUF */
56936510Smarc 	"socket",	/* 3 M_SOCKET */
57036510Smarc 	"pcb",		/* 4 M_PCB */
57136510Smarc 	"routetbl",	/* 5 M_RTABLE */
57236510Smarc 	"hosttbl",	/* 6 M_HTABLE */
57336510Smarc 	"fragtbl",	/* 7 M_FTABLE */
57436510Smarc 	"zombie",	/* 8 M_ZOMBIE */
57536510Smarc 	"ifaddr",	/* 9 M_IFADDR */
57636510Smarc 	"soopts",	/* 10 M_SOOPTS */
57736510Smarc 	"soname",	/* 11 M_SONAME */
57836510Smarc 	"namei",	/* 12 M_NAMEI */
57936510Smarc 	"gprof",	/* 13 M_GPROF */
58036510Smarc 	"ioctlops",	/* 14 M_IOCTLOPS */
58136510Smarc 	"superblk",	/* 15 M_SUPERBLK */
58236510Smarc 	"cred",		/* 16 M_CRED */
58336510Smarc 	"pgrp",		/* 17 M_PGRP */
58436510Smarc 	"session",	/* 18 M_SESSION */
58536513Smarc 	"iov",		/* 19 M_IOV */
58638262Smckusick 	"mount",	/* 20 M_MOUNT */
58738262Smckusick 	"fhandle",	/* 21 M_FHANDLE */
58838262Smckusick 	"NFS req",	/* 22 M_NFSREQ */
58938262Smckusick 	"NFS mount",	/* 23 M_NFSMNT */
59036510Smarc 	0, 0, 0, 0, 0,
59136510Smarc 	0, 0, 0, 0, 0,
59236510Smarc 	0, 0, 0, 0, 0,
59336510Smarc 	0, 0, 0, 0, 0,
59436510Smarc 	0, 0, 0, 0, 0,
59536510Smarc 	"temp",		/* 49 M_TEMP */
59633610Smckusick };
59733610Smckusick 
59833610Smckusick domem()
59933610Smckusick {
60033610Smckusick 	struct kmemstats kmemstats[M_LAST];
60133610Smckusick 	struct kmembuckets buckets[MINBUCKET + 16];
60233610Smckusick 	register struct kmembuckets *kp;
60333610Smckusick 	register struct kmemstats *ks;
60433610Smckusick 	int i;
60533610Smckusick 
60633610Smckusick 	lseek(mf, (long)nl[X_KMEMBUCKETS].n_value, L_SET);
60733610Smckusick 	read(mf, buckets, sizeof buckets);
60833610Smckusick 	printf("Memory statistics by bucket size\n");
60933610Smckusick 	printf("    Size   In Use   Free   Requests  HighWater  Couldfree\n");
61033610Smckusick 	for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
61133610Smckusick 		if (kp->kb_calls == 0)
61233610Smckusick 			continue;
61333610Smckusick 		printf("%8d%9d%7d%11d%8d%11d\n", 1 << i,
61433610Smckusick 			kp->kb_total - kp->kb_totalfree,
61533610Smckusick 			kp->kb_totalfree, kp->kb_calls,
61633610Smckusick 			kp->kb_highwat, kp->kb_couldfree);
61733610Smckusick 
61833610Smckusick 	}
61933610Smckusick 	lseek(mf, (long)nl[X_KMEMSTAT].n_value, L_SET);
62033610Smckusick 	read(mf, kmemstats, sizeof kmemstats);
62133610Smckusick 	printf("Memory statistics by type\n");
62233610Smckusick 	printf("     Type   In Use  MemUse   HighUse  Limit  Requests %s\n",
62333610Smckusick 		"TypeLimit KernLimit");
62433610Smckusick 	for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
62533610Smckusick 		if (ks->ks_calls == 0)
62633610Smckusick 			continue;
62733610Smckusick 		printf("%10s%7d%8dK%9dK%6dK%9d%7d%10d\n",
62833610Smckusick 			kmemnames[i] ? kmemnames[i] : "undefined",
62933610Smckusick 			ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
63033610Smckusick 			(ks->ks_maxused + 1023) / 1024,
63133610Smckusick 			(ks->ks_limit + 1023) / 1024, ks->ks_calls,
63233610Smckusick 			ks->ks_limblocks, ks->ks_mapblocks);
63333610Smckusick 	}
63433610Smckusick }
63533610Smckusick 
63618761Ssam #define steal(where, var) \
63718761Ssam 	lseek(mf, where, L_SET); read(mf, &var, sizeof var);
6383162Stoy /*
6393162Stoy  * Read the drive names out of kmem.
6403162Stoy  */
64110826Ssam #ifdef vax
64218761Ssam #include <vaxuba/ubavar.h>
64318761Ssam #include <vaxmba/mbavar.h>
64418761Ssam 
6453162Stoy read_names()
6463162Stoy {
6473162Stoy 	struct mba_device mdev;
6483162Stoy 	register struct mba_device *mp;
6493162Stoy 	struct mba_driver mdrv;
6503162Stoy 	short two_char;
6513162Stoy 	char *cp = (char *) &two_char;
6523162Stoy 	struct uba_device udev, *up;
6533162Stoy 	struct uba_driver udrv;
6543162Stoy 
6553162Stoy 	mp = (struct mba_device *) nl[X_MBDINIT].n_value;
6563162Stoy 	up = (struct uba_device *) nl[X_UBDINIT].n_value;
6573492Sroot 	if (up == 0) {
65810826Ssam 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
6593162Stoy 		exit(1);
6603162Stoy 	}
6613492Sroot 	if (mp) for (;;) {
6623162Stoy 		steal(mp++, mdev);
6633162Stoy 		if (mdev.mi_driver == 0)
6643162Stoy 			break;
6653162Stoy 		if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
6663162Stoy 			continue;
6673162Stoy 		steal(mdev.mi_driver, mdrv);
6683162Stoy 		steal(mdrv.md_dname, two_char);
66918761Ssam 		sprintf(dr_name[mdev.mi_dk], "%c%c%d",
67018761Ssam 		    cp[0], cp[1], mdev.mi_unit);
6713162Stoy 	}
6723492Sroot 	for (;;) {
6733162Stoy 		steal(up++, udev);
6743162Stoy 		if (udev.ui_driver == 0)
6753162Stoy 			break;
6763162Stoy 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
6773162Stoy 			continue;
6783162Stoy 		steal(udev.ui_driver, udrv);
6793162Stoy 		steal(udrv.ud_dname, two_char);
68018761Ssam 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
68118761Ssam 		    cp[0], cp[1], udev.ui_unit);
6823162Stoy 	}
6833162Stoy }
68410826Ssam #endif
68525708Ssam 
68625708Ssam #ifdef tahoe
68725708Ssam #include <tahoevba/vbavar.h>
68825708Ssam 
68925708Ssam /*
69025708Ssam  * Read the drive names out of kmem.
69125708Ssam  */
69225708Ssam read_names()
69325708Ssam {
69425708Ssam 	struct vba_device udev, *up;
69525708Ssam 	struct vba_driver udrv;
69625708Ssam 	short two_char;
69725708Ssam 	char *cp = (char *)&two_char;
69825708Ssam 
69925708Ssam 	up = (struct vba_device *) nl[X_VBDINIT].n_value;
70025708Ssam 	if (up == 0) {
70125708Ssam 		fprintf(stderr, "vmstat: Disk init info not in namelist\n");
70225708Ssam 		exit(1);
70325708Ssam 	}
70425708Ssam 	for (;;) {
70525708Ssam 		steal(up++, udev);
70625708Ssam 		if (udev.ui_driver == 0)
70725708Ssam 			break;
70825708Ssam 		if (udev.ui_dk < 0 || udev.ui_alive == 0)
70925708Ssam 			continue;
71025708Ssam 		steal(udev.ui_driver, udrv);
71125708Ssam 		steal(udrv.ud_dname, two_char);
71225708Ssam 		sprintf(dr_name[udev.ui_dk], "%c%c%d",
71325708Ssam 		     cp[0], cp[1], udev.ui_unit);
71425708Ssam 	}
71525708Ssam }
71625708Ssam #endif
717