1*3162Stoy static char *sccsid = "@(#)vmstat.c 4.3 (Berkeley) 03/09/81"; 21155Sbill #include <stdio.h> 31155Sbill #include <sys/param.h> 41155Sbill #include <sys/vm.h> 51155Sbill #include <sys/dk.h> 61155Sbill #include <nlist.h> 7*3162Stoy #include <sys/buf.h> 8*3162Stoy #include <sys/ubavar.h> 9*3162Stoy #include <sys/mbavar.h> 101155Sbill 111155Sbill struct nlist nl[] = { 121448Sbill #define X_CPTIME 0 131448Sbill { "_cp_time" }, 141448Sbill #define X_RATE 1 151155Sbill { "_rate" }, 161448Sbill #define X_TOTAL 2 171155Sbill { "_total" }, 181448Sbill #define X_DEFICIT 3 191155Sbill { "_deficit" }, 201448Sbill #define X_FORKSTAT 4 211155Sbill { "_forkstat" }, 221448Sbill #define X_SUM 5 231155Sbill { "_sum" }, 241448Sbill #define X_FIRSTFREE 6 251155Sbill { "_firstfree" }, 261448Sbill #define X_MAXFREE 7 271155Sbill { "_maxfree" }, 281448Sbill #define X_BOOTIME 8 291155Sbill { "_bootime" }, 301448Sbill #define X_DKXFER 9 311448Sbill { "_dk_xfer" }, 32*3162Stoy #define X_MBDINIT 10 33*3162Stoy { "_mbdinit" }, 34*3162Stoy #define X_UBDINIT 11 35*3162Stoy { "_ubdinit" }, 36*3162Stoy #define X_REC 12 371155Sbill { "_rectime" }, 38*3162Stoy #define X_PGIN 13 391155Sbill { "_pgintime" }, 40*3162Stoy #define X_HZ 14 41*3162Stoy { "_hz" }, 421155Sbill { 0 }, 431155Sbill }; 441155Sbill 45*3162Stoy char dr_name[DK_NDRIVE][10]; 46*3162Stoy char dr_unit[DK_NDRIVE]; 471155Sbill double stat1(); 481155Sbill int firstfree, maxfree; 49*3162Stoy int hz; 501155Sbill struct 511155Sbill { 521155Sbill int busy; 531448Sbill long time[CPUSTATES]; 541448Sbill long xfer[DK_NDRIVE]; 551155Sbill struct vmmeter Rate; 561155Sbill struct vmtotal Total; 571155Sbill struct vmmeter Sum; 581155Sbill struct forkstat Forkstat; 591155Sbill unsigned rectime; 601155Sbill unsigned pgintime; 611155Sbill } s, s1, z; 621155Sbill #define rate s.Rate 631155Sbill #define total s.Total 641155Sbill #define sum s.Sum 651155Sbill #define forkstat s.Forkstat 661155Sbill 671155Sbill int zero; 681155Sbill int deficit; 691155Sbill double etime; 701155Sbill int mf; 711155Sbill 721155Sbill main(argc, argv) 731155Sbill char **argv; 741155Sbill { 751155Sbill time_t now; 761155Sbill int lines; 771155Sbill extern char *ctime(); 781155Sbill register i,j; 791155Sbill int iter, nintv; 801155Sbill time_t bootime; 811155Sbill double f1, f2; 821155Sbill long t; 831155Sbill extern char _sobuf[]; 841155Sbill 851155Sbill setbuf(stdout, _sobuf); 861155Sbill nlist("/vmunix", nl); 871155Sbill if(nl[0].n_type == 0) { 881155Sbill printf("no /vmunix namelist\n"); 891155Sbill exit(1); 901155Sbill } 911155Sbill mf = open("/dev/kmem", 0); 921155Sbill if(mf < 0) { 931155Sbill printf("cannot open /dev/kmem\n"); 941155Sbill exit(1); 951155Sbill } 961155Sbill iter = 0; 971155Sbill argc--, argv++; 981155Sbill while (argc>0 && argv[0][0]=='-') { 991155Sbill char *cp = *argv++; 1001155Sbill argc--; 1011155Sbill while (*++cp) switch (*cp) { 1021155Sbill 1031155Sbill case 't': 1041155Sbill dotimes(); 1051155Sbill exit(0); 1061155Sbill case 'z': 1071155Sbill close(mf); 1081155Sbill mf = open("/dev/kmem", 2); 1091155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 1101155Sbill write(mf, &z.Sum, sizeof z.Sum); 1111155Sbill exit(0); 1121155Sbill 1131155Sbill case 'f': 1141155Sbill doforkst(); 1151155Sbill exit(0); 1161155Sbill 1171155Sbill case 's': 1181155Sbill dosum(); 1191155Sbill exit(0); 1201155Sbill 1211155Sbill default: 1221155Sbill fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n"); 1231155Sbill exit(1); 1241155Sbill } 1251155Sbill } 1261155Sbill if(argc > 1) 1271155Sbill iter = atoi(argv[1]); 1281155Sbill lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0); 1291155Sbill read(mf, &firstfree, sizeof firstfree); 1301155Sbill lseek(mf, (long)nl[X_MAXFREE].n_value, 0); 1311155Sbill read(mf, &maxfree, sizeof maxfree); 1321155Sbill lseek(mf, (long)nl[X_BOOTIME].n_value, 0); 1331155Sbill read(mf, &bootime, sizeof bootime); 134*3162Stoy lseek(mf, (long)nl[X_HZ].n_value, 0); 135*3162Stoy read(mf, &hz, sizeof hz); 136*3162Stoy for (i = 0; i < DK_NDRIVE; i++) 137*3162Stoy { 138*3162Stoy strcpy(dr_name[i], "DK"); 139*3162Stoy dr_unit[i] = i; 140*3162Stoy } 141*3162Stoy read_names(); 1421155Sbill time(&now); 1431155Sbill nintv = now - bootime; 1441155Sbill if (nintv <= 0 || nintv > 60*60*24*365*10) { 1451155Sbill printf("Time makes no sense... namelist must be wrong.\n"); 1461155Sbill exit(1); 1471155Sbill } 1481155Sbill reprint: 1491155Sbill lines = 20; 1501155Sbill /* s1 = z; */ 1511155Sbill printf("\ 152*3162Stoy Procs Memory Page Swap %s %s %s %s Faults Cpu\n\ 153*3162Stoy R B W AVM FRE RE AT PI PO FR DE SR I O %-2d %-2d %-2d %-2d IN SY CS US SY ID\n\ 154*3162Stoy ", dr_name[0], dr_name[1], dr_name[2], dr_name[3], dr_unit[0], dr_unit[1], dr_unit[2], dr_unit[3]); 1551155Sbill loop: 1561448Sbill lseek(mf, (long)nl[X_CPTIME].n_value, 0); 1571448Sbill read(mf, s.time, sizeof s.time); 1581448Sbill lseek(mf, (long)nl[X_DKXFER].n_value, 0); 1591448Sbill read(mf, s.xfer, sizeof s.xfer); 1601155Sbill if (nintv != 1) { 1611155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 1621155Sbill read(mf, &rate, sizeof rate); 1631155Sbill } else { 1641155Sbill lseek(mf, (long)nl[X_RATE].n_value, 0); 1651155Sbill read(mf, &rate, sizeof rate); 1661155Sbill } 1671155Sbill lseek(mf, (long)nl[X_TOTAL].n_value, 0); 1681155Sbill read(mf, &total, sizeof total); 1691155Sbill lseek(mf, (long)nl[X_DEFICIT].n_value, 0); 1701155Sbill read(mf, &deficit, sizeof deficit); 1711448Sbill etime = 0; 1721155Sbill for (i=0; i < DK_NDRIVE; i++) { 1731448Sbill t = s.xfer[i]; 1741448Sbill s.xfer[i] -= s1.xfer[i]; 1751448Sbill s1.xfer[i] = t; 1761155Sbill } 1771155Sbill for (i=0; i < CPUSTATES; i++) { 1781448Sbill t = s.time[i]; 1791448Sbill s.time[i] -= s1.time[i]; 1801448Sbill s1.time[i] = t; 1811448Sbill etime += s.time[i]; 1821155Sbill } 1831155Sbill if(etime == 0.) 1841155Sbill etime = 1.; 185*3162Stoy printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw); 186*3162Stoy printf("%6d%5d", total.t_avm/2, total.t_free/2); 1871155Sbill printf("%4d%3d%3d", 1881155Sbill (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv, 1891155Sbill (rate.v_xsfrec+rate.v_xifrec)/nintv, rate.v_pgin/nintv); 1901155Sbill printf("%3d%3d%4d%4.1f%2d%2d", rate.v_pgout/nintv, 1911155Sbill rate.v_dfree/nintv, deficit/2, 1921155Sbill (60.0 * rate.v_scan) / (LOOPSIZ*nintv), 1931155Sbill rate.v_swpin/nintv, rate.v_swpout/nintv); 1941155Sbill etime /= 60.; 1951155Sbill printf(" "); 1961155Sbill for(i=0; i<4; i++) 1971155Sbill stats(i); 198*3162Stoy printf("%4d%4d", (rate.v_intr/nintv) - hz, rate.v_syscall/nintv); 1991155Sbill printf("%4d", rate.v_swtch/nintv); 2001155Sbill for(i=0; i<CPUSTATES; i++) { 2011155Sbill float f = stat1(i); 2021155Sbill if (i == 0) { /* US+NI */ 2031155Sbill i++; 2041155Sbill f += stat1(i); 2051155Sbill } 2061155Sbill printf("%3.0f", f); 2071155Sbill } 2081155Sbill printf("\n"); 2091155Sbill fflush(stdout); 2101155Sbill contin: 2111155Sbill nintv = 1; 2121155Sbill --iter; 2131155Sbill if(iter) 2141155Sbill if(argc > 0) { 2151155Sbill sleep(atoi(argv[0])); 2161155Sbill if (--lines <= 0) 2171155Sbill goto reprint; 2181155Sbill goto loop; 2191155Sbill } 2201155Sbill } 2211155Sbill 2221155Sbill dotimes() 2231155Sbill { 2241155Sbill 2251155Sbill lseek(mf, (long)nl[X_REC].n_value, 0); 2261155Sbill read(mf, &s.rectime, sizeof s.rectime); 2271155Sbill lseek(mf, (long)nl[X_PGIN].n_value, 0); 2281155Sbill read(mf, &s.pgintime, sizeof s.pgintime); 2291155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2301155Sbill read(mf, &sum, sizeof sum); 2311155Sbill printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime); 2321155Sbill printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec); 2331155Sbill printf("\n"); 2341155Sbill printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10); 2351155Sbill printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0)); 2361155Sbill } 2371155Sbill 2381155Sbill dosum() 2391155Sbill { 2401155Sbill 2411155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2421155Sbill read(mf, &sum, sizeof sum); 2431155Sbill printf("%9d swap ins\n", sum.v_swpin); 2441155Sbill printf("%9d swap outs\n", sum.v_swpout); 2451155Sbill printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE); 2461155Sbill printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE); 2471155Sbill printf("%9d total address trans. faults taken\n", sum.v_faults); 2481155Sbill printf("%9d page ins\n", sum.v_pgin); 2491155Sbill printf("%9d page outs\n", sum.v_pgout); 2501155Sbill printf("%9d total reclaims\n", sum.v_pgrec); 2511155Sbill printf("%9d reclaims from free list\n", sum.v_pgfrec); 2521155Sbill printf("%9d intransit blocking page faults\n", sum.v_intrans); 2531155Sbill printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE); 2541155Sbill printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE); 2551155Sbill printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE); 2561155Sbill printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE); 2571155Sbill printf("%9d swap text pages found in free list\n", sum.v_xsfrec); 2581155Sbill printf("%9d inode text pages found in free list\n", sum.v_xifrec); 2591155Sbill printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE); 2601155Sbill printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE); 2611155Sbill printf("%9d pages examined by the clock daemon\n", sum.v_scan); 2621155Sbill printf("%9d revolutions of the clock hand\n", sum.v_rev); 2631155Sbill printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE); 2641155Sbill printf("%9d cpu context switches\n", sum.v_swtch); 2651155Sbill printf("%9d device interrupts\n", sum.v_intr); 2661155Sbill printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma); 2671155Sbill printf("%9d traps\n", sum.v_trap); 2681155Sbill printf("%9d system calls\n", sum.v_syscall); 2691155Sbill } 2701155Sbill 2711155Sbill 2721155Sbill doforkst() 2731155Sbill { 2741155Sbill 2751155Sbill lseek(mf, (long)nl[X_FORKSTAT].n_value, 0); 2761155Sbill read(mf, &forkstat, sizeof forkstat); 2771155Sbill printf("%d forks, %d pages, average=%.2f\n", 2781155Sbill forkstat.cntfork, forkstat.sizfork, 2791155Sbill (float) forkstat.sizfork / forkstat.cntfork); 2801155Sbill printf("%d vforks, %d pages, average=%.2f\n", 2811155Sbill forkstat.cntvfork, forkstat.sizvfork, 2821155Sbill (float)forkstat.sizvfork / forkstat.cntvfork); 2831155Sbill } 2841155Sbill 2851155Sbill stats(dn) 2861155Sbill { 2871155Sbill 2881155Sbill if (dn >= DK_NDRIVE) { 2891155Sbill printf(" 0"); 2901155Sbill return; 2911155Sbill } 2921448Sbill printf("%3.0f", s.xfer[dn]/etime); 2931155Sbill } 2941155Sbill 2951155Sbill double 2961155Sbill stat1(row) 2971155Sbill { 2981448Sbill double t; 2991448Sbill register i; 3001155Sbill 3011155Sbill t = 0; 3021155Sbill for(i=0; i<CPUSTATES; i++) 3031448Sbill t += s.time[i]; 3041448Sbill if(t == 0.) 3051448Sbill t = 1.; 3061448Sbill return(s.time[row]*100./t); 3071155Sbill } 3081155Sbill 3091155Sbill pct(top, bot) 3101155Sbill { 3111155Sbill 3121155Sbill if (bot == 0) 3131155Sbill return (0); 3141155Sbill return ((top * 100) / bot); 3151155Sbill } 316*3162Stoy 317*3162Stoy /* 318*3162Stoy * Read the drive names out of kmem. 319*3162Stoy * ARGH ARGH ARGH ARGH !!!!!!!!!!!! 320*3162Stoy */ 321*3162Stoy 322*3162Stoy #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); 323*3162Stoy read_names() 324*3162Stoy { 325*3162Stoy struct mba_device mdev; 326*3162Stoy register struct mba_device *mp; 327*3162Stoy struct mba_driver mdrv; 328*3162Stoy short two_char; 329*3162Stoy char *cp = (char *) &two_char; 330*3162Stoy struct uba_device udev, *up; 331*3162Stoy struct uba_driver udrv; 332*3162Stoy 333*3162Stoy mp = (struct mba_device *) nl[X_MBDINIT].n_value; 334*3162Stoy up = (struct uba_device *) nl[X_UBDINIT].n_value; 335*3162Stoy if (mp == 0 || up == 0) 336*3162Stoy { 337*3162Stoy fprintf(stderr, "iostat: Disk init info not in namelist\n"); 338*3162Stoy exit(1); 339*3162Stoy } 340*3162Stoy while(1) 341*3162Stoy { 342*3162Stoy steal(mp++, mdev); 343*3162Stoy if (mdev.mi_driver == 0) 344*3162Stoy break; 345*3162Stoy if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 346*3162Stoy continue; 347*3162Stoy steal(mdev.mi_driver, mdrv); 348*3162Stoy steal(mdrv.md_dname, two_char); 349*3162Stoy sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]); 350*3162Stoy dr_unit[mdev.mi_dk] = mdev.mi_unit; 351*3162Stoy } 352*3162Stoy while(1) 353*3162Stoy { 354*3162Stoy steal(up++, udev); 355*3162Stoy if (udev.ui_driver == 0) 356*3162Stoy break; 357*3162Stoy if (udev.ui_dk < 0 || udev.ui_alive == 0) 358*3162Stoy continue; 359*3162Stoy steal(udev.ui_driver, udrv); 360*3162Stoy steal(udrv.ud_dname, two_char); 361*3162Stoy sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]); 362*3162Stoy dr_unit[udev.ui_dk] = udev.ui_unit; 363*3162Stoy } 364*3162Stoy } 365