110826Ssam #ifndef lint 2*17262Smckusick static char *sccsid = "@(#)vmstat.c 4.15 (Berkeley) 10/17/84"; 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> 1115807Smckusick #include <sys/dir.h> 12*17262Smckusick #include <sys/namei.h> 1310826Ssam #ifdef vax 149249Ssam #include <vaxuba/ubavar.h> 159249Ssam #include <vaxmba/mbavar.h> 1610826Ssam #endif 1710826Ssam #ifdef sun 1810826Ssam #include <sundev/mbvar.h> 1910826Ssam #endif 201155Sbill 211155Sbill struct nlist nl[] = { 221448Sbill #define X_CPTIME 0 231448Sbill { "_cp_time" }, 241448Sbill #define X_RATE 1 251155Sbill { "_rate" }, 261448Sbill #define X_TOTAL 2 271155Sbill { "_total" }, 281448Sbill #define X_DEFICIT 3 291155Sbill { "_deficit" }, 301448Sbill #define X_FORKSTAT 4 311155Sbill { "_forkstat" }, 321448Sbill #define X_SUM 5 331155Sbill { "_sum" }, 341448Sbill #define X_FIRSTFREE 6 351155Sbill { "_firstfree" }, 361448Sbill #define X_MAXFREE 7 371155Sbill { "_maxfree" }, 389249Ssam #define X_BOOTTIME 8 399249Ssam { "_boottime" }, 401448Sbill #define X_DKXFER 9 411448Sbill { "_dk_xfer" }, 4210826Ssam #define X_REC 10 431155Sbill { "_rectime" }, 4410826Ssam #define X_PGIN 11 451155Sbill { "_pgintime" }, 4610826Ssam #define X_HZ 12 473162Stoy { "_hz" }, 4815266Ssam #define X_PHZ 13 4915266Ssam { "_phz" }, 5015807Smckusick #define X_NCHSTATS 14 5115807Smckusick { "_nchstats" }, 52*17262Smckusick #define X_INTRNAMES 15 53*17262Smckusick { "_intrnames" }, 54*17262Smckusick #define X_EINTRNAMES 16 55*17262Smckusick { "_eintrnames" }, 56*17262Smckusick #define X_INTRCNT 17 57*17262Smckusick { "_intrcnt" }, 58*17262Smckusick #define X_EINTRCNT 18 59*17262Smckusick { "_eintrcnt" }, 6010826Ssam #ifdef vax 61*17262Smckusick #define X_MBDINIT 19 6210826Ssam { "_mbdinit" }, 63*17262Smckusick #define X_UBDINIT 20 6410826Ssam { "_ubdinit" }, 6510826Ssam #endif 6610826Ssam { "" }, 671155Sbill }; 681155Sbill 693162Stoy char dr_name[DK_NDRIVE][10]; 703162Stoy char dr_unit[DK_NDRIVE]; 711155Sbill double stat1(); 721155Sbill int firstfree, maxfree; 733162Stoy int hz; 7415266Ssam int phz; 7515266Ssam int HZ; 7615266Ssam #ifdef sun 7715266Ssam #define INTS(x) (x) 7815266Ssam #endif 7915266Ssam #ifdef vax 8015266Ssam #define INTS(x) ((x) - (hz + phz)) 8115266Ssam #endif 8215266Ssam 831155Sbill struct 841155Sbill { 851155Sbill int busy; 861448Sbill long time[CPUSTATES]; 871448Sbill long xfer[DK_NDRIVE]; 881155Sbill struct vmmeter Rate; 891155Sbill struct vmtotal Total; 901155Sbill struct vmmeter Sum; 911155Sbill struct forkstat Forkstat; 921155Sbill unsigned rectime; 931155Sbill unsigned pgintime; 941155Sbill } s, s1, z; 951155Sbill #define rate s.Rate 961155Sbill #define total s.Total 971155Sbill #define sum s.Sum 981155Sbill #define forkstat s.Forkstat 991155Sbill 10010826Ssam struct vmmeter osum; 1011155Sbill int zero; 1021155Sbill int deficit; 1031155Sbill double etime; 1041155Sbill int mf; 105*17262Smckusick time_t now, boottime; 106*17262Smckusick int printhdr(); 1071155Sbill 1081155Sbill main(argc, argv) 10910826Ssam int argc; 11010826Ssam char **argv; 1111155Sbill { 1121155Sbill int lines; 1131155Sbill extern char *ctime(); 1141155Sbill register i,j; 115*17262Smckusick int iter, nintv, iflag = 0; 1161155Sbill double f1, f2; 1171155Sbill long t; 1181155Sbill 1191155Sbill nlist("/vmunix", nl); 1201155Sbill if(nl[0].n_type == 0) { 1211155Sbill printf("no /vmunix namelist\n"); 1221155Sbill exit(1); 1231155Sbill } 1241155Sbill mf = open("/dev/kmem", 0); 1251155Sbill if(mf < 0) { 1261155Sbill printf("cannot open /dev/kmem\n"); 1271155Sbill exit(1); 1281155Sbill } 1291155Sbill iter = 0; 1301155Sbill argc--, argv++; 1311155Sbill while (argc>0 && argv[0][0]=='-') { 1321155Sbill char *cp = *argv++; 1331155Sbill argc--; 1341155Sbill while (*++cp) switch (*cp) { 1351155Sbill 1361155Sbill case 't': 1371155Sbill dotimes(); 1381155Sbill exit(0); 13910826Ssam 1401155Sbill case 'z': 1411155Sbill close(mf); 1421155Sbill mf = open("/dev/kmem", 2); 1431155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 1441155Sbill write(mf, &z.Sum, sizeof z.Sum); 1451155Sbill exit(0); 1461155Sbill 1471155Sbill case 'f': 1481155Sbill doforkst(); 1491155Sbill exit(0); 1501155Sbill 1511155Sbill case 's': 1521155Sbill dosum(); 1531155Sbill exit(0); 1541155Sbill 155*17262Smckusick case 'i': 156*17262Smckusick iflag++; 157*17262Smckusick break; 158*17262Smckusick 1591155Sbill default: 160*17262Smckusick fprintf(stderr, "usage: vmstat [ -fsi ] [ interval ] [ count]\n"); 1611155Sbill exit(1); 1621155Sbill } 1631155Sbill } 1641155Sbill if(argc > 1) 1651155Sbill iter = atoi(argv[1]); 1661155Sbill lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0); 1671155Sbill read(mf, &firstfree, sizeof firstfree); 1681155Sbill lseek(mf, (long)nl[X_MAXFREE].n_value, 0); 1691155Sbill read(mf, &maxfree, sizeof maxfree); 1709249Ssam lseek(mf, (long)nl[X_BOOTTIME].n_value, 0); 1719249Ssam read(mf, &boottime, sizeof boottime); 1723162Stoy lseek(mf, (long)nl[X_HZ].n_value, 0); 1733162Stoy read(mf, &hz, sizeof hz); 17415266Ssam lseek(mf, (long)nl[X_PHZ].n_value, 0); 17515266Ssam read(mf, &phz, sizeof phz); 17615266Ssam HZ = phz ? phz : hz; 1773612Sroot for (i = 0; i < DK_NDRIVE; i++) { 1783212Swnj strcpy(dr_name[i], "xx"); 1793162Stoy dr_unit[i] = i; 1803162Stoy } 1813162Stoy read_names(); 1821155Sbill time(&now); 1839249Ssam nintv = now - boottime; 1841155Sbill if (nintv <= 0 || nintv > 60*60*24*365*10) { 1851155Sbill printf("Time makes no sense... namelist must be wrong.\n"); 1861155Sbill exit(1); 1871155Sbill } 188*17262Smckusick if (iflag) { 189*17262Smckusick dointr(nintv); 190*17262Smckusick exit(0); 191*17262Smckusick } 192*17262Smckusick signal(SIGCONT, printhdr); 1931155Sbill reprint: 1941155Sbill lines = 20; 1951155Sbill /* s1 = z; */ 196*17262Smckusick printhdr(); 1971155Sbill loop: 1981448Sbill lseek(mf, (long)nl[X_CPTIME].n_value, 0); 1991448Sbill read(mf, s.time, sizeof s.time); 2001448Sbill lseek(mf, (long)nl[X_DKXFER].n_value, 0); 2011448Sbill read(mf, s.xfer, sizeof s.xfer); 2021155Sbill if (nintv != 1) { 2031155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2041155Sbill read(mf, &rate, sizeof rate); 2051155Sbill } else { 2061155Sbill lseek(mf, (long)nl[X_RATE].n_value, 0); 2071155Sbill read(mf, &rate, sizeof rate); 2081155Sbill } 2091155Sbill lseek(mf, (long)nl[X_TOTAL].n_value, 0); 2101155Sbill read(mf, &total, sizeof total); 21110826Ssam osum = sum; 21210826Ssam lseek(mf, (long)nl[X_SUM].n_value, 0); 21310826Ssam read(mf, &sum, sizeof sum); 2141155Sbill lseek(mf, (long)nl[X_DEFICIT].n_value, 0); 2151155Sbill read(mf, &deficit, sizeof deficit); 2161448Sbill etime = 0; 2171155Sbill for (i=0; i < DK_NDRIVE; i++) { 2181448Sbill t = s.xfer[i]; 2191448Sbill s.xfer[i] -= s1.xfer[i]; 2201448Sbill s1.xfer[i] = t; 2211155Sbill } 2221155Sbill for (i=0; i < CPUSTATES; i++) { 2231448Sbill t = s.time[i]; 2241448Sbill s.time[i] -= s1.time[i]; 2251448Sbill s1.time[i] = t; 2261448Sbill etime += s.time[i]; 2271155Sbill } 2281155Sbill if(etime == 0.) 2291155Sbill etime = 1.; 2303162Stoy printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw); 23110826Ssam #define pgtok(a) ((a)*NBPG/1024) 23210826Ssam printf("%6d%5d", pgtok(total.t_avm), pgtok(total.t_free)); 23315266Ssam printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv, 23415266Ssam (rate.v_xsfrec+rate.v_xifrec)/nintv); 23510826Ssam printf("%4d", pgtok(rate.v_pgpgin)/nintv); 23610826Ssam printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv, 23710826Ssam pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv); 23815266Ssam etime /= (float) HZ; 2391155Sbill for(i=0; i<4; i++) 2401155Sbill stats(i); 24115266Ssam printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv, 24215266Ssam rate.v_swtch/nintv); 2431155Sbill for(i=0; i<CPUSTATES; i++) { 2441155Sbill float f = stat1(i); 2451155Sbill if (i == 0) { /* US+NI */ 2461155Sbill i++; 2471155Sbill f += stat1(i); 2481155Sbill } 2491155Sbill printf("%3.0f", f); 2501155Sbill } 2511155Sbill printf("\n"); 2521155Sbill fflush(stdout); 2531155Sbill contin: 2541155Sbill nintv = 1; 2551155Sbill --iter; 2561155Sbill if(iter) 2571155Sbill if(argc > 0) { 2581155Sbill sleep(atoi(argv[0])); 2591155Sbill if (--lines <= 0) 2601155Sbill goto reprint; 2611155Sbill goto loop; 2621155Sbill } 2631155Sbill } 2641155Sbill 265*17262Smckusick printhdr() 266*17262Smckusick { 267*17262Smckusick printf("\ 268*17262Smckusick procs memory page disk faults cpu\n\ 269*17262Smckusick 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", 270*17262Smckusick 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]); 271*17262Smckusick } 272*17262Smckusick 2731155Sbill dotimes() 2741155Sbill { 2751155Sbill 2761155Sbill lseek(mf, (long)nl[X_REC].n_value, 0); 2771155Sbill read(mf, &s.rectime, sizeof s.rectime); 2781155Sbill lseek(mf, (long)nl[X_PGIN].n_value, 0); 2791155Sbill read(mf, &s.pgintime, sizeof s.pgintime); 2801155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2811155Sbill read(mf, &sum, sizeof sum); 2821155Sbill printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime); 2831155Sbill printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec); 2841155Sbill printf("\n"); 2851155Sbill printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10); 2861155Sbill printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0)); 2871155Sbill } 2881155Sbill 2891155Sbill dosum() 2901155Sbill { 29115807Smckusick struct nchstats statbuf; 29215807Smckusick long nchtotal; 2931155Sbill 2941155Sbill lseek(mf, (long)nl[X_SUM].n_value, 0); 2951155Sbill read(mf, &sum, sizeof sum); 2961155Sbill printf("%9d swap ins\n", sum.v_swpin); 2971155Sbill printf("%9d swap outs\n", sum.v_swpout); 2981155Sbill printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE); 2991155Sbill printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE); 3001155Sbill printf("%9d total address trans. faults taken\n", sum.v_faults); 3011155Sbill printf("%9d page ins\n", sum.v_pgin); 3021155Sbill printf("%9d page outs\n", sum.v_pgout); 3033612Sroot printf("%9d pages paged in\n", sum.v_pgpgin); 3043612Sroot printf("%9d pages paged out\n", sum.v_pgpgout); 3053612Sroot printf("%9d sequential process pages freed\n", sum.v_seqfree); 30612830Ssam printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec, 30712830Ssam (sum.v_fastpgrec * 100) / (sum.v_pgrec == 0 ? 1 : sum.v_pgrec)); 3081155Sbill printf("%9d reclaims from free list\n", sum.v_pgfrec); 3091155Sbill printf("%9d intransit blocking page faults\n", sum.v_intrans); 3101155Sbill printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE); 3111155Sbill printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE); 3121155Sbill printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE); 3131155Sbill printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE); 3141155Sbill printf("%9d swap text pages found in free list\n", sum.v_xsfrec); 3151155Sbill printf("%9d inode text pages found in free list\n", sum.v_xifrec); 3161155Sbill printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE); 3171155Sbill printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE); 3181155Sbill printf("%9d pages examined by the clock daemon\n", sum.v_scan); 3191155Sbill printf("%9d revolutions of the clock hand\n", sum.v_rev); 3201155Sbill printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE); 3211155Sbill printf("%9d cpu context switches\n", sum.v_swtch); 3221155Sbill printf("%9d device interrupts\n", sum.v_intr); 323*17262Smckusick printf("%9d software interrupts\n", sum.v_soft); 3241155Sbill printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma); 3251155Sbill printf("%9d traps\n", sum.v_trap); 3261155Sbill printf("%9d system calls\n", sum.v_syscall); 32715807Smckusick lseek(mf, (long)nl[X_NCHSTATS].n_value, 0); 32815807Smckusick read(mf, &statbuf, sizeof statbuf); 32915807Smckusick nchtotal = statbuf.ncs_goodhits + statbuf.ncs_badhits + 33016586Ssam statbuf.ncs_falsehits + statbuf.ncs_miss + statbuf.ncs_long; 33115807Smckusick printf("%9d total name lookups", nchtotal); 33216586Ssam #define nz(x) ((x) ? (x) : 1) 33315807Smckusick printf(" (cache hits %d%% system %d%% per-process)\n", 33416586Ssam statbuf.ncs_goodhits * 100 / nz(nchtotal), 33516586Ssam statbuf.ncs_pass2 * 100 / nz(nchtotal)); 33616586Ssam printf("%9s badhits %d, falsehits %d, toolong %d\n", "", 33716586Ssam statbuf.ncs_badhits, statbuf.ncs_falsehits, statbuf.ncs_long); 3381155Sbill } 3391155Sbill 3401155Sbill doforkst() 3411155Sbill { 3421155Sbill 3431155Sbill lseek(mf, (long)nl[X_FORKSTAT].n_value, 0); 3441155Sbill read(mf, &forkstat, sizeof forkstat); 3451155Sbill printf("%d forks, %d pages, average=%.2f\n", 3461155Sbill forkstat.cntfork, forkstat.sizfork, 3471155Sbill (float) forkstat.sizfork / forkstat.cntfork); 3481155Sbill printf("%d vforks, %d pages, average=%.2f\n", 3491155Sbill forkstat.cntvfork, forkstat.sizvfork, 3501155Sbill (float)forkstat.sizvfork / forkstat.cntvfork); 3511155Sbill } 3521155Sbill 3531155Sbill stats(dn) 3541155Sbill { 3551155Sbill 3561155Sbill if (dn >= DK_NDRIVE) { 3571155Sbill printf(" 0"); 3581155Sbill return; 3591155Sbill } 3601448Sbill printf("%3.0f", s.xfer[dn]/etime); 3611155Sbill } 3621155Sbill 3631155Sbill double 3641155Sbill stat1(row) 3651155Sbill { 3661448Sbill double t; 3671448Sbill register i; 3681155Sbill 3691155Sbill t = 0; 3701155Sbill for(i=0; i<CPUSTATES; i++) 3711448Sbill t += s.time[i]; 3721448Sbill if(t == 0.) 3731448Sbill t = 1.; 3741448Sbill return(s.time[row]*100./t); 3751155Sbill } 3761155Sbill 3771155Sbill pct(top, bot) 3781155Sbill { 3791155Sbill 3801155Sbill if (bot == 0) 3811155Sbill return (0); 3821155Sbill return ((top * 100) / bot); 3831155Sbill } 3843162Stoy 385*17262Smckusick dointr(nintv) 386*17262Smckusick { 387*17262Smckusick int nintr, inttotal; 388*17262Smckusick long *intrcnt; 389*17262Smckusick char *intrname, *malloc(); 390*17262Smckusick 391*17262Smckusick nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long); 392*17262Smckusick intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value - 393*17262Smckusick nl[X_INTRCNT].n_value); 394*17262Smckusick intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value); 395*17262Smckusick if (intrcnt == NULL || intrname == NULL) { 396*17262Smckusick fprintf(stderr, "vmstat: out of memory\n"); 397*17262Smckusick exit(9); 398*17262Smckusick } 399*17262Smckusick lseek(mf, (long)nl[X_INTRCNT].n_value, 0); 400*17262Smckusick read(mf, intrcnt, nintr * sizeof (long)); 401*17262Smckusick lseek(mf, (long)nl[X_INTRNAMES].n_value, 0); 402*17262Smckusick read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value); 403*17262Smckusick printf("interrupt total rate\n"); 404*17262Smckusick inttotal = 0; 405*17262Smckusick while (nintr--) { 406*17262Smckusick if (*intrcnt) 407*17262Smckusick printf("%-12s %8ld %8ld\n", intrname, 408*17262Smckusick *intrcnt, *intrcnt / nintv); 409*17262Smckusick intrname += strlen(intrname) + 1; 410*17262Smckusick inttotal += *intrcnt++; 411*17262Smckusick } 412*17262Smckusick printf("Total %8ld %8ld\n", inttotal, inttotal / nintv); 413*17262Smckusick } 414*17262Smckusick 41510826Ssam #define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var); 4163162Stoy /* 4173162Stoy * Read the drive names out of kmem. 4183162Stoy */ 41910826Ssam #ifdef vax 4203162Stoy read_names() 4213162Stoy { 4223162Stoy struct mba_device mdev; 4233162Stoy register struct mba_device *mp; 4243162Stoy struct mba_driver mdrv; 4253162Stoy short two_char; 4263162Stoy char *cp = (char *) &two_char; 4273162Stoy struct uba_device udev, *up; 4283162Stoy struct uba_driver udrv; 4293162Stoy 4303162Stoy mp = (struct mba_device *) nl[X_MBDINIT].n_value; 4313162Stoy up = (struct uba_device *) nl[X_UBDINIT].n_value; 4323492Sroot if (up == 0) { 43310826Ssam fprintf(stderr, "vmstat: Disk init info not in namelist\n"); 4343162Stoy exit(1); 4353162Stoy } 4363492Sroot if (mp) for (;;) { 4373162Stoy steal(mp++, mdev); 4383162Stoy if (mdev.mi_driver == 0) 4393162Stoy break; 4403162Stoy if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 4413162Stoy continue; 4423162Stoy steal(mdev.mi_driver, mdrv); 4433162Stoy steal(mdrv.md_dname, two_char); 4443162Stoy sprintf(dr_name[mdev.mi_dk], "%c%c", cp[0], cp[1]); 4453162Stoy dr_unit[mdev.mi_dk] = mdev.mi_unit; 4463162Stoy } 4473492Sroot for (;;) { 4483162Stoy steal(up++, udev); 4493162Stoy if (udev.ui_driver == 0) 4503162Stoy break; 4513162Stoy if (udev.ui_dk < 0 || udev.ui_alive == 0) 4523162Stoy continue; 4533162Stoy steal(udev.ui_driver, udrv); 4543162Stoy steal(udrv.ud_dname, two_char); 4553162Stoy sprintf(dr_name[udev.ui_dk], "%c%c", cp[0], cp[1]); 4563162Stoy dr_unit[udev.ui_dk] = udev.ui_unit; 4573162Stoy } 4583162Stoy } 45910826Ssam #endif 46010826Ssam 46110826Ssam #ifdef sun 46210826Ssam read_names() 46310826Ssam { 46410826Ssam struct mb_device mdev; 46510826Ssam register struct mb_device *mp; 46610826Ssam struct mb_driver mdrv; 46710826Ssam short two_char; 46810826Ssam char *cp = (char *) &two_char; 46910826Ssam 47010826Ssam mp = (struct mb_device *) nl[X_MBDINIT].n_value; 47110826Ssam if (mp == 0) { 47210826Ssam fprintf(stderr, "iostat: Disk init info not in namelist\n"); 47310826Ssam exit(1); 47410826Ssam } 47510826Ssam for (;;) { 47610826Ssam steal(mp++, mdev); 47710826Ssam if (mdev.md_driver == 0) 47810826Ssam break; 47910826Ssam if (mdev.md_dk < 0 || mdev.md_alive == 0) 48010826Ssam continue; 48110826Ssam steal(mdev.md_driver, mdrv); 48210826Ssam steal(mdrv.mdr_dname, two_char); 48310826Ssam sprintf(dr_name[mdev.md_dk], "%c%c%d", cp[0], cp[1]); 48410826Ssam dr_unit[mdev.md_dk] = mdev.md_unit; 48510826Ssam } 48610826Ssam } 48710826Ssam #endif 488