xref: /csrg-svn/usr.bin/vmstat/vmstat.c (revision 1448)
1*1448Sbill static char *sccsid = "@(#)vmstat.c	4.2 (Berkeley) 10/16/80";
21155Sbill #include <stdio.h>
31155Sbill #include <sys/param.h>
41155Sbill #include <sys/vm.h>
51155Sbill #include <sys/dk.h>
61155Sbill #include <nlist.h>
71155Sbill 
81155Sbill struct nlist nl[] = {
9*1448Sbill #define	X_CPTIME	0
10*1448Sbill 	{ "_cp_time" },
11*1448Sbill #define	X_RATE		1
121155Sbill 	{ "_rate" },
13*1448Sbill #define X_TOTAL		2
141155Sbill 	{ "_total" },
15*1448Sbill #define	X_DEFICIT	3
161155Sbill 	{ "_deficit" },
17*1448Sbill #define	X_FORKSTAT	4
181155Sbill 	{ "_forkstat" },
19*1448Sbill #define X_SUM		5
201155Sbill 	{ "_sum" },
21*1448Sbill #define	X_FIRSTFREE	6
221155Sbill 	{ "_firstfree" },
23*1448Sbill #define	X_MAXFREE	7
241155Sbill 	{ "_maxfree" },
25*1448Sbill #define	X_BOOTIME	8
261155Sbill 	{ "_bootime" },
27*1448Sbill #define	X_DKXFER	9
28*1448Sbill 	{ "_dk_xfer" },
291155Sbill #ifdef ERNIE
30*1448Sbill #define X_REC		10
311155Sbill 	{ "_rectime" },
32*1448Sbill #define X_PGIN		11
331155Sbill 	{ "_pgintime" },
341155Sbill #endif
351155Sbill 	{ 0 },
361155Sbill };
371155Sbill 
381155Sbill double	stat1();
391155Sbill int	firstfree, maxfree;
401155Sbill struct
411155Sbill {
421155Sbill 	int	busy;
43*1448Sbill 	long	time[CPUSTATES];
44*1448Sbill 	long	xfer[DK_NDRIVE];
451155Sbill 	struct	vmmeter Rate;
461155Sbill 	struct	vmtotal	Total;
471155Sbill 	struct	vmmeter Sum;
481155Sbill 	struct	forkstat Forkstat;
491155Sbill #ifdef ERNIE
501155Sbill 	unsigned rectime;
511155Sbill 	unsigned pgintime;
521155Sbill #endif
531155Sbill } s, s1, z;
541155Sbill #define	rate		s.Rate
551155Sbill #define	total		s.Total
561155Sbill #define	sum		s.Sum
571155Sbill #define	forkstat	s.Forkstat
581155Sbill 
591155Sbill int	iflag = 1;
601155Sbill int	zero;
611155Sbill int	deficit;
621155Sbill double	etime;
631155Sbill int 	mf;
641155Sbill 
651155Sbill main(argc, argv)
661155Sbill char **argv;
671155Sbill {
681155Sbill 	time_t now;
691155Sbill 	int lines;
701155Sbill 	extern char *ctime();
711155Sbill 	register i,j;
721155Sbill 	int iter, nintv;
731155Sbill 	time_t bootime;
741155Sbill 	double f1, f2;
751155Sbill 	long t;
761155Sbill 	extern char _sobuf[];
771155Sbill 
781155Sbill 	setbuf(stdout, _sobuf);
791155Sbill 	nlist("/vmunix", nl);
801155Sbill 	if(nl[0].n_type == 0) {
811155Sbill 		printf("no /vmunix namelist\n");
821155Sbill 		exit(1);
831155Sbill 	}
841155Sbill 	mf = open("/dev/kmem", 0);
851155Sbill 	if(mf < 0) {
861155Sbill 		printf("cannot open /dev/kmem\n");
871155Sbill 		exit(1);
881155Sbill 	}
891155Sbill 	iter = 0;
901155Sbill 	argc--, argv++;
911155Sbill 	while (argc>0 && argv[0][0]=='-') {
921155Sbill 		char *cp = *argv++;
931155Sbill 		argc--;
941155Sbill 		while (*++cp) switch (*cp) {
951155Sbill 
961155Sbill #ifdef ERNIE
971155Sbill 		case 't':
981155Sbill 			dotimes();
991155Sbill 			exit(0);
1001155Sbill #endif
1011155Sbill 		case 'z':
1021155Sbill 			close(mf);
1031155Sbill 			mf = open("/dev/kmem", 2);
1041155Sbill 			lseek(mf, (long)nl[X_SUM].n_value, 0);
1051155Sbill 			write(mf, &z.Sum, sizeof z.Sum);
1061155Sbill 			exit(0);
1071155Sbill 
1081155Sbill 		case 'f':
1091155Sbill 			doforkst();
1101155Sbill 			exit(0);
1111155Sbill 
1121155Sbill 		case 's':
1131155Sbill 			dosum();
1141155Sbill 			exit(0);
1151155Sbill 
1161155Sbill 		case 'i':
1171155Sbill 			iflag = 0;
1181155Sbill 			break;
1191155Sbill 
1201155Sbill 		default:
1211155Sbill 			fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n");
1221155Sbill 			exit(1);
1231155Sbill 		}
1241155Sbill 	}
1251155Sbill 	if(argc > 1)
1261155Sbill 		iter = atoi(argv[1]);
1271155Sbill 	lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0);
1281155Sbill 	read(mf, &firstfree, sizeof firstfree);
1291155Sbill 	lseek(mf, (long)nl[X_MAXFREE].n_value, 0);
1301155Sbill 	read(mf, &maxfree, sizeof maxfree);
1311155Sbill 	lseek(mf, (long)nl[X_BOOTIME].n_value, 0);
1321155Sbill 	read(mf, &bootime, sizeof bootime);
1331155Sbill 	time(&now);
1341155Sbill 	nintv = now - bootime;
1351155Sbill 	if (nintv <= 0 || nintv > 60*60*24*365*10) {
1361155Sbill 		printf("Time makes no sense... namelist must be wrong.\n");
1371155Sbill 		exit(1);
1381155Sbill 	}
1391155Sbill reprint:
1401155Sbill 	lines = 20;
1411155Sbill 	/* s1 = z; */
1421155Sbill 	if (iflag==0)
1431155Sbill printf("\
1441155Sbill       Procs  Virtual Real         Page        Swap         Disk             Cpu\n\
1451155Sbill RQ DW PW SW   AVM TX  FRE  RE AT PI PO FR  DE  SR I O  D0 D1 D2 D3  CS US SY ID\n\
1461155Sbill ");
1471155Sbill 	else
1481155Sbill printf("\
1491155Sbill  Procs     Memory            Page        Swap         Disk  Faults          Cpu\n\
1501155Sbill  R B W   AVM  FRE  RE AT PI PO FR  DE  SR I O  D0 D1 D2 D3  IN  SY  CS US SY ID\n\
1511155Sbill ");
1521155Sbill loop:
153*1448Sbill 	lseek(mf, (long)nl[X_CPTIME].n_value, 0);
154*1448Sbill  	read(mf, s.time, sizeof s.time);
155*1448Sbill 	lseek(mf, (long)nl[X_DKXFER].n_value, 0);
156*1448Sbill 	read(mf, s.xfer, sizeof s.xfer);
1571155Sbill 	if (nintv != 1) {
1581155Sbill 		lseek(mf, (long)nl[X_SUM].n_value, 0);
1591155Sbill 		read(mf, &rate, sizeof rate);
1601155Sbill 	} else {
1611155Sbill 		lseek(mf, (long)nl[X_RATE].n_value, 0);
1621155Sbill 		read(mf, &rate, sizeof rate);
1631155Sbill 	}
1641155Sbill 	lseek(mf, (long)nl[X_TOTAL].n_value, 0);
1651155Sbill 	read(mf, &total, sizeof total);
1661155Sbill 	lseek(mf, (long)nl[X_DEFICIT].n_value, 0);
1671155Sbill 	read(mf, &deficit, sizeof deficit);
168*1448Sbill 	etime = 0;
1691155Sbill 	for (i=0; i < DK_NDRIVE; i++) {
170*1448Sbill 		t = s.xfer[i];
171*1448Sbill 		s.xfer[i] -= s1.xfer[i];
172*1448Sbill 		s1.xfer[i] = t;
1731155Sbill 	}
1741155Sbill 	for (i=0; i < CPUSTATES; i++) {
175*1448Sbill 		t = s.time[i];
176*1448Sbill 		s.time[i] -= s1.time[i];
177*1448Sbill 		s1.time[i] = t;
178*1448Sbill 		etime += s.time[i];
1791155Sbill 	}
1801155Sbill 	if(etime == 0.)
1811155Sbill 		etime = 1.;
1821155Sbill 	if (iflag)
1831155Sbill 		printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw,
1841155Sbill 		    total.t_sw);
1851155Sbill 	else
1861155Sbill 		printf("%2d%3d%3d%3d%3d", total.t_rq, total.t_dw, total.t_pw,
1871155Sbill 		    total.t_sw);
1881155Sbill 	if (iflag)
1891155Sbill 		printf("%6d%5d", total.t_avm/2, total.t_free/2);
1901155Sbill 	else
1911155Sbill 		printf("%6d%3d%5d", total.t_avm/2,
1921155Sbill 		    pct(total.t_avmtxt, total.t_avm), total.t_free/2);
1931155Sbill 	printf("%4d%3d%3d",
1941155Sbill 	    (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
1951155Sbill 	    (rate.v_xsfrec+rate.v_xifrec)/nintv, rate.v_pgin/nintv);
1961155Sbill 	printf("%3d%3d%4d%4.1f%2d%2d", rate.v_pgout/nintv,
1971155Sbill 	    rate.v_dfree/nintv, deficit/2,
1981155Sbill 	    (60.0 * rate.v_scan) / (LOOPSIZ*nintv),
1991155Sbill 	    rate.v_swpin/nintv, rate.v_swpout/nintv);
2001155Sbill 	etime /= 60.;
2011155Sbill 	printf(" ");
2021155Sbill 	for(i=0; i<4; i++)
2031155Sbill 		stats(i);
2041155Sbill 	if (iflag)
2051155Sbill 		printf("%4d%4d", (rate.v_intr/nintv) - HZ,
2061155Sbill 		    rate.v_syscall/nintv);
2071155Sbill 	printf("%4d", rate.v_swtch/nintv);
2081155Sbill 	for(i=0; i<CPUSTATES; i++) {
2091155Sbill 		float f = stat1(i);
2101155Sbill 		if (i == 0) {		/* US+NI */
2111155Sbill 			i++;
2121155Sbill 			f += stat1(i);
2131155Sbill 		}
2141155Sbill 		printf("%3.0f", f);
2151155Sbill 	}
2161155Sbill 	printf("\n");
2171155Sbill 	fflush(stdout);
2181155Sbill contin:
2191155Sbill 	nintv = 1;
2201155Sbill 	--iter;
2211155Sbill 	if(iter)
2221155Sbill 	if(argc > 0) {
2231155Sbill 		sleep(atoi(argv[0]));
2241155Sbill 		if (--lines <= 0)
2251155Sbill 			goto reprint;
2261155Sbill 		goto loop;
2271155Sbill 	}
2281155Sbill }
2291155Sbill 
2301155Sbill #ifdef ERNIE
2311155Sbill dotimes()
2321155Sbill {
2331155Sbill 
2341155Sbill 	lseek(mf, (long)nl[X_REC].n_value, 0);
2351155Sbill 	read(mf, &s.rectime, sizeof s.rectime);
2361155Sbill 	lseek(mf, (long)nl[X_PGIN].n_value, 0);
2371155Sbill 	read(mf, &s.pgintime, sizeof s.pgintime);
2381155Sbill 	lseek(mf, (long)nl[X_SUM].n_value, 0);
2391155Sbill 	read(mf, &sum, sizeof sum);
2401155Sbill 	printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
2411155Sbill 	printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
2421155Sbill 	printf("\n");
2431155Sbill 	printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
2441155Sbill 	printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
2451155Sbill }
2461155Sbill #endif
2471155Sbill 
2481155Sbill dosum()
2491155Sbill {
2501155Sbill 
2511155Sbill 	lseek(mf, (long)nl[X_SUM].n_value, 0);
2521155Sbill 	read(mf, &sum, sizeof sum);
2531155Sbill 	printf("%9d swap ins\n", sum.v_swpin);
2541155Sbill 	printf("%9d swap outs\n", sum.v_swpout);
2551155Sbill 	printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
2561155Sbill 	printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
2571155Sbill 	printf("%9d total address trans. faults taken\n", sum.v_faults);
2581155Sbill 	printf("%9d page ins\n", sum.v_pgin);
2591155Sbill 	printf("%9d page outs\n", sum.v_pgout);
2601155Sbill 	printf("%9d total reclaims\n", sum.v_pgrec);
2611155Sbill 	printf("%9d reclaims from free list\n", sum.v_pgfrec);
2621155Sbill 	printf("%9d intransit blocking page faults\n", sum.v_intrans);
2631155Sbill 	printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
2641155Sbill 	printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
2651155Sbill 	printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
2661155Sbill 	printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
2671155Sbill 	printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
2681155Sbill 	printf("%9d inode text pages found in free list\n", sum.v_xifrec);
2691155Sbill 	printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
2701155Sbill 	printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
2711155Sbill 	printf("%9d pages examined by the clock daemon\n", sum.v_scan);
2721155Sbill 	printf("%9d revolutions of the clock hand\n", sum.v_rev);
2731155Sbill 	printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
2741155Sbill 	printf("%9d cpu context switches\n", sum.v_swtch);
2751155Sbill 	printf("%9d device interrupts\n", sum.v_intr);
2761155Sbill 	printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma);
2771155Sbill 	printf("%9d traps\n", sum.v_trap);
2781155Sbill 	printf("%9d system calls\n", sum.v_syscall);
2791155Sbill }
2801155Sbill 
2811155Sbill 
2821155Sbill doforkst()
2831155Sbill {
2841155Sbill 
2851155Sbill 	lseek(mf, (long)nl[X_FORKSTAT].n_value, 0);
2861155Sbill 	read(mf, &forkstat, sizeof forkstat);
2871155Sbill 	printf("%d forks, %d pages, average=%.2f\n",
2881155Sbill 		forkstat.cntfork, forkstat.sizfork,
2891155Sbill 		(float) forkstat.sizfork / forkstat.cntfork);
2901155Sbill 	printf("%d vforks, %d pages, average=%.2f\n",
2911155Sbill 		forkstat.cntvfork, forkstat.sizvfork,
2921155Sbill 		(float)forkstat.sizvfork / forkstat.cntvfork);
2931155Sbill }
2941155Sbill 
2951155Sbill stats(dn)
2961155Sbill {
2971155Sbill 
2981155Sbill 	if (dn >= DK_NDRIVE) {
2991155Sbill 		printf("  0");
3001155Sbill 		return;
3011155Sbill 	}
302*1448Sbill 	printf("%3.0f", s.xfer[dn]/etime);
3031155Sbill }
3041155Sbill 
3051155Sbill double
3061155Sbill stat1(row)
3071155Sbill {
308*1448Sbill 	double t;
309*1448Sbill 	register i;
3101155Sbill 
3111155Sbill 	t = 0;
3121155Sbill 	for(i=0; i<CPUSTATES; i++)
313*1448Sbill 		t += s.time[i];
314*1448Sbill 	if(t == 0.)
315*1448Sbill 		t = 1.;
316*1448Sbill 	return(s.time[row]*100./t);
3171155Sbill }
3181155Sbill 
3191155Sbill pct(top, bot)
3201155Sbill {
3211155Sbill 
3221155Sbill 	if (bot == 0)
3231155Sbill 		return (0);
3241155Sbill 	return ((top * 100) / bot);
3251155Sbill }
326