xref: /csrg-svn/usr.bin/vmstat/vmstat.c (revision 1155)
1*1155Sbill static char *sccsid = "@(#)vmstat.c	4.1 (Berkeley) 10/01/80";
2*1155Sbill #include <stdio.h>
3*1155Sbill #include <sys/param.h>
4*1155Sbill #include <sys/vm.h>
5*1155Sbill #include <sys/dk.h>
6*1155Sbill #include <nlist.h>
7*1155Sbill 
8*1155Sbill struct nlist nl[] = {
9*1155Sbill #define	X_DKBUSY 0
10*1155Sbill 	{ "_dk_busy" },
11*1155Sbill #define	X_DKTIME 1
12*1155Sbill 	{ "_dk_time" },
13*1155Sbill #define	X_DKNUMB 2
14*1155Sbill 	{ "_dk_numb" },
15*1155Sbill #define	X_RATE 3
16*1155Sbill 	{ "_rate" },
17*1155Sbill #define X_TOTAL 4
18*1155Sbill 	{ "_total" },
19*1155Sbill #define	X_DEFICIT 5
20*1155Sbill 	{ "_deficit" },
21*1155Sbill #define	X_FORKSTAT 6
22*1155Sbill 	{ "_forkstat" },
23*1155Sbill #define X_SUM 7
24*1155Sbill 	{ "_sum" },
25*1155Sbill #define	X_FIRSTFREE 8
26*1155Sbill 	{ "_firstfree" },
27*1155Sbill #define	X_MAXFREE 9
28*1155Sbill 	{ "_maxfree" },
29*1155Sbill #define	X_BOOTIME 10
30*1155Sbill 	{ "_bootime" },
31*1155Sbill #ifdef ERNIE
32*1155Sbill #define X_REC 10
33*1155Sbill 	{ "_rectime" },
34*1155Sbill #define X_PGIN 11
35*1155Sbill 	{ "_pgintime" },
36*1155Sbill #endif
37*1155Sbill 	{ 0 },
38*1155Sbill };
39*1155Sbill 
40*1155Sbill double	stat1();
41*1155Sbill int	firstfree, maxfree;
42*1155Sbill struct
43*1155Sbill {
44*1155Sbill 	int	busy;
45*1155Sbill 	long	etime[CPUSTATES][DK_NSTATES];
46*1155Sbill 	long	numb[DK_NDRIVE];
47*1155Sbill 	struct	vmmeter Rate;
48*1155Sbill 	struct	vmtotal	Total;
49*1155Sbill 	struct	vmmeter Sum;
50*1155Sbill 	struct	forkstat Forkstat;
51*1155Sbill #ifdef ERNIE
52*1155Sbill 	unsigned rectime;
53*1155Sbill 	unsigned pgintime;
54*1155Sbill #endif
55*1155Sbill } s, s1, z;
56*1155Sbill #define	rate		s.Rate
57*1155Sbill #define	total		s.Total
58*1155Sbill #define	sum		s.Sum
59*1155Sbill #define	forkstat	s.Forkstat
60*1155Sbill 
61*1155Sbill int	iflag = 1;
62*1155Sbill int	zero;
63*1155Sbill int	deficit;
64*1155Sbill double	etime;
65*1155Sbill int 	mf;
66*1155Sbill 
67*1155Sbill main(argc, argv)
68*1155Sbill char **argv;
69*1155Sbill {
70*1155Sbill 	time_t now;
71*1155Sbill 	int lines;
72*1155Sbill 	extern char *ctime();
73*1155Sbill 	register i,j;
74*1155Sbill 	int iter, nintv;
75*1155Sbill 	time_t bootime;
76*1155Sbill 	double f1, f2;
77*1155Sbill 	long t;
78*1155Sbill 	extern char _sobuf[];
79*1155Sbill 
80*1155Sbill 	setbuf(stdout, _sobuf);
81*1155Sbill 	nlist("/vmunix", nl);
82*1155Sbill 	if(nl[0].n_type == 0) {
83*1155Sbill 		printf("no /vmunix namelist\n");
84*1155Sbill 		exit(1);
85*1155Sbill 	}
86*1155Sbill 	mf = open("/dev/kmem", 0);
87*1155Sbill 	if(mf < 0) {
88*1155Sbill 		printf("cannot open /dev/kmem\n");
89*1155Sbill 		exit(1);
90*1155Sbill 	}
91*1155Sbill 	iter = 0;
92*1155Sbill 	argc--, argv++;
93*1155Sbill 	while (argc>0 && argv[0][0]=='-') {
94*1155Sbill 		char *cp = *argv++;
95*1155Sbill 		argc--;
96*1155Sbill 		while (*++cp) switch (*cp) {
97*1155Sbill 
98*1155Sbill #ifdef ERNIE
99*1155Sbill 		case 't':
100*1155Sbill 			dotimes();
101*1155Sbill 			exit(0);
102*1155Sbill #endif
103*1155Sbill 		case 'z':
104*1155Sbill 			close(mf);
105*1155Sbill 			mf = open("/dev/kmem", 2);
106*1155Sbill 			lseek(mf, (long)nl[X_SUM].n_value, 0);
107*1155Sbill 			write(mf, &z.Sum, sizeof z.Sum);
108*1155Sbill 			exit(0);
109*1155Sbill 
110*1155Sbill 		case 'f':
111*1155Sbill 			doforkst();
112*1155Sbill 			exit(0);
113*1155Sbill 
114*1155Sbill 		case 's':
115*1155Sbill 			dosum();
116*1155Sbill 			exit(0);
117*1155Sbill 
118*1155Sbill 		case 'i':
119*1155Sbill 			iflag = 0;
120*1155Sbill 			break;
121*1155Sbill 
122*1155Sbill 		default:
123*1155Sbill 			fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n");
124*1155Sbill 			exit(1);
125*1155Sbill 		}
126*1155Sbill 	}
127*1155Sbill 	if(argc > 1)
128*1155Sbill 		iter = atoi(argv[1]);
129*1155Sbill 	lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0);
130*1155Sbill 	read(mf, &firstfree, sizeof firstfree);
131*1155Sbill 	lseek(mf, (long)nl[X_MAXFREE].n_value, 0);
132*1155Sbill 	read(mf, &maxfree, sizeof maxfree);
133*1155Sbill 	lseek(mf, (long)nl[X_BOOTIME].n_value, 0);
134*1155Sbill 	read(mf, &bootime, sizeof bootime);
135*1155Sbill 	time(&now);
136*1155Sbill 	nintv = now - bootime;
137*1155Sbill 	if (nintv <= 0 || nintv > 60*60*24*365*10) {
138*1155Sbill 		printf("Time makes no sense... namelist must be wrong.\n");
139*1155Sbill 		exit(1);
140*1155Sbill 	}
141*1155Sbill reprint:
142*1155Sbill 	lines = 20;
143*1155Sbill 	/* s1 = z; */
144*1155Sbill 	if (iflag==0)
145*1155Sbill printf("\
146*1155Sbill       Procs  Virtual Real         Page        Swap         Disk             Cpu\n\
147*1155Sbill 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\
148*1155Sbill ");
149*1155Sbill 	else
150*1155Sbill printf("\
151*1155Sbill  Procs     Memory            Page        Swap         Disk  Faults          Cpu\n\
152*1155Sbill  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\
153*1155Sbill ");
154*1155Sbill loop:
155*1155Sbill 	lseek(mf, (long)nl[X_DKBUSY].n_value, 0);
156*1155Sbill  	read(mf, &s.busy, sizeof s.busy);
157*1155Sbill  	lseek(mf, (long)nl[X_DKTIME].n_value, 0);
158*1155Sbill  	read(mf, s.etime, sizeof s.etime);
159*1155Sbill  	lseek(mf, (long)nl[X_DKNUMB].n_value, 0);
160*1155Sbill  	read(mf, s.numb, sizeof s.numb);
161*1155Sbill 	if (nintv != 1) {
162*1155Sbill 		lseek(mf, (long)nl[X_SUM].n_value, 0);
163*1155Sbill 		read(mf, &rate, sizeof rate);
164*1155Sbill 	} else {
165*1155Sbill 		lseek(mf, (long)nl[X_RATE].n_value, 0);
166*1155Sbill 		read(mf, &rate, sizeof rate);
167*1155Sbill 	}
168*1155Sbill 	lseek(mf, (long)nl[X_TOTAL].n_value, 0);
169*1155Sbill 	read(mf, &total, sizeof total);
170*1155Sbill 	lseek(mf, (long)nl[X_DEFICIT].n_value, 0);
171*1155Sbill 	read(mf, &deficit, sizeof deficit);
172*1155Sbill 	for (i=0; i < DK_NDRIVE; i++) {
173*1155Sbill 		t = s.numb[i];
174*1155Sbill 		s.numb[i] -= s1.numb[i];
175*1155Sbill 		s1.numb[i] = t;
176*1155Sbill 	}
177*1155Sbill 	for (i=0; i < CPUSTATES; i++) {
178*1155Sbill 		for (j=0; j < DK_NSTATES; j++) {
179*1155Sbill 			t = s.etime[i][j];
180*1155Sbill 			s.etime[i][j] -= s1.etime[i][j];
181*1155Sbill 			s1.etime[i][j] = t;
182*1155Sbill 		}
183*1155Sbill 	}
184*1155Sbill 	t = 0;
185*1155Sbill 	for (i=0; i < CPUSTATES; i++)
186*1155Sbill 		for (j=0; j < DK_NSTATES; j++)
187*1155Sbill 			t += s.etime[i][j];
188*1155Sbill 	etime = t;
189*1155Sbill 	if(etime == 0.)
190*1155Sbill 		etime = 1.;
191*1155Sbill 	if (iflag)
192*1155Sbill 		printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw,
193*1155Sbill 		    total.t_sw);
194*1155Sbill 	else
195*1155Sbill 		printf("%2d%3d%3d%3d%3d", total.t_rq, total.t_dw, total.t_pw,
196*1155Sbill 		    total.t_sw);
197*1155Sbill 	if (iflag)
198*1155Sbill 		printf("%6d%5d", total.t_avm/2, total.t_free/2);
199*1155Sbill 	else
200*1155Sbill 		printf("%6d%3d%5d", total.t_avm/2,
201*1155Sbill 		    pct(total.t_avmtxt, total.t_avm), total.t_free/2);
202*1155Sbill 	printf("%4d%3d%3d",
203*1155Sbill 	    (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
204*1155Sbill 	    (rate.v_xsfrec+rate.v_xifrec)/nintv, rate.v_pgin/nintv);
205*1155Sbill 	printf("%3d%3d%4d%4.1f%2d%2d", rate.v_pgout/nintv,
206*1155Sbill 	    rate.v_dfree/nintv, deficit/2,
207*1155Sbill 	    (60.0 * rate.v_scan) / (LOOPSIZ*nintv),
208*1155Sbill 	    rate.v_swpin/nintv, rate.v_swpout/nintv);
209*1155Sbill 	etime /= 60.;
210*1155Sbill 	printf(" ");
211*1155Sbill 	for(i=0; i<4; i++)
212*1155Sbill 		stats(i);
213*1155Sbill 	if (iflag)
214*1155Sbill 		printf("%4d%4d", (rate.v_intr/nintv) - HZ,
215*1155Sbill 		    rate.v_syscall/nintv);
216*1155Sbill 	printf("%4d", rate.v_swtch/nintv);
217*1155Sbill 	for(i=0; i<CPUSTATES; i++) {
218*1155Sbill 		float f = stat1(i);
219*1155Sbill 		if (i == 0) {		/* US+NI */
220*1155Sbill 			i++;
221*1155Sbill 			f += stat1(i);
222*1155Sbill 		}
223*1155Sbill 		printf("%3.0f", f);
224*1155Sbill 	}
225*1155Sbill 	printf("\n");
226*1155Sbill 	fflush(stdout);
227*1155Sbill contin:
228*1155Sbill 	nintv = 1;
229*1155Sbill 	--iter;
230*1155Sbill 	if(iter)
231*1155Sbill 	if(argc > 0) {
232*1155Sbill 		sleep(atoi(argv[0]));
233*1155Sbill 		if (--lines <= 0)
234*1155Sbill 			goto reprint;
235*1155Sbill 		goto loop;
236*1155Sbill 	}
237*1155Sbill }
238*1155Sbill 
239*1155Sbill #ifdef ERNIE
240*1155Sbill dotimes()
241*1155Sbill {
242*1155Sbill 
243*1155Sbill 	lseek(mf, (long)nl[X_REC].n_value, 0);
244*1155Sbill 	read(mf, &s.rectime, sizeof s.rectime);
245*1155Sbill 	lseek(mf, (long)nl[X_PGIN].n_value, 0);
246*1155Sbill 	read(mf, &s.pgintime, sizeof s.pgintime);
247*1155Sbill 	lseek(mf, (long)nl[X_SUM].n_value, 0);
248*1155Sbill 	read(mf, &sum, sizeof sum);
249*1155Sbill 	printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
250*1155Sbill 	printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
251*1155Sbill 	printf("\n");
252*1155Sbill 	printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
253*1155Sbill 	printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
254*1155Sbill }
255*1155Sbill #endif
256*1155Sbill 
257*1155Sbill dosum()
258*1155Sbill {
259*1155Sbill 
260*1155Sbill 	lseek(mf, (long)nl[X_SUM].n_value, 0);
261*1155Sbill 	read(mf, &sum, sizeof sum);
262*1155Sbill 	printf("%9d swap ins\n", sum.v_swpin);
263*1155Sbill 	printf("%9d swap outs\n", sum.v_swpout);
264*1155Sbill 	printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
265*1155Sbill 	printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
266*1155Sbill 	printf("%9d total address trans. faults taken\n", sum.v_faults);
267*1155Sbill 	printf("%9d page ins\n", sum.v_pgin);
268*1155Sbill 	printf("%9d page outs\n", sum.v_pgout);
269*1155Sbill 	printf("%9d total reclaims\n", sum.v_pgrec);
270*1155Sbill 	printf("%9d reclaims from free list\n", sum.v_pgfrec);
271*1155Sbill 	printf("%9d intransit blocking page faults\n", sum.v_intrans);
272*1155Sbill 	printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
273*1155Sbill 	printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
274*1155Sbill 	printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
275*1155Sbill 	printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
276*1155Sbill 	printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
277*1155Sbill 	printf("%9d inode text pages found in free list\n", sum.v_xifrec);
278*1155Sbill 	printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
279*1155Sbill 	printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
280*1155Sbill 	printf("%9d pages examined by the clock daemon\n", sum.v_scan);
281*1155Sbill 	printf("%9d revolutions of the clock hand\n", sum.v_rev);
282*1155Sbill 	printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
283*1155Sbill 	printf("%9d cpu context switches\n", sum.v_swtch);
284*1155Sbill 	printf("%9d device interrupts\n", sum.v_intr);
285*1155Sbill 	printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma);
286*1155Sbill 	printf("%9d traps\n", sum.v_trap);
287*1155Sbill 	printf("%9d system calls\n", sum.v_syscall);
288*1155Sbill }
289*1155Sbill 
290*1155Sbill 
291*1155Sbill doforkst()
292*1155Sbill {
293*1155Sbill 
294*1155Sbill 	lseek(mf, (long)nl[X_FORKSTAT].n_value, 0);
295*1155Sbill 	read(mf, &forkstat, sizeof forkstat);
296*1155Sbill 	printf("%d forks, %d pages, average=%.2f\n",
297*1155Sbill 		forkstat.cntfork, forkstat.sizfork,
298*1155Sbill 		(float) forkstat.sizfork / forkstat.cntfork);
299*1155Sbill 	printf("%d vforks, %d pages, average=%.2f\n",
300*1155Sbill 		forkstat.cntvfork, forkstat.sizvfork,
301*1155Sbill 		(float)forkstat.sizvfork / forkstat.cntvfork);
302*1155Sbill }
303*1155Sbill 
304*1155Sbill stats(dn)
305*1155Sbill {
306*1155Sbill 
307*1155Sbill 	if (dn >= DK_NDRIVE) {
308*1155Sbill 		printf("  0");
309*1155Sbill 		return;
310*1155Sbill 	}
311*1155Sbill 	printf("%3.0f", s.numb[dn]/etime);
312*1155Sbill }
313*1155Sbill 
314*1155Sbill double
315*1155Sbill stat1(row)
316*1155Sbill {
317*1155Sbill 	register i, j;
318*1155Sbill 	long t;
319*1155Sbill 	double f1, f2;
320*1155Sbill 
321*1155Sbill 	t = 0;
322*1155Sbill 	for(i=0; i<CPUSTATES; i++)
323*1155Sbill 		for(j=0; j<DK_NSTATES; j++)
324*1155Sbill 			t += s.etime[i][j];
325*1155Sbill 	f1 = t;
326*1155Sbill 	if(f1 == 0.)
327*1155Sbill 		f1 = 1.;
328*1155Sbill 	t = 0;
329*1155Sbill 	for(j=0; j<DK_NSTATES; j++)
330*1155Sbill 		t += s.etime[row][j];
331*1155Sbill 	f2 = t;
332*1155Sbill 	return(f2*100./f1);
333*1155Sbill }
334*1155Sbill 
335*1155Sbill pct(top, bot)
336*1155Sbill {
337*1155Sbill 
338*1155Sbill 	if (bot == 0)
339*1155Sbill 		return (0);
340*1155Sbill 	return ((top * 100) / bot);
341*1155Sbill }
342