version 2.11 becomes 2.12 automagically.
[unix-history] / usr / src / usr.bin / vmstat / vmstat.c
CommitLineData
338c4a5d
SL
1#ifndef lint
2static char *sccsid = "@(#)vmstat.c 4.9 (Berkeley) %G%";
3#endif
4
7f02df2f
BJ
5#include <stdio.h>
6#include <sys/param.h>
7#include <sys/vm.h>
8#include <sys/dk.h>
9#include <nlist.h>
61d7d2b3 10#include <sys/buf.h>
338c4a5d 11#ifdef vax
a43be079
SL
12#include <vaxuba/ubavar.h>
13#include <vaxmba/mbavar.h>
338c4a5d
SL
14#endif
15#ifdef sun
16#include <sundev/mbvar.h>
17#endif
7f02df2f
BJ
18
19struct nlist nl[] = {
682f1dcb
BJ
20#define X_CPTIME 0
21 { "_cp_time" },
22#define X_RATE 1
7f02df2f 23 { "_rate" },
682f1dcb 24#define X_TOTAL 2
7f02df2f 25 { "_total" },
682f1dcb 26#define X_DEFICIT 3
7f02df2f 27 { "_deficit" },
682f1dcb 28#define X_FORKSTAT 4
7f02df2f 29 { "_forkstat" },
682f1dcb 30#define X_SUM 5
7f02df2f 31 { "_sum" },
682f1dcb 32#define X_FIRSTFREE 6
7f02df2f 33 { "_firstfree" },
682f1dcb 34#define X_MAXFREE 7
7f02df2f 35 { "_maxfree" },
a43be079
SL
36#define X_BOOTTIME 8
37 { "_boottime" },
682f1dcb
BJ
38#define X_DKXFER 9
39 { "_dk_xfer" },
338c4a5d 40#define X_REC 10
7f02df2f 41 { "_rectime" },
338c4a5d 42#define X_PGIN 11
7f02df2f 43 { "_pgintime" },
338c4a5d 44#define X_HZ 12
61d7d2b3 45 { "_hz" },
338c4a5d
SL
46#ifdef vax
47#define X_MBDINIT 13
48 { "_mbdinit" },
49#define X_UBDINIT 14
50 { "_ubdinit" },
51#endif
52#ifdef sun
53#define X_MBDINIT 13
54 { "_mbdinit" },
55#endif
56 { "" },
7f02df2f
BJ
57};
58
61d7d2b3
MT
59char dr_name[DK_NDRIVE][10];
60char dr_unit[DK_NDRIVE];
7f02df2f
BJ
61double stat1();
62int firstfree, maxfree;
61d7d2b3 63int hz;
7f02df2f
BJ
64struct
65{
66 int busy;
682f1dcb
BJ
67 long time[CPUSTATES];
68 long xfer[DK_NDRIVE];
7f02df2f
BJ
69 struct vmmeter Rate;
70 struct vmtotal Total;
71 struct vmmeter Sum;
72 struct forkstat Forkstat;
7f02df2f
BJ
73 unsigned rectime;
74 unsigned pgintime;
7f02df2f
BJ
75} s, s1, z;
76#define rate s.Rate
77#define total s.Total
78#define sum s.Sum
79#define forkstat s.Forkstat
80
338c4a5d 81struct vmmeter osum;
7f02df2f
BJ
82int zero;
83int deficit;
84double etime;
85int mf;
338c4a5d 86int swflag;
7f02df2f
BJ
87
88main(argc, argv)
338c4a5d
SL
89 int argc;
90 char **argv;
7f02df2f
BJ
91{
92 time_t now;
93 int lines;
94 extern char *ctime();
95 register i,j;
96 int iter, nintv;
a43be079 97 time_t boottime;
7f02df2f
BJ
98 double f1, f2;
99 long t;
100 extern char _sobuf[];
101
338c4a5d
SL
102#ifdef sun
103 swflag = 1;
104#endif
7f02df2f
BJ
105 setbuf(stdout, _sobuf);
106 nlist("/vmunix", nl);
107 if(nl[0].n_type == 0) {
108 printf("no /vmunix namelist\n");
109 exit(1);
110 }
111 mf = open("/dev/kmem", 0);
112 if(mf < 0) {
113 printf("cannot open /dev/kmem\n");
114 exit(1);
115 }
116 iter = 0;
117 argc--, argv++;
118 while (argc>0 && argv[0][0]=='-') {
119 char *cp = *argv++;
120 argc--;
121 while (*++cp) switch (*cp) {
122
338c4a5d
SL
123 case 'S':
124 swflag = 1 - swflag;
125 break;
126
127
7f02df2f
BJ
128 case 't':
129 dotimes();
130 exit(0);
338c4a5d 131
7f02df2f
BJ
132 case 'z':
133 close(mf);
134 mf = open("/dev/kmem", 2);
135 lseek(mf, (long)nl[X_SUM].n_value, 0);
136 write(mf, &z.Sum, sizeof z.Sum);
137 exit(0);
138
139 case 'f':
140 doforkst();
141 exit(0);
142
143 case 's':
144 dosum();
145 exit(0);
146
7f02df2f
BJ
147 default:
148 fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n");
149 exit(1);
150 }
151 }
152 if(argc > 1)
153 iter = atoi(argv[1]);
154 lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0);
155 read(mf, &firstfree, sizeof firstfree);
156 lseek(mf, (long)nl[X_MAXFREE].n_value, 0);
157 read(mf, &maxfree, sizeof maxfree);
a43be079
SL
158 lseek(mf, (long)nl[X_BOOTTIME].n_value, 0);
159 read(mf, &boottime, sizeof boottime);
61d7d2b3
MT
160 lseek(mf, (long)nl[X_HZ].n_value, 0);
161 read(mf, &hz, sizeof hz);
513dfff1 162 for (i = 0; i < DK_NDRIVE; i++) {
4a072e2d 163 strcpy(dr_name[i], "xx");
61d7d2b3
MT
164 dr_unit[i] = i;
165 }
166 read_names();
7f02df2f 167 time(&now);
a43be079 168 nintv = now - boottime;
7f02df2f
BJ
169 if (nintv <= 0 || nintv > 60*60*24*365*10) {
170 printf("Time makes no sense... namelist must be wrong.\n");
171 exit(1);
172 }
173reprint:
174 lines = 20;
175 /* s1 = z; */
7f02df2f 176printf("\
513dfff1 177 procs memory page disk faults cpu\n\
338c4a5d
SL
178 r b w avm fre %5s pi po fr de sr %c%d %c%d %c%d %c%d in sy cs us sy id\n\
179", swflag ? "si so" : "re at",
180 dr_name[0][0], dr_unit[0], dr_name[1][0], dr_unit[1], dr_name[2][0], dr_unit[2], dr_name[3][0], dr_unit[3]);
7f02df2f 181loop:
682f1dcb
BJ
182 lseek(mf, (long)nl[X_CPTIME].n_value, 0);
183 read(mf, s.time, sizeof s.time);
184 lseek(mf, (long)nl[X_DKXFER].n_value, 0);
185 read(mf, s.xfer, sizeof s.xfer);
7f02df2f
BJ
186 if (nintv != 1) {
187 lseek(mf, (long)nl[X_SUM].n_value, 0);
188 read(mf, &rate, sizeof rate);
189 } else {
190 lseek(mf, (long)nl[X_RATE].n_value, 0);
191 read(mf, &rate, sizeof rate);
192 }
193 lseek(mf, (long)nl[X_TOTAL].n_value, 0);
194 read(mf, &total, sizeof total);
338c4a5d
SL
195 osum = sum;
196 lseek(mf, (long)nl[X_SUM].n_value, 0);
197 read(mf, &sum, sizeof sum);
7f02df2f
BJ
198 lseek(mf, (long)nl[X_DEFICIT].n_value, 0);
199 read(mf, &deficit, sizeof deficit);
682f1dcb 200 etime = 0;
7f02df2f 201 for (i=0; i < DK_NDRIVE; i++) {
682f1dcb
BJ
202 t = s.xfer[i];
203 s.xfer[i] -= s1.xfer[i];
204 s1.xfer[i] = t;
7f02df2f
BJ
205 }
206 for (i=0; i < CPUSTATES; i++) {
682f1dcb
BJ
207 t = s.time[i];
208 s.time[i] -= s1.time[i];
209 s1.time[i] = t;
210 etime += s.time[i];
7f02df2f 211 }
7f02df2f
BJ
212 if(etime == 0.)
213 etime = 1.;
61d7d2b3 214 printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw);
338c4a5d
SL
215#define pgtok(a) ((a)*NBPG/1024)
216 printf("%6d%5d", pgtok(total.t_avm), pgtok(total.t_free));
217 printf("%4d%3d",
218 swflag ?
219 sum.v_swpin-osum.v_swpin :
220 (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
221 swflag ?
222 sum.v_swpout-osum.v_swpout :
223 (rate.v_xsfrec+rate.v_xifrec)/nintv);
224 printf("%4d", pgtok(rate.v_pgpgin)/nintv);
225 printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv,
226 pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv);
7f02df2f 227 etime /= 60.;
7f02df2f
BJ
228 for(i=0; i<4; i++)
229 stats(i);
338c4a5d
SL
230#ifdef sun
231 printf("%4d%4d", (rate.v_intr/nintv), rate.v_syscall/nintv);
232#endif
233#ifdef vax
61d7d2b3 234 printf("%4d%4d", (rate.v_intr/nintv) - hz, rate.v_syscall/nintv);
338c4a5d 235#endif
7f02df2f
BJ
236 printf("%4d", rate.v_swtch/nintv);
237 for(i=0; i<CPUSTATES; i++) {
238 float f = stat1(i);
239 if (i == 0) { /* US+NI */
240 i++;
241 f += stat1(i);
242 }
243 printf("%3.0f", f);
244 }
245 printf("\n");
246 fflush(stdout);
247contin:
248 nintv = 1;
249 --iter;
250 if(iter)
251 if(argc > 0) {
252 sleep(atoi(argv[0]));
253 if (--lines <= 0)
254 goto reprint;
255 goto loop;
256 }
257}
258
7f02df2f
BJ
259dotimes()
260{
261
262 lseek(mf, (long)nl[X_REC].n_value, 0);
263 read(mf, &s.rectime, sizeof s.rectime);
264 lseek(mf, (long)nl[X_PGIN].n_value, 0);
265 read(mf, &s.pgintime, sizeof s.pgintime);
266 lseek(mf, (long)nl[X_SUM].n_value, 0);
267 read(mf, &sum, sizeof sum);
268 printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
269 printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
270 printf("\n");
271 printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
272 printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
273}
7f02df2f
BJ
274
275dosum()
276{
277
278 lseek(mf, (long)nl[X_SUM].n_value, 0);
279 read(mf, &sum, sizeof sum);
280 printf("%9d swap ins\n", sum.v_swpin);
281 printf("%9d swap outs\n", sum.v_swpout);
282 printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
283 printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
284 printf("%9d total address trans. faults taken\n", sum.v_faults);
285 printf("%9d page ins\n", sum.v_pgin);
286 printf("%9d page outs\n", sum.v_pgout);
513dfff1
BJ
287 printf("%9d pages paged in\n", sum.v_pgpgin);
288 printf("%9d pages paged out\n", sum.v_pgpgout);
289 printf("%9d sequential process pages freed\n", sum.v_seqfree);
7f02df2f
BJ
290 printf("%9d total reclaims\n", sum.v_pgrec);
291 printf("%9d reclaims from free list\n", sum.v_pgfrec);
292 printf("%9d intransit blocking page faults\n", sum.v_intrans);
293 printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
294 printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
295 printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
296 printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
297 printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
298 printf("%9d inode text pages found in free list\n", sum.v_xifrec);
299 printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
300 printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
301 printf("%9d pages examined by the clock daemon\n", sum.v_scan);
302 printf("%9d revolutions of the clock hand\n", sum.v_rev);
303 printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
304 printf("%9d cpu context switches\n", sum.v_swtch);
305 printf("%9d device interrupts\n", sum.v_intr);
306 printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma);
307 printf("%9d traps\n", sum.v_trap);
308 printf("%9d system calls\n", sum.v_syscall);
309}
310
7f02df2f
BJ
311doforkst()
312{
313
314 lseek(mf, (long)nl[X_FORKSTAT].n_value, 0);
315 read(mf, &forkstat, sizeof forkstat);
316 printf("%d forks, %d pages, average=%.2f\n",
317 forkstat.cntfork, forkstat.sizfork,
318 (float) forkstat.sizfork / forkstat.cntfork);
319 printf("%d vforks, %d pages, average=%.2f\n",
320 forkstat.cntvfork, forkstat.sizvfork,
321 (float)forkstat.sizvfork / forkstat.cntvfork);
322}
323
324stats(dn)
325{
326
327 if (dn >= DK_NDRIVE) {
328 printf(" 0");
329 return;
330 }
682f1dcb 331 printf("%3.0f", s.xfer[dn]/etime);
7f02df2f
BJ
332}
333
334double
335stat1(row)
336{
682f1dcb
BJ
337 double t;
338 register i;
7f02df2f
BJ
339
340 t = 0;
341 for(i=0; i<CPUSTATES; i++)
682f1dcb
BJ
342 t += s.time[i];
343 if(t == 0.)
344 t = 1.;
345 return(s.time[row]*100./t);
7f02df2f
BJ
346}
347
348pct(top, bot)
349{
350
351 if (bot == 0)
352 return (0);
353 return ((top * 100) / bot);
354}
61d7d2b3 355
338c4a5d 356#define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var);
61d7d2b3
MT
357/*
358 * Read the drive names out of kmem.
61d7d2b3 359 */
338c4a5d 360#ifdef vax
61d7d2b3
MT
361read_names()
362{
363 struct mba_device mdev;
364 register struct mba_device *mp;
365 struct mba_driver mdrv;
366 short two_char;
367 char *cp = (char *) &two_char;
368 struct uba_device udev, *up;
369 struct uba_driver udrv;
370
371 mp = (struct mba_device *) nl[X_MBDINIT].n_value;
372 up = (struct uba_device *) nl[X_UBDINIT].n_value;
93ca0bfe 373 if (up == 0) {
338c4a5d 374 fprintf(stderr, "vmstat: Disk init info not in namelist\n");
61d7d2b3
MT
375 exit(1);
376 }
93ca0bfe 377 if (mp) for (;;) {
61d7d2b3
MT
378 steal(mp++, mdev);
379 if (mdev.mi_driver == 0)
380 break;
381 if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
382 continue;
383 steal(mdev.mi_driver, mdrv);
384 steal(mdrv.md_dname, two_char);
385 sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]);
386 dr_unit[mdev.mi_dk] = mdev.mi_unit;
387 }
93ca0bfe 388 for (;;) {
61d7d2b3
MT
389 steal(up++, udev);
390 if (udev.ui_driver == 0)
391 break;
392 if (udev.ui_dk < 0 || udev.ui_alive == 0)
393 continue;
394 steal(udev.ui_driver, udrv);
395 steal(udrv.ud_dname, two_char);
396 sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]);
397 dr_unit[udev.ui_dk] = udev.ui_unit;
398 }
399}
338c4a5d
SL
400#endif
401
402#ifdef sun
403read_names()
404{
405 struct mb_device mdev;
406 register struct mb_device *mp;
407 struct mb_driver mdrv;
408 short two_char;
409 char *cp = (char *) &two_char;
410
411 mp = (struct mb_device *) nl[X_MBDINIT].n_value;
412 if (mp == 0) {
413 fprintf(stderr, "iostat: Disk init info not in namelist\n");
414 exit(1);
415 }
416 for (;;) {
417 steal(mp++, mdev);
418 if (mdev.md_driver == 0)
419 break;
420 if (mdev.md_dk < 0 || mdev.md_alive == 0)
421 continue;
422 steal(mdev.md_driver, mdrv);
423 steal(mdrv.mdr_dname, two_char);
424 sprintf(dr_name[mdev.md_dk], "%c%c%d", cp[0], cp[1]);
425 dr_unit[mdev.md_dk] = mdev.md_unit;
426 }
427}
428#endif