|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)vmstat.c 4.11 (Berkeley) 9/25/83";
3: #endif
4:
5: #include <curses.h>
6: #include <signal.h>
7: #include <stdio.h>
8: #include <sys/param.h>
9: #include <sys/vm.h>
10: #include <sys/dk.h>
11: #include <nlist.h>
12: #include <sys/buf.h>
13: #include <vba/vbavar.h>
14: #include <vba/vddc.h>
15:
16: struct nlist nli[] = {
17: #define X_CPTIME 0
18: { "_cp_time" },
19: #define X_RATE 1
20: { "_rate" },
21: #define X_TOTAL 2
22: { "_total" },
23: #define X_DEFICIT 3
24: { "_deficit" },
25: #define X_FORKSTAT 4
26: { "_forkstat" },
27: #define X_SUM 5
28: { "_sum" },
29: #define X_FIRSTFREE 6
30: { "_firstfree" },
31: #define X_MAXFREE 7
32: { "_maxfree" },
33: #define X_BOOTTIME 8
34: { "_boottime" },
35: #define X_DKXFER 9
36: { "_dk_xfer" },
37: #define X_VBDINIT 10
38: { "_vbdinit" },
39: #define X_REC 11
40: { "_rectime" },
41: #define X_PGIN 12
42: { "_pgintime" },
43: #define X_HZ 13
44: { "_hz" },
45: #define X_NVDDRV 14
46: { "_nvddrv" },
47: #define X_VDST 15
48: { "_vdst" },
49: { "" },
50: };
51:
52: #define UNIX "/vmunix"
53: char dr_name[DK_NDRIVE][10];
54: double stat1();
55: int firstfree, maxfree;
56: int hz;
57: int nodktyp;
58: struct
59: {
60: int busy;
61: long time[CPUSTATES];
62: long xfer[DK_NDRIVE];
63: struct vmmeter Rate;
64: struct vmtotal Total;
65: struct vmmeter Sum;
66: struct forkstat Forkstat;
67: unsigned rectime;
68: unsigned pgintime;
69: } s, s1, z;
70: #define rate s.Rate
71: #define total s.Total
72: #define sum s.Sum
73: #define forkstat s.Forkstat
74: #define MAXRPT 10
75: #define NCOLS 80
76: #define NLINES 24
77:
78: struct vmmeter osum;
79: int zero;
80: int deficit;
81: double etime;
82: int mf;
83: int swflag;
84: float f;
85: int iter,count,repcnt;
86:
87: fs_tab *vdinfo, *vdinfo_save;
88: long name;
89:
90: struct
91: {
92: int r;
93: int b;
94: int w;
95: int avm;
96: int fre;
97: int pgre;
98: int pgat;
99: int pi;
100: int po;
101: int fr;
102: int de;
103: int sr;
104: float dk[DK_NDRIVE];
105: int in;
106: int sy;
107: int cs;
108: float syste[(CPUSTATES-1)];
109: /*
110: int us;
111: int sy;
112: int id;
113: */
114: } rec[MAXRPT];
115:
116: extern char *malloc();
117:
118: main(argc, argv)
119: int argc;
120: char **argv;
121: {
122: extern char *ctime();
123: register i,j;
124: int nintv;
125: int totrep;
126: time_t boottime;
127: double f1, f2;
128: long t;
129: extern char _sobuf[];
130: int die();
131: int ptoutput();
132: int shiftarray();
133: int dietty();
134: int TERM;
135: time_t now;
136:
137: TERM = isatty(1);
138: setbuf(stdout, _sobuf);
139: nlist(UNIX, nli);
140: if(nli[0].n_value == 0) {
141: printf("no %s namelist\n",UNIX);
142: exit(1);
143: }
144: mf = open("/dev/kmem", 0);
145: if(mf < 0) {
146: printf("cannot open /dev/kmem\n");
147: exit(1);
148: }
149: iter = 0;
150: argc--, argv++;
151: while (argc>0 && argv[0][0]=='-') {
152: char *cp = *argv++;
153: argc--;
154: while (*++cp) switch (*cp) {
155:
156: case 'S':
157: swflag = 1 - swflag;
158: break;
159:
160:
161: case 't':
162: dotimes();
163: exit(0);
164:
165: case 'z':
166: close(mf);
167: mf = open("/dev/kmem", 2);
168: lseek(mf, (long)nli[X_SUM].n_value, 0);
169: write(mf, &z.Sum, sizeof z.Sum);
170: exit(0);
171:
172: case 'f':
173: doforkst();
174: exit(0);
175:
176: case 's':
177: dosum();
178: exit(0);
179:
180: default:
181: fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n");
182: exit(1);
183: }
184: }
185: totrep = 1;
186: if(argc > 1)
187: totrep = atoi(argv[1]);
188: if(argc ==1)
189: totrep = -1;
190: iter = 0;
191: if ((totrep <0 ) || (totrep > MAXRPT))
192: repcnt = MAXRPT;
193: else
194: repcnt = totrep;
195: lseek(mf, (long)nli[X_FIRSTFREE].n_value, 0);
196: read(mf, &firstfree, sizeof firstfree);
197: lseek(mf, (long)nli[X_MAXFREE].n_value, 0);
198: read(mf, &maxfree, sizeof maxfree);
199: lseek(mf, (long)nli[X_BOOTTIME].n_value, 0);
200: read(mf, &boottime, sizeof boottime);
201: lseek(mf, (long)nli[X_HZ].n_value, 0);
202: read(mf, &hz, sizeof hz);
203: lseek(mf, (long)nli[X_NVDDRV].n_value, 0);
204: read(mf, &nodktyp, sizeof nodktyp);
205: vdinfo = (fs_tab *)malloc(nodktyp*sizeof(fs_tab));
206: lseek(mf, (long)nli[X_VDST].n_value, 0);
207: read(mf, (char *)vdinfo, nodktyp*sizeof(fs_tab));
208: vdinfo_save = vdinfo;
209: for (i = 0; i < nodktyp; vdinfo++, i++) {
210: name = (long)vdinfo->type_name;
211: vdinfo->type_name = malloc(3);
212: lseek(mf, (long)name, 0);
213: read(mf, vdinfo->type_name, 3);
214: }
215: vdinfo = vdinfo_save;
216: for (i = 0; i < DK_NDRIVE; i++)
217: sprintf(dr_name[i],"??%x",i);
218: read_names();
219: time(&now);
220: nintv = now - boottime;
221: if (nintv <= 0 || nintv > 60*60*24*365*10) {
222: printf("Time makes no sense... namelist must be wrong.\n");
223: exit(1);
224: }
225: if (TERM){
226: initscr();
227: signal(SIGINT,dietty);
228: nonl();
229: crmode();
230: noecho();
231: leaveok(stdscr,TRUE);
232: scrollok(stdscr,FALSE);
233: }
234: else
235: signal(SIGINT,die);
236: reprint:
237: loop:
238: lseek(mf, (long)nli[X_CPTIME].n_value, 0);
239: read(mf, s.time, sizeof s.time);
240: lseek(mf, (long)nli[X_DKXFER].n_value, 0);
241: read(mf, s.xfer, sizeof s.xfer);
242: if (nintv != 1) {
243: lseek(mf, (long)nli[X_SUM].n_value, 0);
244: read(mf, &rate, sizeof rate);
245: } else {
246: lseek(mf, (long)nli[X_RATE].n_value, 0);
247: read(mf, &rate, sizeof rate);
248: }
249: lseek(mf, (long)nli[X_TOTAL].n_value, 0);
250: read(mf, &total, sizeof total);
251: osum = sum;
252: lseek(mf, (long)nli[X_SUM].n_value, 0);
253: read(mf, &sum, sizeof sum);
254: lseek(mf, (long)nli[X_DEFICIT].n_value, 0);
255: read(mf, &deficit, sizeof deficit);
256: etime = 0;
257: for (i=0; i < DK_NDRIVE; i++) {
258: t = s.xfer[i];
259: s.xfer[i] -= s1.xfer[i];
260: s1.xfer[i] = t;
261: }
262: for (i=0; i < CPUSTATES; i++) {
263: t = s.time[i];
264: s.time[i] -= s1.time[i];
265: s1.time[i] = t;
266: etime += s.time[i];
267: }
268: if(etime == 0.)
269: etime = 1.;
270: rec[iter].r = total.t_rq;
271: rec[iter].b = total.t_dw+total.t_pw;
272: rec[iter].w = total.t_sw;
273: rec[iter].avm= total.t_avm;
274: rec[iter].fre = total.t_free;
275: if(swflag){
276: rec[iter].pgre= sum.v_swpin-osum.v_swpin ;
277: rec[iter].pgat = sum.v_swpout-osum.v_swpout ;
278: }
279: else {
280:
281: rec[iter].pgre = (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv;
282: rec[iter].pgat = (rate.v_xsfrec+rate.v_xifrec)/nintv;
283: }
284: rec[iter].pi = rate.v_pgpgin/nintv;
285: rec[iter].po= rate.v_pgpgout/nintv;
286: rec[iter].fr= rate.v_dfree/nintv;
287: rec[iter].de = deficit;
288: rec[iter].sr = rate.v_scan/nintv;
289: etime /= (float) hz;
290: for(i=0; i < DK_NDRIVE; i++){
291: rec[iter].dk[i] = s.xfer[i]/etime;
292: }
293: rec[iter].in= (rate.v_intr/nintv) - hz;
294: rec[iter].sy = rate.v_syscall/nintv;
295: rec[iter].cs = rate.v_swtch/nintv;
296: for(i=0; i<CPUSTATES; i++) {
297: f = stat1(i);
298: if (i == 0) { /* US+NI */
299: i++;
300: f += stat1(i);
301: }
302: rec[iter].syste[i-1] = f;
303: }
304: nintv = 1;
305: count++;
306: if (count >= MAXRPT)
307: if ( (count % MAXRPT) == 0)
308: if(TERM == 0)
309: ptoutput(iter+1);
310: if(TERM)
311: {
312: printw("mem[avm fre] pag[%5s pi po fr de sr] fault[in sy cs] cpu[us sy id]\n", swflag ? "si so" : "re at");
313: for(i=0; i < (iter+1); i++){
314: printw("%7d%7d %4d%3d%4d%4d%4d%4d%4d %5d%4d%4d ",
315: rec[i].avm,rec[i].fre, rec[i].pgre,rec[i].pgat,
316: rec[i].pi,rec[i].po,rec[i].fr, rec[i].de,rec[i].sr,
317: rec[i].in,rec[i].sy,rec[i].cs);
318: for(j=0; j<( CPUSTATES -1); j++)
319: printw("%3.0f",rec[i].syste[j]);
320: printw("\n");
321: }
322: for(i=(iter+1); i<repcnt; i++)
323: printw("\n");
324: printw("proc[r b w]Dsk[");
325: for (i=0; i < DK_NDRIVE; i++)
326: if(dr_name[i][0] !='?')
327: printw("%3.3s ",dr_name[i]);
328: printw("]\n");
329: for(i=0; i < (iter+1); i++){
330: printw(" %2d%2d%2d ",rec[i].r,rec[i].b,rec[i].w);
331: for(j=0; j<DK_NDRIVE; j++)
332: if(dr_name[j][0] !='?')
333: printw("%3.0f ",rec[i].dk[j]);
334: printw("\n");
335: }
336: for (i=(iter+1); i< repcnt; i++)
337: printw("\n");
338: refresh();
339: move(0,0);
340: }
341: if (totrep > 0)
342: totrep--;
343: iter++;
344: if (count >= MAXRPT ){
345: for(i=0; i < (MAXRPT -1); i++){
346: shiftarray(i,1);
347: }
348: iter = MAXRPT-1;
349: }
350:
351: if (totrep != 0){
352: if(argc > 0) {
353: sleep(atoi(argv[0]));
354: goto loop;
355: }
356: }
357: if(TERM)
358: dietty();
359: else {
360: die();
361: }
362: }
363:
364: dotimes()
365: {
366:
367: lseek(mf, (long)nli[X_REC].n_value, 0);
368: read(mf, &s.rectime, sizeof s.rectime);
369: lseek(mf, (long)nli[X_PGIN].n_value, 0);
370: read(mf, &s.pgintime, sizeof s.pgintime);
371: lseek(mf, (long)nli[X_SUM].n_value, 0);
372: read(mf, &sum, sizeof sum);
373: printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
374: printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
375: printf("\n");
376: printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
377: printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
378: }
379:
380: dosum()
381: {
382:
383: lseek(mf, (long)nli[X_SUM].n_value, 0);
384: read(mf, &sum, sizeof sum);
385: printf("%9d swap ins\n", sum.v_swpin);
386: printf("%9d swap outs\n", sum.v_swpout);
387: printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE);
388: printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE);
389: printf("%9d total address trans. faults taken\n", sum.v_faults);
390: printf("%9d page ins\n", sum.v_pgin);
391: printf("%9d page outs\n", sum.v_pgout);
392: printf("%9d pages paged in\n", sum.v_pgpgin);
393: printf("%9d pages paged out\n", sum.v_pgpgout);
394: printf("%9d sequential process pages freed\n", sum.v_seqfree);
395: printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
396: (sum.v_fastpgrec * 100) / (sum.v_pgrec == 0 ? 1 : sum.v_pgrec));
397: printf("%9d reclaims from free list\n", sum.v_pgfrec);
398: printf("%9d intransit blocking page faults\n", sum.v_intrans);
399: printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
400: printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE);
401: printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE);
402: printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE);
403: printf("%9d swap text pages found in free list\n", sum.v_xsfrec);
404: printf("%9d inode text pages found in free list\n", sum.v_xifrec);
405: printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE);
406: printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE);
407: printf("%9d pages examined by the clock daemon\n", sum.v_scan);
408: printf("%9d revolutions of the clock hand\n", sum.v_rev);
409: printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
410: printf("%9d cpu context switches\n", sum.v_swtch);
411: printf("%9d device interrupts\n", sum.v_intr);
412: printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma);
413: printf("%9d traps\n", sum.v_trap);
414: printf("%9d system calls\n", sum.v_syscall);
415: }
416:
417: doforkst()
418: {
419:
420: lseek(mf, (long)nli[X_FORKSTAT].n_value, 0);
421: read(mf, &forkstat, sizeof forkstat);
422: printf("%d forks, %d pages, average=%.2f\n",
423: forkstat.cntfork, forkstat.sizfork,
424: (float) forkstat.sizfork / forkstat.cntfork);
425: printf("%d vforks, %d pages, average=%.2f\n",
426: forkstat.cntvfork, forkstat.sizvfork,
427: (float)forkstat.sizvfork / forkstat.cntvfork);
428: }
429:
430: stats(dn)
431: {
432:
433: if (dn >= DK_NDRIVE) {
434: printf(" 0");
435: return;
436: }
437: printf("%3.0f", s.xfer[dn]/etime);
438: }
439:
440: double
441: stat1(row)
442: {
443: double t;
444: register i;
445:
446: t = 0;
447: for(i=0; i<CPUSTATES; i++)
448: t += s.time[i];
449: if(t == 0.)
450: t = 1.;
451: return(s.time[row]*100./t);
452: }
453:
454: pct(top, bot)
455: {
456:
457: if (bot == 0)
458: return (0);
459: return ((top * 100) / bot);
460: }
461:
462: #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var);
463:
464: read_names()
465: {
466: struct vba_device udev, *up;
467: struct vba_driver udrv;
468: int unit, i;
469:
470: up = (struct vba_device *) nli[X_VBDINIT].n_value;
471: if (up == 0)
472: {
473: fprintf(stderr, "vmstat: Disk init info not in namelist\n");
474: exit(1);
475: }
476: vdinfo_save = vdinfo;
477: for (;;) {
478: steal(up++, udev);
479: unit = (udev.ui_ctlr * 4) + udev.ui_slave;
480: if (udev.ui_driver == 0)
481: break;
482: if (udev.ui_dk <= 0 || udev.ui_alive == 0)
483: continue;
484: if(udev.ui_type >= nodktyp){
485: fprintf(stderr,"vmstat : disk type in unit %d not supported \n",unit);
486: exit(1);
487: }
488: vdinfo = vdinfo_save;
489: for(i=0; i < udev.ui_type; i++)
490: vdinfo++;
491: dr_name[unit][0] = vdinfo->type_name[0];
492: dr_name[unit][1] = vdinfo->type_name[1];
493: }
494: }
495: die()
496: {
497: int i,j,k;
498: iter--;
499: signal(SIGINT,SIG_IGN);
500: i = count % MAXRPT;
501: if (count >= MAXRPT){
502: k = MAXRPT - i;
503: for (j=0; j <i; j++)
504: shiftarray(0,k);
505: }
506: ptoutput(i);
507: exit(0);
508: }
509: dietty()
510: {
511: signal(SIGINT,SIG_IGN);
512: mvcur(0,COLS-1, LINES-1,0);
513: endwin();
514: exit(0);
515: }
516: ptoutput(reptot)
517: int reptot;
518: {
519: register i,j;
520: printf("mem[avm fre] pag[%5s pi po fr de sr] fault[in sy cs] cpu[us sy id]\n", swflag ? "si so" : "re at");
521: for(i=0; i < (reptot); i++){
522: printf(" %6d%5d %4d%3d%4d%4d%4d%4d%4d %4d%4d%4d ",
523: rec[i].avm,rec[i].fre, rec[i].pgre,rec[i].pgat,
524: rec[i].pi,rec[i].po,rec[i].fr, rec[i].de,rec[i].sr,
525: rec[i].in,rec[i].sy,rec[i].cs);
526: for(j=0; j<( CPUSTATES -1); j++)
527: printf("%3.0f",rec[i].syste[j]);
528: printf("\n");
529: }
530: for(i=(reptot); i<repcnt; i++)
531: printf("\n");
532:
533: printf("proc[r b w]Dsk[");
534:
535: for (i=0; i < DK_NDRIVE; i++)
536: if(dr_name[i][0] !='?')
537: printf("%3.3s ",dr_name[i]);
538: printf("]\n");
539: for(i=0; i < (reptot); i++){
540: printf(" %2d%2d%2d ",rec[i].r,rec[i].b,rec[i].w);
541: for(j=0; j<DK_NDRIVE; j++)
542: if(dr_name[j][0] !='?')
543: printf("%3.0f ",rec[i].dk[j]);
544: printf("\n");
545: }
546: for (i=(reptot); i< repcnt; i++)
547: printf("\n");
548: }
549: shiftarray(srtary,offset)
550: int srtary; /* starting array to be shifted */
551: int offset; /* offset to be skip in shifting array */
552: {
553: register j;
554: rec[srtary].r = rec[srtary+offset].r;
555: rec[srtary].b = rec[srtary+offset].b;
556: rec[srtary].w = rec[srtary+offset].w;
557: rec[srtary].avm = rec[srtary+offset].avm;
558: rec[srtary].fre = rec[srtary+offset].fre;
559: rec[srtary].pgre = rec[srtary+offset].pgre;
560: rec[srtary].pgat = rec[srtary+offset].pgat;
561: rec[srtary].pi = rec[srtary+offset].pi;
562: rec[srtary].po = rec[srtary+offset].po;
563: rec[srtary].fr = rec[srtary+offset].fr;
564: rec[srtary].de = rec[srtary+offset].de;
565: rec[srtary].sr = rec[srtary+offset].sr;
566: for(j=0; j < DK_NDRIVE; j++)
567: rec[srtary].dk[j] = rec[srtary+offset].dk[j];
568: rec[srtary].in = rec[srtary+offset].in;
569: rec[srtary].sy = rec[srtary+offset].sy;
570: rec[srtary].cs = rec[srtary+offset].cs;
571: for(j=0; j < (CPUSTATES-1); j++)
572: rec[srtary].syste[j] = rec[srtary+offset].syste[j];
573: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.