1*10826Ssam #ifndef lint 2*10826Ssam static char *sccsid = "@(#)vmstat.c 4.9 (Berkeley) 02/09/83"; 3*10826Ssam #endif 4*10826Ssam 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> 11*10826Ssam #ifdef vax 129249Ssam #include <vaxuba/ubavar.h> 139249Ssam #include <vaxmba/mbavar.h> 14*10826Ssam #endif 15*10826Ssam #ifdef sun 16*10826Ssam #include <sundev/mbvar.h> 17*10826Ssam #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" }, 40*10826Ssam #define X_REC 10 411155Sbill { "_rectime" }, 42*10826Ssam #define X_PGIN 11 431155Sbill { "_pgintime" }, 44*10826Ssam #define X_HZ 12 453162Stoy { "_hz" }, 46*10826Ssam #ifdef vax 47*10826Ssam #define X_MBDINIT 13 48*10826Ssam { "_mbdinit" }, 49*10826Ssam #define X_UBDINIT 14 50*10826Ssam { "_ubdinit" }, 51*10826Ssam #endif 52*10826Ssam #ifdef sun 53*10826Ssam #define X_MBDINIT 13 54*10826Ssam { "_mbdinit" }, 55*10826Ssam #endif 56*10826Ssam { "" }, 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 81*10826Ssam struct vmmeter osum; 821155Sbill int zero; 831155Sbill int deficit; 841155Sbill double etime; 851155Sbill int mf; 86*10826Ssam int swflag; 871155Sbill 881155Sbill main(argc, argv) 89*10826Ssam int argc; 90*10826Ssam 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 102*10826Ssam #ifdef sun 103*10826Ssam swflag = 1; 104*10826Ssam #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 123*10826Ssam case 'S': 124*10826Ssam swflag = 1 - swflag; 125*10826Ssam break; 126*10826Ssam 127*10826Ssam 1281155Sbill case 't': 1291155Sbill dotimes(); 1301155Sbill exit(0); 131*10826Ssam 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\ 178*10826Ssam 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\ 179*10826Ssam ", swflag ? "si so" : "re at", 180*10826Ssam 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); 195*10826Ssam osum = sum; 196*10826Ssam lseek(mf, (long)nl[X_SUM].n_value, 0); 197*10826Ssam 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); 215*10826Ssam #define pgtok(a) ((a)*NBPG/1024) 216*10826Ssam printf("%6d%5d", pgtok(total.t_avm), pgtok(total.t_free)); 217*10826Ssam printf("%4d%3d", 218*10826Ssam swflag ? 219*10826Ssam sum.v_swpin-osum.v_swpin : 220*10826Ssam (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv, 221*10826Ssam swflag ? 222*10826Ssam sum.v_swpout-osum.v_swpout : 223*10826Ssam (rate.v_xsfrec+rate.v_xifrec)/nintv); 224*10826Ssam printf("%4d", pgtok(rate.v_pgpgin)/nintv); 225*10826Ssam printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv, 226*10826Ssam pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv); 2271155Sbill etime /= 60.; 2281155Sbill for(i=0; i<4; i++) 2291155Sbill stats(i); 230*10826Ssam #ifdef sun 231*10826Ssam printf("%4d%4d", (rate.v_intr/nintv), rate.v_syscall/nintv); 232*10826Ssam #endif 233*10826Ssam #ifdef vax 2343162Stoy printf("%4d%4d", (rate.v_intr/nintv) - hz, rate.v_syscall/nintv); 235*10826Ssam #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); 2901155Sbill printf("%9d total reclaims\n", sum.v_pgrec); 2911155Sbill printf("%9d reclaims from free list\n", sum.v_pgfrec); 2921155Sbill printf("%9d intransit blocking page faults\n", sum.v_intrans); 2931155Sbill printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE); 2941155Sbill printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE); 2951155Sbill printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE); 2961155Sbill printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE); 2971155Sbill printf("%9d swap text pages found in free list\n", sum.v_xsfrec); 2981155Sbill printf("%9d inode text pages found in free list\n", sum.v_xifrec); 2991155Sbill printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE); 3001155Sbill printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE); 3011155Sbill printf("%9d pages examined by the clock daemon\n", sum.v_scan); 3021155Sbill printf("%9d revolutions of the clock hand\n", sum.v_rev); 3031155Sbill printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE); 3041155Sbill printf("%9d cpu context switches\n", sum.v_swtch); 3051155Sbill printf("%9d device interrupts\n", sum.v_intr); 3061155Sbill printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma); 3071155Sbill printf("%9d traps\n", sum.v_trap); 3081155Sbill printf("%9d system calls\n", sum.v_syscall); 3091155Sbill } 3101155Sbill 3111155Sbill doforkst() 3121155Sbill { 3131155Sbill 3141155Sbill lseek(mf, (long)nl[X_FORKSTAT].n_value, 0); 3151155Sbill read(mf, &forkstat, sizeof forkstat); 3161155Sbill printf("%d forks, %d pages, average=%.2f\n", 3171155Sbill forkstat.cntfork, forkstat.sizfork, 3181155Sbill (float) forkstat.sizfork / forkstat.cntfork); 3191155Sbill printf("%d vforks, %d pages, average=%.2f\n", 3201155Sbill forkstat.cntvfork, forkstat.sizvfork, 3211155Sbill (float)forkstat.sizvfork / forkstat.cntvfork); 3221155Sbill } 3231155Sbill 3241155Sbill stats(dn) 3251155Sbill { 3261155Sbill 3271155Sbill if (dn >= DK_NDRIVE) { 3281155Sbill printf(" 0"); 3291155Sbill return; 3301155Sbill } 3311448Sbill printf("%3.0f", s.xfer[dn]/etime); 3321155Sbill } 3331155Sbill 3341155Sbill double 3351155Sbill stat1(row) 3361155Sbill { 3371448Sbill double t; 3381448Sbill register i; 3391155Sbill 3401155Sbill t = 0; 3411155Sbill for(i=0; i<CPUSTATES; i++) 3421448Sbill t += s.time[i]; 3431448Sbill if(t == 0.) 3441448Sbill t = 1.; 3451448Sbill return(s.time[row]*100./t); 3461155Sbill } 3471155Sbill 3481155Sbill pct(top, bot) 3491155Sbill { 3501155Sbill 3511155Sbill if (bot == 0) 3521155Sbill return (0); 3531155Sbill return ((top * 100) / bot); 3541155Sbill } 3553162Stoy 356*10826Ssam #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); 3573162Stoy /* 3583162Stoy * Read the drive names out of kmem. 3593162Stoy */ 360*10826Ssam #ifdef vax 3613162Stoy read_names() 3623162Stoy { 3633162Stoy struct mba_device mdev; 3643162Stoy register struct mba_device *mp; 3653162Stoy struct mba_driver mdrv; 3663162Stoy short two_char; 3673162Stoy char *cp = (char *) &two_char; 3683162Stoy struct uba_device udev, *up; 3693162Stoy struct uba_driver udrv; 3703162Stoy 3713162Stoy mp = (struct mba_device *) nl[X_MBDINIT].n_value; 3723162Stoy up = (struct uba_device *) nl[X_UBDINIT].n_value; 3733492Sroot if (up == 0) { 374*10826Ssam fprintf(stderr, "vmstat: Disk init info not in namelist\n"); 3753162Stoy exit(1); 3763162Stoy } 3773492Sroot if (mp) for (;;) { 3783162Stoy steal(mp++, mdev); 3793162Stoy if (mdev.mi_driver == 0) 3803162Stoy break; 3813162Stoy if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 3823162Stoy continue; 3833162Stoy steal(mdev.mi_driver, mdrv); 3843162Stoy steal(mdrv.md_dname, two_char); 3853162Stoy sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]); 3863162Stoy dr_unit[mdev.mi_dk] = mdev.mi_unit; 3873162Stoy } 3883492Sroot for (;;) { 3893162Stoy steal(up++, udev); 3903162Stoy if (udev.ui_driver == 0) 3913162Stoy break; 3923162Stoy if (udev.ui_dk < 0 || udev.ui_alive == 0) 3933162Stoy continue; 3943162Stoy steal(udev.ui_driver, udrv); 3953162Stoy steal(udrv.ud_dname, two_char); 3963162Stoy sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]); 3973162Stoy dr_unit[udev.ui_dk] = udev.ui_unit; 3983162Stoy } 3993162Stoy } 400*10826Ssam #endif 401*10826Ssam 402*10826Ssam #ifdef sun 403*10826Ssam read_names() 404*10826Ssam { 405*10826Ssam struct mb_device mdev; 406*10826Ssam register struct mb_device *mp; 407*10826Ssam struct mb_driver mdrv; 408*10826Ssam short two_char; 409*10826Ssam char *cp = (char *) &two_char; 410*10826Ssam 411*10826Ssam mp = (struct mb_device *) nl[X_MBDINIT].n_value; 412*10826Ssam if (mp == 0) { 413*10826Ssam fprintf(stderr, "iostat: Disk init info not in namelist\n"); 414*10826Ssam exit(1); 415*10826Ssam } 416*10826Ssam for (;;) { 417*10826Ssam steal(mp++, mdev); 418*10826Ssam if (mdev.md_driver == 0) 419*10826Ssam break; 420*10826Ssam if (mdev.md_dk < 0 || mdev.md_alive == 0) 421*10826Ssam continue; 422*10826Ssam steal(mdev.md_driver, mdrv); 423*10826Ssam steal(mdrv.mdr_dname, two_char); 424*10826Ssam sprintf(dr_name[mdev.md_dk], "%c%c%d", cp[0], cp[1]); 425*10826Ssam dr_unit[mdev.md_dk] = mdev.md_unit; 426*10826Ssam } 427*10826Ssam } 428*10826Ssam #endif 429