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