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