110826Ssam #ifndef lint 2*12830Ssam static char *sccsid = "@(#)vmstat.c 4.10 (Berkeley) 05/30/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" }, 4610826Ssam #ifdef vax 4710826Ssam #define X_MBDINIT 13 4810826Ssam { "_mbdinit" }, 4910826Ssam #define X_UBDINIT 14 5010826Ssam { "_ubdinit" }, 5110826Ssam #endif 5210826Ssam #ifdef sun 5310826Ssam #define X_MBDINIT 13 5410826Ssam { "_mbdinit" }, 5510826Ssam #endif 5610826Ssam { "" }, 571155Sbill }; 581155Sbill 593162Stoy char dr_name[DK_NDRIVE][10]; 603162Stoy char dr_unit[DK_NDRIVE]; 611155Sbill double stat1(); 621155Sbill int firstfree, maxfree; 633162Stoy int hz; 641155Sbill struct 651155Sbill { 661155Sbill int busy; 671448Sbill long time[CPUSTATES]; 681448Sbill long xfer[DK_NDRIVE]; 691155Sbill struct vmmeter Rate; 701155Sbill struct vmtotal Total; 711155Sbill struct vmmeter Sum; 721155Sbill struct forkstat Forkstat; 731155Sbill unsigned rectime; 741155Sbill unsigned pgintime; 751155Sbill } s, s1, z; 761155Sbill #define rate s.Rate 771155Sbill #define total s.Total 781155Sbill #define sum s.Sum 791155Sbill #define forkstat s.Forkstat 801155Sbill 8110826Ssam struct vmmeter osum; 821155Sbill int zero; 831155Sbill int deficit; 841155Sbill double etime; 851155Sbill int mf; 8610826Ssam int swflag; 871155Sbill 881155Sbill main(argc, argv) 8910826Ssam int argc; 9010826Ssam char **argv; 911155Sbill { 921155Sbill time_t now; 931155Sbill int lines; 941155Sbill extern char *ctime(); 951155Sbill register i,j; 961155Sbill int iter, nintv; 979249Ssam time_t boottime; 981155Sbill double f1, f2; 991155Sbill long t; 1001155Sbill extern char _sobuf[]; 1011155Sbill 10210826Ssam #ifdef sun 10310826Ssam swflag = 1; 10410826Ssam #endif 1051155Sbill setbuf(stdout, _sobuf); 1061155Sbill nlist("/vmunix", nl); 1071155Sbill if(nl[0].n_type == 0) { 1081155Sbill printf("no /vmunix namelist\n"); 1091155Sbill exit(1); 1101155Sbill } 1111155Sbill mf = open("/dev/kmem", 0); 1121155Sbill if(mf < 0) { 1131155Sbill printf("cannot open /dev/kmem\n"); 1141155Sbill exit(1); 1151155Sbill } 1161155Sbill iter = 0; 1171155Sbill argc--, argv++; 1181155Sbill while (argc>0 && argv[0][0]=='-') { 1191155Sbill char *cp = *argv++; 1201155Sbill argc--; 1211155Sbill while (*++cp) switch (*cp) { 1221155Sbill 12310826Ssam case 'S': 12410826Ssam swflag = 1 - swflag; 12510826Ssam break; 12610826Ssam 12710826Ssam 1281155Sbill case 't': 1291155Sbill dotimes(); 1301155Sbill exit(0); 13110826Ssam 1321155Sbill case 'z': 1331155Sbill close(mf); 1341155Sbill mf = open("/dev/kmem", 2); 1351155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 1361155Sbill write(mf, &z.Sum, sizeof z.Sum); 1371155Sbill exit(0); 1381155Sbill 1391155Sbill case 'f': 1401155Sbill doforkst(); 1411155Sbill exit(0); 1421155Sbill 1431155Sbill case 's': 1441155Sbill dosum(); 1451155Sbill exit(0); 1461155Sbill 1471155Sbill default: 1481155Sbill fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n"); 1491155Sbill exit(1); 1501155Sbill } 1511155Sbill } 1521155Sbill if(argc > 1) 1531155Sbill iter = atoi(argv[1]); 1541155Sbill lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0); 1551155Sbill read(mf, &firstfree, sizeof firstfree); 1561155Sbill lseek(mf, (long)nl[X_MAXFREE].n_value, 0); 1571155Sbill read(mf, &maxfree, sizeof maxfree); 1589249Ssam lseek(mf, (long)nl[X_BOOTTIME].n_value, 0); 1599249Ssam read(mf, &boottime, sizeof boottime); 1603162Stoy lseek(mf, (long)nl[X_HZ].n_value, 0); 1613162Stoy read(mf, &hz, sizeof hz); 1623612Sroot for (i = 0; i < DK_NDRIVE; i++) { 1633212Swnj strcpy(dr_name[i], "xx"); 1643162Stoy dr_unit[i] = i; 1653162Stoy } 1663162Stoy read_names(); 1671155Sbill time(&now); 1689249Ssam nintv = now - boottime; 1691155Sbill if (nintv <= 0 || nintv > 60*60*24*365*10) { 1701155Sbill printf("Time makes no sense... namelist must be wrong.\n"); 1711155Sbill exit(1); 1721155Sbill } 1731155Sbill reprint: 1741155Sbill lines = 20; 1751155Sbill /* s1 = z; */ 1761155Sbill printf("\ 1773612Sroot procs memory page disk faults cpu\n\ 17810826Ssam r b w avm fre %5s pi po fr de sr %c%d %c%d %c%d %c%d in sy cs us sy id\n\ 17910826Ssam ", swflag ? "si so" : "re at", 18010826Ssam 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]); 1811155Sbill loop: 1821448Sbill lseek(mf, (long)nl[X_CPTIME].n_value, 0); 1831448Sbill read(mf, s.time, sizeof s.time); 1841448Sbill lseek(mf, (long)nl[X_DKXFER].n_value, 0); 1851448Sbill read(mf, s.xfer, sizeof s.xfer); 1861155Sbill if (nintv != 1) { 1871155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 1881155Sbill read(mf, &rate, sizeof rate); 1891155Sbill } else { 1901155Sbill lseek(mf, (long)nl[X_RATE].n_value, 0); 1911155Sbill read(mf, &rate, sizeof rate); 1921155Sbill } 1931155Sbill lseek(mf, (long)nl[X_TOTAL].n_value, 0); 1941155Sbill read(mf, &total, sizeof total); 19510826Ssam osum = sum; 19610826Ssam lseek(mf, (long)nl[X_SUM].n_value, 0); 19710826Ssam read(mf, &sum, sizeof sum); 1981155Sbill lseek(mf, (long)nl[X_DEFICIT].n_value, 0); 1991155Sbill read(mf, &deficit, sizeof deficit); 2001448Sbill etime = 0; 2011155Sbill for (i=0; i < DK_NDRIVE; i++) { 2021448Sbill t = s.xfer[i]; 2031448Sbill s.xfer[i] -= s1.xfer[i]; 2041448Sbill s1.xfer[i] = t; 2051155Sbill } 2061155Sbill for (i=0; i < CPUSTATES; i++) { 2071448Sbill t = s.time[i]; 2081448Sbill s.time[i] -= s1.time[i]; 2091448Sbill s1.time[i] = t; 2101448Sbill etime += s.time[i]; 2111155Sbill } 2121155Sbill if(etime == 0.) 2131155Sbill etime = 1.; 2143162Stoy printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw); 21510826Ssam #define pgtok(a) ((a)*NBPG/1024) 21610826Ssam printf("%6d%5d", pgtok(total.t_avm), pgtok(total.t_free)); 21710826Ssam printf("%4d%3d", 21810826Ssam swflag ? 21910826Ssam sum.v_swpin-osum.v_swpin : 22010826Ssam (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv, 22110826Ssam swflag ? 22210826Ssam sum.v_swpout-osum.v_swpout : 22310826Ssam (rate.v_xsfrec+rate.v_xifrec)/nintv); 22410826Ssam printf("%4d", pgtok(rate.v_pgpgin)/nintv); 22510826Ssam printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv, 22610826Ssam pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv); 2271155Sbill etime /= 60.; 2281155Sbill for(i=0; i<4; i++) 2291155Sbill stats(i); 23010826Ssam #ifdef sun 23110826Ssam printf("%4d%4d", (rate.v_intr/nintv), rate.v_syscall/nintv); 23210826Ssam #endif 23310826Ssam #ifdef vax 2343162Stoy printf("%4d%4d", (rate.v_intr/nintv) - hz, rate.v_syscall/nintv); 23510826Ssam #endif 2361155Sbill printf("%4d", rate.v_swtch/nintv); 2371155Sbill for(i=0; i<CPUSTATES; i++) { 2381155Sbill float f = stat1(i); 2391155Sbill if (i == 0) { /* US+NI */ 2401155Sbill i++; 2411155Sbill f += stat1(i); 2421155Sbill } 2431155Sbill printf("%3.0f", f); 2441155Sbill } 2451155Sbill printf("\n"); 2461155Sbill fflush(stdout); 2471155Sbill contin: 2481155Sbill nintv = 1; 2491155Sbill --iter; 2501155Sbill if(iter) 2511155Sbill if(argc > 0) { 2521155Sbill sleep(atoi(argv[0])); 2531155Sbill if (--lines <= 0) 2541155Sbill goto reprint; 2551155Sbill goto loop; 2561155Sbill } 2571155Sbill } 2581155Sbill 2591155Sbill dotimes() 2601155Sbill { 2611155Sbill 2621155Sbill lseek(mf, (long)nl[X_REC].n_value, 0); 2631155Sbill read(mf, &s.rectime, sizeof s.rectime); 2641155Sbill lseek(mf, (long)nl[X_PGIN].n_value, 0); 2651155Sbill read(mf, &s.pgintime, sizeof s.pgintime); 2661155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2671155Sbill read(mf, &sum, sizeof sum); 2681155Sbill printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime); 2691155Sbill printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec); 2701155Sbill printf("\n"); 2711155Sbill printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10); 2721155Sbill printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0)); 2731155Sbill } 2741155Sbill 2751155Sbill dosum() 2761155Sbill { 2771155Sbill 2781155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2791155Sbill read(mf, &sum, sizeof sum); 2801155Sbill printf("%9d swap ins\n", sum.v_swpin); 2811155Sbill printf("%9d swap outs\n", sum.v_swpout); 2821155Sbill printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE); 2831155Sbill printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE); 2841155Sbill printf("%9d total address trans. faults taken\n", sum.v_faults); 2851155Sbill printf("%9d page ins\n", sum.v_pgin); 2861155Sbill printf("%9d page outs\n", sum.v_pgout); 2873612Sroot printf("%9d pages paged in\n", sum.v_pgpgin); 2883612Sroot printf("%9d pages paged out\n", sum.v_pgpgout); 2893612Sroot printf("%9d sequential process pages freed\n", sum.v_seqfree); 290*12830Ssam printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec, 291*12830Ssam (sum.v_fastpgrec * 100) / (sum.v_pgrec == 0 ? 1 : sum.v_pgrec)); 2921155Sbill printf("%9d reclaims from free list\n", sum.v_pgfrec); 2931155Sbill printf("%9d intransit blocking page faults\n", sum.v_intrans); 2941155Sbill printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE); 2951155Sbill printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE); 2961155Sbill printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE); 2971155Sbill printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE); 2981155Sbill printf("%9d swap text pages found in free list\n", sum.v_xsfrec); 2991155Sbill printf("%9d inode text pages found in free list\n", sum.v_xifrec); 3001155Sbill printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE); 3011155Sbill printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE); 3021155Sbill printf("%9d pages examined by the clock daemon\n", sum.v_scan); 3031155Sbill printf("%9d revolutions of the clock hand\n", sum.v_rev); 3041155Sbill printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE); 3051155Sbill printf("%9d cpu context switches\n", sum.v_swtch); 3061155Sbill printf("%9d device interrupts\n", sum.v_intr); 3071155Sbill printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma); 3081155Sbill printf("%9d traps\n", sum.v_trap); 3091155Sbill printf("%9d system calls\n", sum.v_syscall); 3101155Sbill } 3111155Sbill 3121155Sbill doforkst() 3131155Sbill { 3141155Sbill 3151155Sbill lseek(mf, (long)nl[X_FORKSTAT].n_value, 0); 3161155Sbill read(mf, &forkstat, sizeof forkstat); 3171155Sbill printf("%d forks, %d pages, average=%.2f\n", 3181155Sbill forkstat.cntfork, forkstat.sizfork, 3191155Sbill (float) forkstat.sizfork / forkstat.cntfork); 3201155Sbill printf("%d vforks, %d pages, average=%.2f\n", 3211155Sbill forkstat.cntvfork, forkstat.sizvfork, 3221155Sbill (float)forkstat.sizvfork / forkstat.cntvfork); 3231155Sbill } 3241155Sbill 3251155Sbill stats(dn) 3261155Sbill { 3271155Sbill 3281155Sbill if (dn >= DK_NDRIVE) { 3291155Sbill printf(" 0"); 3301155Sbill return; 3311155Sbill } 3321448Sbill printf("%3.0f", s.xfer[dn]/etime); 3331155Sbill } 3341155Sbill 3351155Sbill double 3361155Sbill stat1(row) 3371155Sbill { 3381448Sbill double t; 3391448Sbill register i; 3401155Sbill 3411155Sbill t = 0; 3421155Sbill for(i=0; i<CPUSTATES; i++) 3431448Sbill t += s.time[i]; 3441448Sbill if(t == 0.) 3451448Sbill t = 1.; 3461448Sbill return(s.time[row]*100./t); 3471155Sbill } 3481155Sbill 3491155Sbill pct(top, bot) 3501155Sbill { 3511155Sbill 3521155Sbill if (bot == 0) 3531155Sbill return (0); 3541155Sbill return ((top * 100) / bot); 3551155Sbill } 3563162Stoy 35710826Ssam #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); 3583162Stoy /* 3593162Stoy * Read the drive names out of kmem. 3603162Stoy */ 36110826Ssam #ifdef vax 3623162Stoy read_names() 3633162Stoy { 3643162Stoy struct mba_device mdev; 3653162Stoy register struct mba_device *mp; 3663162Stoy struct mba_driver mdrv; 3673162Stoy short two_char; 3683162Stoy char *cp = (char *) &two_char; 3693162Stoy struct uba_device udev, *up; 3703162Stoy struct uba_driver udrv; 3713162Stoy 3723162Stoy mp = (struct mba_device *) nl[X_MBDINIT].n_value; 3733162Stoy up = (struct uba_device *) nl[X_UBDINIT].n_value; 3743492Sroot if (up == 0) { 37510826Ssam fprintf(stderr, "vmstat: Disk init info not in namelist\n"); 3763162Stoy exit(1); 3773162Stoy } 3783492Sroot if (mp) for (;;) { 3793162Stoy steal(mp++, mdev); 3803162Stoy if (mdev.mi_driver == 0) 3813162Stoy break; 3823162Stoy if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 3833162Stoy continue; 3843162Stoy steal(mdev.mi_driver, mdrv); 3853162Stoy steal(mdrv.md_dname, two_char); 3863162Stoy sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]); 3873162Stoy dr_unit[mdev.mi_dk] = mdev.mi_unit; 3883162Stoy } 3893492Sroot for (;;) { 3903162Stoy steal(up++, udev); 3913162Stoy if (udev.ui_driver == 0) 3923162Stoy break; 3933162Stoy if (udev.ui_dk < 0 || udev.ui_alive == 0) 3943162Stoy continue; 3953162Stoy steal(udev.ui_driver, udrv); 3963162Stoy steal(udrv.ud_dname, two_char); 3973162Stoy sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]); 3983162Stoy dr_unit[udev.ui_dk] = udev.ui_unit; 3993162Stoy } 4003162Stoy } 40110826Ssam #endif 40210826Ssam 40310826Ssam #ifdef sun 40410826Ssam read_names() 40510826Ssam { 40610826Ssam struct mb_device mdev; 40710826Ssam register struct mb_device *mp; 40810826Ssam struct mb_driver mdrv; 40910826Ssam short two_char; 41010826Ssam char *cp = (char *) &two_char; 41110826Ssam 41210826Ssam mp = (struct mb_device *) nl[X_MBDINIT].n_value; 41310826Ssam if (mp == 0) { 41410826Ssam fprintf(stderr, "iostat: Disk init info not in namelist\n"); 41510826Ssam exit(1); 41610826Ssam } 41710826Ssam for (;;) { 41810826Ssam steal(mp++, mdev); 41910826Ssam if (mdev.md_driver == 0) 42010826Ssam break; 42110826Ssam if (mdev.md_dk < 0 || mdev.md_alive == 0) 42210826Ssam continue; 42310826Ssam steal(mdev.md_driver, mdrv); 42410826Ssam steal(mdrv.mdr_dname, two_char); 42510826Ssam sprintf(dr_name[mdev.md_dk], "%c%c%d", cp[0], cp[1]); 42610826Ssam dr_unit[mdev.md_dk] = mdev.md_unit; 42710826Ssam } 42810826Ssam } 42910826Ssam #endif 430