110826Ssam #ifndef lint 2*15266Ssam static char *sccsid = "@(#)vmstat.c 4.12 (Berkeley) 10/19/83"; 310826Ssam #endif 410826Ssam 51155Sbill #include <stdio.h> 61155Sbill #include <sys/param.h> 71155Sbill #include <sys/vm.h> 81155Sbill #include <sys/dk.h> 91155Sbill #include <nlist.h> 103162Stoy #include <sys/buf.h> 1110826Ssam #ifdef vax 129249Ssam #include <vaxuba/ubavar.h> 139249Ssam #include <vaxmba/mbavar.h> 1410826Ssam #endif 1510826Ssam #ifdef sun 1610826Ssam #include <sundev/mbvar.h> 1710826Ssam #endif 181155Sbill 191155Sbill struct nlist nl[] = { 201448Sbill #define X_CPTIME 0 211448Sbill { "_cp_time" }, 221448Sbill #define X_RATE 1 231155Sbill { "_rate" }, 241448Sbill #define X_TOTAL 2 251155Sbill { "_total" }, 261448Sbill #define X_DEFICIT 3 271155Sbill { "_deficit" }, 281448Sbill #define X_FORKSTAT 4 291155Sbill { "_forkstat" }, 301448Sbill #define X_SUM 5 311155Sbill { "_sum" }, 321448Sbill #define X_FIRSTFREE 6 331155Sbill { "_firstfree" }, 341448Sbill #define X_MAXFREE 7 351155Sbill { "_maxfree" }, 369249Ssam #define X_BOOTTIME 8 379249Ssam { "_boottime" }, 381448Sbill #define X_DKXFER 9 391448Sbill { "_dk_xfer" }, 4010826Ssam #define X_REC 10 411155Sbill { "_rectime" }, 4210826Ssam #define X_PGIN 11 431155Sbill { "_pgintime" }, 4410826Ssam #define X_HZ 12 453162Stoy { "_hz" }, 46*15266Ssam #define X_PHZ 13 47*15266Ssam { "_phz" }, 4810826Ssam #ifdef vax 49*15266Ssam #define X_MBDINIT 14 5010826Ssam { "_mbdinit" }, 51*15266Ssam #define X_UBDINIT 15 5210826Ssam { "_ubdinit" }, 5310826Ssam #endif 5410826Ssam #ifdef sun 55*15266Ssam #define X_MBDINIT 14 5610826Ssam { "_mbdinit" }, 5710826Ssam #endif 5810826Ssam { "" }, 591155Sbill }; 601155Sbill 613162Stoy char dr_name[DK_NDRIVE][10]; 623162Stoy char dr_unit[DK_NDRIVE]; 631155Sbill double stat1(); 641155Sbill int firstfree, maxfree; 653162Stoy int hz; 66*15266Ssam int phz; 67*15266Ssam int HZ; 68*15266Ssam #ifdef sun 69*15266Ssam #define INTS(x) (x) 70*15266Ssam #endif 71*15266Ssam #ifdef vax 72*15266Ssam #define INTS(x) ((x) - (hz + phz)) 73*15266Ssam #endif 74*15266Ssam 751155Sbill struct 761155Sbill { 771155Sbill int busy; 781448Sbill long time[CPUSTATES]; 791448Sbill long xfer[DK_NDRIVE]; 801155Sbill struct vmmeter Rate; 811155Sbill struct vmtotal Total; 821155Sbill struct vmmeter Sum; 831155Sbill struct forkstat Forkstat; 841155Sbill unsigned rectime; 851155Sbill unsigned pgintime; 861155Sbill } s, s1, z; 871155Sbill #define rate s.Rate 881155Sbill #define total s.Total 891155Sbill #define sum s.Sum 901155Sbill #define forkstat s.Forkstat 911155Sbill 9210826Ssam struct vmmeter osum; 931155Sbill int zero; 941155Sbill int deficit; 951155Sbill double etime; 961155Sbill int mf; 971155Sbill 981155Sbill main(argc, argv) 9910826Ssam int argc; 10010826Ssam char **argv; 1011155Sbill { 1021155Sbill time_t now; 1031155Sbill int lines; 1041155Sbill extern char *ctime(); 1051155Sbill register i,j; 1061155Sbill int iter, nintv; 1079249Ssam time_t boottime; 1081155Sbill double f1, f2; 1091155Sbill long t; 1101155Sbill extern char _sobuf[]; 1111155Sbill 1121155Sbill setbuf(stdout, _sobuf); 1131155Sbill nlist("/vmunix", nl); 1141155Sbill if(nl[0].n_type == 0) { 1151155Sbill printf("no /vmunix namelist\n"); 1161155Sbill exit(1); 1171155Sbill } 1181155Sbill mf = open("/dev/kmem", 0); 1191155Sbill if(mf < 0) { 1201155Sbill printf("cannot open /dev/kmem\n"); 1211155Sbill exit(1); 1221155Sbill } 1231155Sbill iter = 0; 1241155Sbill argc--, argv++; 1251155Sbill while (argc>0 && argv[0][0]=='-') { 1261155Sbill char *cp = *argv++; 1271155Sbill argc--; 1281155Sbill while (*++cp) switch (*cp) { 1291155Sbill 1301155Sbill case 't': 1311155Sbill dotimes(); 1321155Sbill exit(0); 13310826Ssam 1341155Sbill case 'z': 1351155Sbill close(mf); 1361155Sbill mf = open("/dev/kmem", 2); 1371155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 1381155Sbill write(mf, &z.Sum, sizeof z.Sum); 1391155Sbill exit(0); 1401155Sbill 1411155Sbill case 'f': 1421155Sbill doforkst(); 1431155Sbill exit(0); 1441155Sbill 1451155Sbill case 's': 1461155Sbill dosum(); 1471155Sbill exit(0); 1481155Sbill 1491155Sbill default: 1501155Sbill fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n"); 1511155Sbill exit(1); 1521155Sbill } 1531155Sbill } 1541155Sbill if(argc > 1) 1551155Sbill iter = atoi(argv[1]); 1561155Sbill lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0); 1571155Sbill read(mf, &firstfree, sizeof firstfree); 1581155Sbill lseek(mf, (long)nl[X_MAXFREE].n_value, 0); 1591155Sbill read(mf, &maxfree, sizeof maxfree); 1609249Ssam lseek(mf, (long)nl[X_BOOTTIME].n_value, 0); 1619249Ssam read(mf, &boottime, sizeof boottime); 1623162Stoy lseek(mf, (long)nl[X_HZ].n_value, 0); 1633162Stoy read(mf, &hz, sizeof hz); 164*15266Ssam lseek(mf, (long)nl[X_PHZ].n_value, 0); 165*15266Ssam read(mf, &phz, sizeof phz); 166*15266Ssam HZ = phz ? phz : hz; 1673612Sroot for (i = 0; i < DK_NDRIVE; i++) { 1683212Swnj strcpy(dr_name[i], "xx"); 1693162Stoy dr_unit[i] = i; 1703162Stoy } 1713162Stoy read_names(); 1721155Sbill time(&now); 1739249Ssam nintv = now - boottime; 1741155Sbill if (nintv <= 0 || nintv > 60*60*24*365*10) { 1751155Sbill printf("Time makes no sense... namelist must be wrong.\n"); 1761155Sbill exit(1); 1771155Sbill } 1781155Sbill reprint: 1791155Sbill lines = 20; 1801155Sbill /* s1 = z; */ 1811155Sbill printf("\ 1823612Sroot procs memory page disk faults cpu\n\ 183*15266Ssam 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", 18410826Ssam 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]); 1851155Sbill loop: 1861448Sbill lseek(mf, (long)nl[X_CPTIME].n_value, 0); 1871448Sbill read(mf, s.time, sizeof s.time); 1881448Sbill lseek(mf, (long)nl[X_DKXFER].n_value, 0); 1891448Sbill read(mf, s.xfer, sizeof s.xfer); 1901155Sbill if (nintv != 1) { 1911155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 1921155Sbill read(mf, &rate, sizeof rate); 1931155Sbill } else { 1941155Sbill lseek(mf, (long)nl[X_RATE].n_value, 0); 1951155Sbill read(mf, &rate, sizeof rate); 1961155Sbill } 1971155Sbill lseek(mf, (long)nl[X_TOTAL].n_value, 0); 1981155Sbill read(mf, &total, sizeof total); 19910826Ssam osum = sum; 20010826Ssam lseek(mf, (long)nl[X_SUM].n_value, 0); 20110826Ssam read(mf, &sum, sizeof sum); 2021155Sbill lseek(mf, (long)nl[X_DEFICIT].n_value, 0); 2031155Sbill read(mf, &deficit, sizeof deficit); 2041448Sbill etime = 0; 2051155Sbill for (i=0; i < DK_NDRIVE; i++) { 2061448Sbill t = s.xfer[i]; 2071448Sbill s.xfer[i] -= s1.xfer[i]; 2081448Sbill s1.xfer[i] = t; 2091155Sbill } 2101155Sbill for (i=0; i < CPUSTATES; i++) { 2111448Sbill t = s.time[i]; 2121448Sbill s.time[i] -= s1.time[i]; 2131448Sbill s1.time[i] = t; 2141448Sbill etime += s.time[i]; 2151155Sbill } 2161155Sbill if(etime == 0.) 2171155Sbill etime = 1.; 2183162Stoy printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw); 21910826Ssam #define pgtok(a) ((a)*NBPG/1024) 22010826Ssam printf("%6d%5d", pgtok(total.t_avm), pgtok(total.t_free)); 221*15266Ssam printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv, 222*15266Ssam (rate.v_xsfrec+rate.v_xifrec)/nintv); 22310826Ssam printf("%4d", pgtok(rate.v_pgpgin)/nintv); 22410826Ssam printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv, 22510826Ssam pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv); 226*15266Ssam etime /= (float) HZ; 2271155Sbill for(i=0; i<4; i++) 2281155Sbill stats(i); 229*15266Ssam printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv, 230*15266Ssam rate.v_swtch/nintv); 2311155Sbill for(i=0; i<CPUSTATES; i++) { 2321155Sbill float f = stat1(i); 2331155Sbill if (i == 0) { /* US+NI */ 2341155Sbill i++; 2351155Sbill f += stat1(i); 2361155Sbill } 2371155Sbill printf("%3.0f", f); 2381155Sbill } 2391155Sbill printf("\n"); 2401155Sbill fflush(stdout); 2411155Sbill contin: 2421155Sbill nintv = 1; 2431155Sbill --iter; 2441155Sbill if(iter) 2451155Sbill if(argc > 0) { 2461155Sbill sleep(atoi(argv[0])); 2471155Sbill if (--lines <= 0) 2481155Sbill goto reprint; 2491155Sbill goto loop; 2501155Sbill } 2511155Sbill } 2521155Sbill 2531155Sbill dotimes() 2541155Sbill { 2551155Sbill 2561155Sbill lseek(mf, (long)nl[X_REC].n_value, 0); 2571155Sbill read(mf, &s.rectime, sizeof s.rectime); 2581155Sbill lseek(mf, (long)nl[X_PGIN].n_value, 0); 2591155Sbill read(mf, &s.pgintime, sizeof s.pgintime); 2601155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2611155Sbill read(mf, &sum, sizeof sum); 2621155Sbill printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime); 2631155Sbill printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec); 2641155Sbill printf("\n"); 2651155Sbill printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10); 2661155Sbill printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0)); 2671155Sbill } 2681155Sbill 2691155Sbill dosum() 2701155Sbill { 2711155Sbill 2721155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2731155Sbill read(mf, &sum, sizeof sum); 2741155Sbill printf("%9d swap ins\n", sum.v_swpin); 2751155Sbill printf("%9d swap outs\n", sum.v_swpout); 2761155Sbill printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE); 2771155Sbill printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE); 2781155Sbill printf("%9d total address trans. faults taken\n", sum.v_faults); 2791155Sbill printf("%9d page ins\n", sum.v_pgin); 2801155Sbill printf("%9d page outs\n", sum.v_pgout); 2813612Sroot printf("%9d pages paged in\n", sum.v_pgpgin); 2823612Sroot printf("%9d pages paged out\n", sum.v_pgpgout); 2833612Sroot printf("%9d sequential process pages freed\n", sum.v_seqfree); 28412830Ssam printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec, 28512830Ssam (sum.v_fastpgrec * 100) / (sum.v_pgrec == 0 ? 1 : sum.v_pgrec)); 2861155Sbill printf("%9d reclaims from free list\n", sum.v_pgfrec); 2871155Sbill printf("%9d intransit blocking page faults\n", sum.v_intrans); 2881155Sbill printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE); 2891155Sbill printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE); 2901155Sbill printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE); 2911155Sbill printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE); 2921155Sbill printf("%9d swap text pages found in free list\n", sum.v_xsfrec); 2931155Sbill printf("%9d inode text pages found in free list\n", sum.v_xifrec); 2941155Sbill printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE); 2951155Sbill printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE); 2961155Sbill printf("%9d pages examined by the clock daemon\n", sum.v_scan); 2971155Sbill printf("%9d revolutions of the clock hand\n", sum.v_rev); 2981155Sbill printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE); 2991155Sbill printf("%9d cpu context switches\n", sum.v_swtch); 3001155Sbill printf("%9d device interrupts\n", sum.v_intr); 3011155Sbill printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma); 3021155Sbill printf("%9d traps\n", sum.v_trap); 3031155Sbill printf("%9d system calls\n", sum.v_syscall); 3041155Sbill } 3051155Sbill 3061155Sbill doforkst() 3071155Sbill { 3081155Sbill 3091155Sbill lseek(mf, (long)nl[X_FORKSTAT].n_value, 0); 3101155Sbill read(mf, &forkstat, sizeof forkstat); 3111155Sbill printf("%d forks, %d pages, average=%.2f\n", 3121155Sbill forkstat.cntfork, forkstat.sizfork, 3131155Sbill (float) forkstat.sizfork / forkstat.cntfork); 3141155Sbill printf("%d vforks, %d pages, average=%.2f\n", 3151155Sbill forkstat.cntvfork, forkstat.sizvfork, 3161155Sbill (float)forkstat.sizvfork / forkstat.cntvfork); 3171155Sbill } 3181155Sbill 3191155Sbill stats(dn) 3201155Sbill { 3211155Sbill 3221155Sbill if (dn >= DK_NDRIVE) { 3231155Sbill printf(" 0"); 3241155Sbill return; 3251155Sbill } 3261448Sbill printf("%3.0f", s.xfer[dn]/etime); 3271155Sbill } 3281155Sbill 3291155Sbill double 3301155Sbill stat1(row) 3311155Sbill { 3321448Sbill double t; 3331448Sbill register i; 3341155Sbill 3351155Sbill t = 0; 3361155Sbill for(i=0; i<CPUSTATES; i++) 3371448Sbill t += s.time[i]; 3381448Sbill if(t == 0.) 3391448Sbill t = 1.; 3401448Sbill return(s.time[row]*100./t); 3411155Sbill } 3421155Sbill 3431155Sbill pct(top, bot) 3441155Sbill { 3451155Sbill 3461155Sbill if (bot == 0) 3471155Sbill return (0); 3481155Sbill return ((top * 100) / bot); 3491155Sbill } 3503162Stoy 35110826Ssam #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); 3523162Stoy /* 3533162Stoy * Read the drive names out of kmem. 3543162Stoy */ 35510826Ssam #ifdef vax 3563162Stoy read_names() 3573162Stoy { 3583162Stoy struct mba_device mdev; 3593162Stoy register struct mba_device *mp; 3603162Stoy struct mba_driver mdrv; 3613162Stoy short two_char; 3623162Stoy char *cp = (char *) &two_char; 3633162Stoy struct uba_device udev, *up; 3643162Stoy struct uba_driver udrv; 3653162Stoy 3663162Stoy mp = (struct mba_device *) nl[X_MBDINIT].n_value; 3673162Stoy up = (struct uba_device *) nl[X_UBDINIT].n_value; 3683492Sroot if (up == 0) { 36910826Ssam fprintf(stderr, "vmstat: Disk init info not in namelist\n"); 3703162Stoy exit(1); 3713162Stoy } 3723492Sroot if (mp) for (;;) { 3733162Stoy steal(mp++, mdev); 3743162Stoy if (mdev.mi_driver == 0) 3753162Stoy break; 3763162Stoy if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 3773162Stoy continue; 3783162Stoy steal(mdev.mi_driver, mdrv); 3793162Stoy steal(mdrv.md_dname, two_char); 3803162Stoy sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]); 3813162Stoy dr_unit[mdev.mi_dk] = mdev.mi_unit; 3823162Stoy } 3833492Sroot for (;;) { 3843162Stoy steal(up++, udev); 3853162Stoy if (udev.ui_driver == 0) 3863162Stoy break; 3873162Stoy if (udev.ui_dk < 0 || udev.ui_alive == 0) 3883162Stoy continue; 3893162Stoy steal(udev.ui_driver, udrv); 3903162Stoy steal(udrv.ud_dname, two_char); 3913162Stoy sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]); 3923162Stoy dr_unit[udev.ui_dk] = udev.ui_unit; 3933162Stoy } 3943162Stoy } 39510826Ssam #endif 39610826Ssam 39710826Ssam #ifdef sun 39810826Ssam read_names() 39910826Ssam { 40010826Ssam struct mb_device mdev; 40110826Ssam register struct mb_device *mp; 40210826Ssam struct mb_driver mdrv; 40310826Ssam short two_char; 40410826Ssam char *cp = (char *) &two_char; 40510826Ssam 40610826Ssam mp = (struct mb_device *) nl[X_MBDINIT].n_value; 40710826Ssam if (mp == 0) { 40810826Ssam fprintf(stderr, "iostat: Disk init info not in namelist\n"); 40910826Ssam exit(1); 41010826Ssam } 41110826Ssam for (;;) { 41210826Ssam steal(mp++, mdev); 41310826Ssam if (mdev.md_driver == 0) 41410826Ssam break; 41510826Ssam if (mdev.md_dk < 0 || mdev.md_alive == 0) 41610826Ssam continue; 41710826Ssam steal(mdev.md_driver, mdrv); 41810826Ssam steal(mdrv.mdr_dname, two_char); 41910826Ssam sprintf(dr_name[mdev.md_dk], "%c%c%d", cp[0], cp[1]); 42010826Ssam dr_unit[mdev.md_dk] = mdev.md_unit; 42110826Ssam } 42210826Ssam } 42310826Ssam #endif 424