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