block SIGALRM in curses's SIGTSTP catcher, so alarm doesn't mess up the screen
[unix-history] / usr / src / usr.bin / vmstat / vmstat.c
CommitLineData
338c4a5d 1#ifndef lint
c441e2ca 2static char *sccsid = "@(#)vmstat.c 4.16 (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 11#include <sys/dir.h>
4b894a2c 12#include <sys/namei.h>
338c4a5d 13#ifdef vax
a43be079
SL
14#include <vaxuba/ubavar.h>
15#include <vaxmba/mbavar.h>
338c4a5d 16#endif
7f02df2f
BJ
17
18struct nlist nl[] = {
682f1dcb
BJ
19#define X_CPTIME 0
20 { "_cp_time" },
21#define X_RATE 1
7f02df2f 22 { "_rate" },
682f1dcb 23#define X_TOTAL 2
7f02df2f 24 { "_total" },
682f1dcb 25#define X_DEFICIT 3
7f02df2f 26 { "_deficit" },
682f1dcb 27#define X_FORKSTAT 4
7f02df2f 28 { "_forkstat" },
682f1dcb 29#define X_SUM 5
7f02df2f 30 { "_sum" },
682f1dcb 31#define X_FIRSTFREE 6
7f02df2f 32 { "_firstfree" },
682f1dcb 33#define X_MAXFREE 7
7f02df2f 34 { "_maxfree" },
a43be079
SL
35#define X_BOOTTIME 8
36 { "_boottime" },
682f1dcb
BJ
37#define X_DKXFER 9
38 { "_dk_xfer" },
338c4a5d 39#define X_REC 10
7f02df2f 40 { "_rectime" },
338c4a5d 41#define X_PGIN 11
7f02df2f 42 { "_pgintime" },
338c4a5d 43#define X_HZ 12
61d7d2b3 44 { "_hz" },
b3a37270
SL
45#define X_PHZ 13
46 { "_phz" },
dfdfb4c8
KM
47#define X_NCHSTATS 14
48 { "_nchstats" },
4b894a2c
KM
49#define X_INTRNAMES 15
50 { "_intrnames" },
51#define X_EINTRNAMES 16
52 { "_eintrnames" },
53#define X_INTRCNT 17
54 { "_intrcnt" },
55#define X_EINTRCNT 18
56 { "_eintrcnt" },
338c4a5d 57#ifdef vax
4b894a2c 58#define X_MBDINIT 19
338c4a5d 59 { "_mbdinit" },
4b894a2c 60#define X_UBDINIT 20
338c4a5d 61 { "_ubdinit" },
338c4a5d
SL
62#endif
63 { "" },
7f02df2f
BJ
64};
65
61d7d2b3
MT
66char dr_name[DK_NDRIVE][10];
67char dr_unit[DK_NDRIVE];
7f02df2f
BJ
68double stat1();
69int firstfree, maxfree;
61d7d2b3 70int hz;
b3a37270
SL
71int phz;
72int HZ;
b3a37270
SL
73#ifdef vax
74#define INTS(x) ((x) - (hz + phz))
75#endif
76
7f02df2f
BJ
77struct
78{
79 int busy;
682f1dcb
BJ
80 long time[CPUSTATES];
81 long xfer[DK_NDRIVE];
7f02df2f
BJ
82 struct vmmeter Rate;
83 struct vmtotal Total;
84 struct vmmeter Sum;
85 struct forkstat Forkstat;
7f02df2f
BJ
86 unsigned rectime;
87 unsigned pgintime;
7f02df2f
BJ
88} s, s1, z;
89#define rate s.Rate
90#define total s.Total
91#define sum s.Sum
92#define forkstat s.Forkstat
93
338c4a5d 94struct vmmeter osum;
7f02df2f
BJ
95int zero;
96int deficit;
97double etime;
98int mf;
4b894a2c
KM
99time_t now, boottime;
100int printhdr();
7f02df2f
BJ
101
102main(argc, argv)
338c4a5d
SL
103 int argc;
104 char **argv;
7f02df2f 105{
7f02df2f
BJ
106 int lines;
107 extern char *ctime();
108 register i,j;
4b894a2c 109 int iter, nintv, iflag = 0;
7f02df2f
BJ
110 double f1, f2;
111 long t;
7f02df2f 112
7f02df2f
BJ
113 nlist("/vmunix", nl);
114 if(nl[0].n_type == 0) {
115 printf("no /vmunix namelist\n");
116 exit(1);
117 }
118 mf = open("/dev/kmem", 0);
119 if(mf < 0) {
120 printf("cannot open /dev/kmem\n");
121 exit(1);
122 }
123 iter = 0;
124 argc--, argv++;
125 while (argc>0 && argv[0][0]=='-') {
126 char *cp = *argv++;
127 argc--;
128 while (*++cp) switch (*cp) {
129
7f02df2f
BJ
130 case 't':
131 dotimes();
132 exit(0);
338c4a5d 133
7f02df2f
BJ
134 case 'z':
135 close(mf);
136 mf = open("/dev/kmem", 2);
137 lseek(mf, (long)nl[X_SUM].n_value, 0);
138 write(mf, &z.Sum, sizeof z.Sum);
139 exit(0);
140
141 case 'f':
142 doforkst();
143 exit(0);
144
145 case 's':
146 dosum();
147 exit(0);
148
4b894a2c
KM
149 case 'i':
150 iflag++;
151 break;
152
7f02df2f 153 default:
4b894a2c 154 fprintf(stderr, "usage: vmstat [ -fsi ] [ interval ] [ count]\n");
7f02df2f
BJ
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 }
4b894a2c
KM
182 if (iflag) {
183 dointr(nintv);
184 exit(0);
185 }
186 signal(SIGCONT, printhdr);
7f02df2f
BJ
187reprint:
188 lines = 20;
189 /* s1 = z; */
4b894a2c 190 printhdr();
7f02df2f 191loop:
682f1dcb
BJ
192 lseek(mf, (long)nl[X_CPTIME].n_value, 0);
193 read(mf, s.time, sizeof s.time);
194 lseek(mf, (long)nl[X_DKXFER].n_value, 0);
195 read(mf, s.xfer, sizeof s.xfer);
7f02df2f
BJ
196 if (nintv != 1) {
197 lseek(mf, (long)nl[X_SUM].n_value, 0);
198 read(mf, &rate, sizeof rate);
199 } else {
200 lseek(mf, (long)nl[X_RATE].n_value, 0);
201 read(mf, &rate, sizeof rate);
202 }
203 lseek(mf, (long)nl[X_TOTAL].n_value, 0);
204 read(mf, &total, sizeof total);
338c4a5d
SL
205 osum = sum;
206 lseek(mf, (long)nl[X_SUM].n_value, 0);
207 read(mf, &sum, sizeof sum);
7f02df2f
BJ
208 lseek(mf, (long)nl[X_DEFICIT].n_value, 0);
209 read(mf, &deficit, sizeof deficit);
682f1dcb 210 etime = 0;
7f02df2f 211 for (i=0; i < DK_NDRIVE; i++) {
682f1dcb
BJ
212 t = s.xfer[i];
213 s.xfer[i] -= s1.xfer[i];
214 s1.xfer[i] = t;
7f02df2f
BJ
215 }
216 for (i=0; i < CPUSTATES; i++) {
682f1dcb
BJ
217 t = s.time[i];
218 s.time[i] -= s1.time[i];
219 s1.time[i] = t;
220 etime += s.time[i];
7f02df2f 221 }
7f02df2f
BJ
222 if(etime == 0.)
223 etime = 1.;
61d7d2b3 224 printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw);
338c4a5d
SL
225#define pgtok(a) ((a)*NBPG/1024)
226 printf("%6d%5d", pgtok(total.t_avm), pgtok(total.t_free));
b3a37270
SL
227 printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
228 (rate.v_xsfrec+rate.v_xifrec)/nintv);
338c4a5d
SL
229 printf("%4d", pgtok(rate.v_pgpgin)/nintv);
230 printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv,
231 pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv);
b3a37270 232 etime /= (float) HZ;
7f02df2f
BJ
233 for(i=0; i<4; i++)
234 stats(i);
b3a37270
SL
235 printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv,
236 rate.v_swtch/nintv);
7f02df2f
BJ
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
4b894a2c
KM
259printhdr()
260{
261printf("\
262 procs memory page disk faults cpu\n\
263 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",
264 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]);
265}
266
7f02df2f
BJ
267dotimes()
268{
269
270 lseek(mf, (long)nl[X_REC].n_value, 0);
271 read(mf, &s.rectime, sizeof s.rectime);
272 lseek(mf, (long)nl[X_PGIN].n_value, 0);
273 read(mf, &s.pgintime, sizeof s.pgintime);
274 lseek(mf, (long)nl[X_SUM].n_value, 0);
275 read(mf, &sum, sizeof sum);
276 printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
277 printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
278 printf("\n");
279 printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
280 printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
281}
7f02df2f
BJ
282
283dosum()
284{
dfdfb4c8
KM
285 struct nchstats statbuf;
286 long nchtotal;
7f02df2f
BJ
287
288 lseek(mf, (long)nl[X_SUM].n_value, 0);
289 read(mf, &sum, sizeof sum);
290 printf("%9d swap ins\n", sum.v_swpin);
291 printf("%9d swap outs\n", sum.v_swpout);
292 printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
293 printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
294 printf("%9d total address trans. faults taken\n", sum.v_faults);
295 printf("%9d page ins\n", sum.v_pgin);
296 printf("%9d page outs\n", sum.v_pgout);
513dfff1
BJ
297 printf("%9d pages paged in\n", sum.v_pgpgin);
298 printf("%9d pages paged out\n", sum.v_pgpgout);
299 printf("%9d sequential process pages freed\n", sum.v_seqfree);
e23f616a
SL
300 printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
301 (sum.v_fastpgrec * 100) / (sum.v_pgrec == 0 ? 1 : sum.v_pgrec));
7f02df2f
BJ
302 printf("%9d reclaims from free list\n", sum.v_pgfrec);
303 printf("%9d intransit blocking page faults\n", sum.v_intrans);
304 printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
305 printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
306 printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
307 printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
308 printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
309 printf("%9d inode text pages found in free list\n", sum.v_xifrec);
310 printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
311 printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
312 printf("%9d pages examined by the clock daemon\n", sum.v_scan);
313 printf("%9d revolutions of the clock hand\n", sum.v_rev);
314 printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
315 printf("%9d cpu context switches\n", sum.v_swtch);
316 printf("%9d device interrupts\n", sum.v_intr);
4b894a2c 317 printf("%9d software interrupts\n", sum.v_soft);
7f02df2f
BJ
318 printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma);
319 printf("%9d traps\n", sum.v_trap);
320 printf("%9d system calls\n", sum.v_syscall);
dfdfb4c8
KM
321 lseek(mf, (long)nl[X_NCHSTATS].n_value, 0);
322 read(mf, &statbuf, sizeof statbuf);
323 nchtotal = statbuf.ncs_goodhits + statbuf.ncs_badhits +
c8520a5c 324 statbuf.ncs_falsehits + statbuf.ncs_miss + statbuf.ncs_long;
dfdfb4c8 325 printf("%9d total name lookups", nchtotal);
c8520a5c 326#define nz(x) ((x) ? (x) : 1)
dfdfb4c8 327 printf(" (cache hits %d%% system %d%% per-process)\n",
c8520a5c
SL
328 statbuf.ncs_goodhits * 100 / nz(nchtotal),
329 statbuf.ncs_pass2 * 100 / nz(nchtotal));
330 printf("%9s badhits %d, falsehits %d, toolong %d\n", "",
331 statbuf.ncs_badhits, statbuf.ncs_falsehits, statbuf.ncs_long);
7f02df2f
BJ
332}
333
7f02df2f
BJ
334doforkst()
335{
336
337 lseek(mf, (long)nl[X_FORKSTAT].n_value, 0);
338 read(mf, &forkstat, sizeof forkstat);
339 printf("%d forks, %d pages, average=%.2f\n",
340 forkstat.cntfork, forkstat.sizfork,
341 (float) forkstat.sizfork / forkstat.cntfork);
342 printf("%d vforks, %d pages, average=%.2f\n",
343 forkstat.cntvfork, forkstat.sizvfork,
344 (float)forkstat.sizvfork / forkstat.cntvfork);
345}
346
347stats(dn)
348{
349
350 if (dn >= DK_NDRIVE) {
351 printf(" 0");
352 return;
353 }
682f1dcb 354 printf("%3.0f", s.xfer[dn]/etime);
7f02df2f
BJ
355}
356
357double
358stat1(row)
359{
682f1dcb
BJ
360 double t;
361 register i;
7f02df2f
BJ
362
363 t = 0;
364 for(i=0; i<CPUSTATES; i++)
682f1dcb
BJ
365 t += s.time[i];
366 if(t == 0.)
367 t = 1.;
368 return(s.time[row]*100./t);
7f02df2f
BJ
369}
370
371pct(top, bot)
372{
373
374 if (bot == 0)
375 return (0);
376 return ((top * 100) / bot);
377}
61d7d2b3 378
4b894a2c
KM
379dointr(nintv)
380{
381 int nintr, inttotal;
382 long *intrcnt;
383 char *intrname, *malloc();
384
385 nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long);
386 intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value -
387 nl[X_INTRCNT].n_value);
388 intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
389 if (intrcnt == NULL || intrname == NULL) {
390 fprintf(stderr, "vmstat: out of memory\n");
391 exit(9);
392 }
393 lseek(mf, (long)nl[X_INTRCNT].n_value, 0);
394 read(mf, intrcnt, nintr * sizeof (long));
395 lseek(mf, (long)nl[X_INTRNAMES].n_value, 0);
396 read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
397 printf("interrupt total rate\n");
398 inttotal = 0;
399 while (nintr--) {
400 if (*intrcnt)
401 printf("%-12s %8ld %8ld\n", intrname,
402 *intrcnt, *intrcnt / nintv);
403 intrname += strlen(intrname) + 1;
404 inttotal += *intrcnt++;
405 }
406 printf("Total %8ld %8ld\n", inttotal, inttotal / nintv);
407}
408
338c4a5d 409#define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var);
61d7d2b3
MT
410/*
411 * Read the drive names out of kmem.
61d7d2b3 412 */
338c4a5d 413#ifdef vax
61d7d2b3
MT
414read_names()
415{
416 struct mba_device mdev;
417 register struct mba_device *mp;
418 struct mba_driver mdrv;
419 short two_char;
420 char *cp = (char *) &two_char;
421 struct uba_device udev, *up;
422 struct uba_driver udrv;
423
424 mp = (struct mba_device *) nl[X_MBDINIT].n_value;
425 up = (struct uba_device *) nl[X_UBDINIT].n_value;
93ca0bfe 426 if (up == 0) {
338c4a5d 427 fprintf(stderr, "vmstat: Disk init info not in namelist\n");
61d7d2b3
MT
428 exit(1);
429 }
93ca0bfe 430 if (mp) for (;;) {
61d7d2b3
MT
431 steal(mp++, mdev);
432 if (mdev.mi_driver == 0)
433 break;
434 if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
435 continue;
436 steal(mdev.mi_driver, mdrv);
437 steal(mdrv.md_dname, two_char);
438 sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]);
439 dr_unit[mdev.mi_dk] = mdev.mi_unit;
440 }
93ca0bfe 441 for (;;) {
61d7d2b3
MT
442 steal(up++, udev);
443 if (udev.ui_driver == 0)
444 break;
445 if (udev.ui_dk < 0 || udev.ui_alive == 0)
446 continue;
447 steal(udev.ui_driver, udrv);
448 steal(udrv.ud_dname, two_char);
449 sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]);
450 dr_unit[udev.ui_dk] = udev.ui_unit;
451 }
452}
338c4a5d 453#endif