121585Sdist /* 236580Sbostic * Copyright (c) 1980 The Regents of the University of California. 336580Sbostic * All rights reserved. 436580Sbostic * 536580Sbostic * Redistribution and use in source and binary forms are permitted 636580Sbostic * provided that the above copyright notice and this paragraph are 736580Sbostic * duplicated in all such forms and that any documentation, 836580Sbostic * advertising materials, and other materials related to such 936580Sbostic * distribution and use acknowledge that the software was developed 1036580Sbostic * by the University of California, Berkeley. The name of the 1136580Sbostic * University may not be used to endorse or promote products derived 1236580Sbostic * from this software without specific prior written permission. 1336580Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1436580Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1536580Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621585Sdist */ 1721585Sdist 1810826Ssam #ifndef lint 1921585Sdist char copyright[] = 2036580Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 2121585Sdist All rights reserved.\n"; 2236580Sbostic #endif /* not lint */ 2310826Ssam 2421585Sdist #ifndef lint 25*38263Smckusick static char sccsid[] = "@(#)vmstat.c 5.15 (Berkeley) 06/08/89"; 2636580Sbostic #endif /* not lint */ 2721585Sdist 281155Sbill #include <sys/param.h> 2918761Ssam #include <sys/file.h> 301155Sbill #include <sys/vm.h> 3129664Ssam #include <sys/dkstat.h> 323162Stoy #include <sys/buf.h> 3315807Smckusick #include <sys/dir.h> 34*38263Smckusick #include <sys/time.h> 35*38263Smckusick #include <sys/vnode.h> 36*38263Smckusick #include <ufs/inode.h> 3717262Smckusick #include <sys/namei.h> 3825708Ssam #include <sys/text.h> 3933610Smckusick #include <sys/malloc.h> 4037912Sbostic #include <stdio.h> 4137912Sbostic #include <ctype.h> 4237912Sbostic #include <nlist.h> 4337912Sbostic #include <paths.h> 441155Sbill 451155Sbill struct nlist nl[] = { 461448Sbill #define X_CPTIME 0 471448Sbill { "_cp_time" }, 481448Sbill #define X_RATE 1 491155Sbill { "_rate" }, 501448Sbill #define X_TOTAL 2 511155Sbill { "_total" }, 521448Sbill #define X_DEFICIT 3 531155Sbill { "_deficit" }, 541448Sbill #define X_FORKSTAT 4 551155Sbill { "_forkstat" }, 561448Sbill #define X_SUM 5 571155Sbill { "_sum" }, 581448Sbill #define X_FIRSTFREE 6 591155Sbill { "_firstfree" }, 601448Sbill #define X_MAXFREE 7 611155Sbill { "_maxfree" }, 629249Ssam #define X_BOOTTIME 8 639249Ssam { "_boottime" }, 641448Sbill #define X_DKXFER 9 651448Sbill { "_dk_xfer" }, 6610826Ssam #define X_REC 10 671155Sbill { "_rectime" }, 6810826Ssam #define X_PGIN 11 691155Sbill { "_pgintime" }, 7010826Ssam #define X_HZ 12 713162Stoy { "_hz" }, 7218761Ssam #define X_PHZ 13 7315266Ssam { "_phz" }, 7415807Smckusick #define X_NCHSTATS 14 7515807Smckusick { "_nchstats" }, 7617262Smckusick #define X_INTRNAMES 15 7717262Smckusick { "_intrnames" }, 7817262Smckusick #define X_EINTRNAMES 16 7917262Smckusick { "_eintrnames" }, 8017262Smckusick #define X_INTRCNT 17 8117262Smckusick { "_intrcnt" }, 8217262Smckusick #define X_EINTRCNT 18 8317262Smckusick { "_eintrcnt" }, 8418761Ssam #define X_DK_NDRIVE 19 8518761Ssam { "_dk_ndrive" }, 8625512Ssam #define X_XSTATS 20 8725512Ssam { "_xstats" }, 8833610Smckusick #define X_KMEMSTAT 21 8933610Smckusick { "_kmemstats" }, 9033610Smckusick #define X_KMEMBUCKETS 22 9133610Smckusick { "_bucket" }, 9210826Ssam #ifdef vax 9325708Ssam #define X_MBDINIT (X_XSTATS+1) 9410826Ssam { "_mbdinit" }, 9525708Ssam #define X_UBDINIT (X_XSTATS+2) 9610826Ssam { "_ubdinit" }, 9710826Ssam #endif 9825708Ssam #ifdef tahoe 9925708Ssam #define X_VBDINIT (X_XSTATS+1) 10025708Ssam { "_vbdinit" }, 10125960Ssam #define X_CKEYSTATS (X_XSTATS+2) 10225960Ssam { "_ckeystats" }, 10325960Ssam #define X_DKEYSTATS (X_XSTATS+3) 10425960Ssam { "_dkeystats" }, 10525708Ssam #endif 10610826Ssam { "" }, 1071155Sbill }; 1081155Sbill 10918761Ssam char **dr_name; 11018761Ssam int *dr_select; 11118761Ssam int dk_ndrive; 11218761Ssam int ndrives = 0; 11318761Ssam #ifdef vax 11418761Ssam char *defdrives[] = { "hp0", "hp1", "hp2", 0 }; 11518761Ssam #else 11618761Ssam char *defdrives[] = { 0 }; 11718761Ssam #endif 1181155Sbill double stat1(); 1191155Sbill int firstfree, maxfree; 1203162Stoy int hz; 12115266Ssam int phz; 12215266Ssam int HZ; 12318761Ssam 12418761Ssam struct { 1251155Sbill int busy; 1261448Sbill long time[CPUSTATES]; 12718761Ssam long *xfer; 1281155Sbill struct vmmeter Rate; 1291155Sbill struct vmtotal Total; 1301155Sbill struct vmmeter Sum; 1311155Sbill struct forkstat Forkstat; 1321155Sbill unsigned rectime; 1331155Sbill unsigned pgintime; 1341155Sbill } s, s1, z; 1351155Sbill #define rate s.Rate 1361155Sbill #define total s.Total 1371155Sbill #define sum s.Sum 1381155Sbill #define forkstat s.Forkstat 1391155Sbill 14010826Ssam struct vmmeter osum; 1411155Sbill int deficit; 1421155Sbill double etime; 1431155Sbill int mf; 14417262Smckusick time_t now, boottime; 14517262Smckusick int printhdr(); 14618768Ssam int lines = 1; 1471155Sbill 14829664Ssam #define INTS(x) ((x) - (hz + phz)) 14929664Ssam 1501155Sbill main(argc, argv) 15110826Ssam int argc; 15210826Ssam char **argv; 1531155Sbill { 1541155Sbill extern char *ctime(); 15529664Ssam register i; 15617262Smckusick int iter, nintv, iflag = 0; 1571155Sbill long t; 15829664Ssam char *arg, **cp, buf[BUFSIZ]; 1591155Sbill 16037912Sbostic nlist(_PATH_UNIX, nl); 1611155Sbill if(nl[0].n_type == 0) { 16237912Sbostic fprintf(stderr, "vmstat: no %s namelist\n", _PATH_UNIX); 1631155Sbill exit(1); 1641155Sbill } 16537912Sbostic mf = open(_PATH_KMEM, 0); 1661155Sbill if(mf < 0) { 16737912Sbostic fprintf(stderr, "vmstat: cannot open %s\n", _PATH_KMEM); 1681155Sbill exit(1); 1691155Sbill } 1701155Sbill iter = 0; 1711155Sbill argc--, argv++; 1721155Sbill while (argc>0 && argv[0][0]=='-') { 1731155Sbill char *cp = *argv++; 1741155Sbill argc--; 1751155Sbill while (*++cp) switch (*cp) { 1761155Sbill 1771155Sbill case 't': 1781155Sbill dotimes(); 1791155Sbill exit(0); 18010826Ssam 1811155Sbill case 'z': 1821155Sbill close(mf); 18337912Sbostic mf = open(_PATH_KMEM, 2); 18418761Ssam lseek(mf, (long)nl[X_SUM].n_value, L_SET); 1851155Sbill write(mf, &z.Sum, sizeof z.Sum); 1861155Sbill exit(0); 1871155Sbill 1881155Sbill case 'f': 1891155Sbill doforkst(); 1901155Sbill exit(0); 1911155Sbill 19233610Smckusick case 'm': 19333610Smckusick domem(); 19433610Smckusick exit(0); 19533610Smckusick 1961155Sbill case 's': 1971155Sbill dosum(); 1981155Sbill exit(0); 1991155Sbill 20017262Smckusick case 'i': 20117262Smckusick iflag++; 20217262Smckusick break; 20317262Smckusick 2041155Sbill default: 20518761Ssam fprintf(stderr, 20633610Smckusick "usage: vmstat [ -fsim ] [ interval ] [ count]\n"); 2071155Sbill exit(1); 2081155Sbill } 2091155Sbill } 21018761Ssam lseek(mf, (long)nl[X_FIRSTFREE].n_value, L_SET); 2111155Sbill read(mf, &firstfree, sizeof firstfree); 21218761Ssam lseek(mf, (long)nl[X_MAXFREE].n_value, L_SET); 2131155Sbill read(mf, &maxfree, sizeof maxfree); 21418761Ssam lseek(mf, (long)nl[X_BOOTTIME].n_value, L_SET); 2159249Ssam read(mf, &boottime, sizeof boottime); 21618761Ssam lseek(mf, (long)nl[X_HZ].n_value, L_SET); 2173162Stoy read(mf, &hz, sizeof hz); 21818761Ssam if (nl[X_PHZ].n_value != 0) { 21918761Ssam lseek(mf, (long)nl[X_PHZ].n_value, L_SET); 22018761Ssam read(mf, &phz, sizeof phz); 22118761Ssam } 22215266Ssam HZ = phz ? phz : hz; 22330266Sbostic if (nl[X_DK_NDRIVE].n_value == 0) { 22429664Ssam fprintf(stderr, "dk_ndrive undefined in system\n"); 22518761Ssam exit(1); 2263162Stoy } 22718761Ssam lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET); 22818761Ssam read(mf, &dk_ndrive, sizeof (dk_ndrive)); 22918761Ssam if (dk_ndrive <= 0) { 23029664Ssam fprintf(stderr, "dk_ndrive %d\n", dk_ndrive); 23118761Ssam exit(1); 23218761Ssam } 23318761Ssam dr_select = (int *)calloc(dk_ndrive, sizeof (int)); 23418761Ssam dr_name = (char **)calloc(dk_ndrive, sizeof (char *)); 23518761Ssam #define allocate(e, t) \ 23618761Ssam s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \ 23718761Ssam s1./**/e = (t *)calloc(dk_ndrive, sizeof (t)); 23818761Ssam allocate(xfer, long); 23918761Ssam for (arg = buf, i = 0; i < dk_ndrive; i++) { 24018761Ssam dr_name[i] = arg; 24118761Ssam sprintf(dr_name[i], "dk%d", i); 24218761Ssam arg += strlen(dr_name[i]) + 1; 24318761Ssam } 2443162Stoy read_names(); 2451155Sbill time(&now); 2469249Ssam nintv = now - boottime; 2471155Sbill if (nintv <= 0 || nintv > 60*60*24*365*10) { 24829664Ssam fprintf(stderr, 24929664Ssam "Time makes no sense... namelist must be wrong.\n"); 2501155Sbill exit(1); 2511155Sbill } 25217262Smckusick if (iflag) { 25317262Smckusick dointr(nintv); 25417262Smckusick exit(0); 25517262Smckusick } 25618761Ssam /* 25718761Ssam * Choose drives to be displayed. Priority 25818761Ssam * goes to (in order) drives supplied as arguments, 25918761Ssam * default drives. If everything isn't filled 26018761Ssam * in and there are drives not taken care of, 26118761Ssam * display the first few that fit. 26218761Ssam */ 26318761Ssam ndrives = 0; 26418761Ssam while (argc > 0 && !isdigit(argv[0][0])) { 26518761Ssam for (i = 0; i < dk_ndrive; i++) { 26618761Ssam if (strcmp(dr_name[i], argv[0])) 26718761Ssam continue; 26818761Ssam dr_select[i] = 1; 26918761Ssam ndrives++; 27018761Ssam } 27118761Ssam argc--, argv++; 27218761Ssam } 27318761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 27418761Ssam if (dr_select[i]) 27518761Ssam continue; 27618761Ssam for (cp = defdrives; *cp; cp++) 27718761Ssam if (strcmp(dr_name[i], *cp) == 0) { 27818761Ssam dr_select[i] = 1; 27918761Ssam ndrives++; 28018761Ssam break; 28118761Ssam } 28218761Ssam } 28318761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 28418761Ssam if (dr_select[i]) 28518761Ssam continue; 28618761Ssam dr_select[i] = 1; 28718761Ssam ndrives++; 28818761Ssam } 28918761Ssam if (argc > 1) 29018761Ssam iter = atoi(argv[1]); 29117262Smckusick signal(SIGCONT, printhdr); 2921155Sbill loop: 29318768Ssam if (--lines == 0) 29418768Ssam printhdr(); 29518761Ssam lseek(mf, (long)nl[X_CPTIME].n_value, L_SET); 2961448Sbill read(mf, s.time, sizeof s.time); 29718761Ssam lseek(mf, (long)nl[X_DKXFER].n_value, L_SET); 29818761Ssam read(mf, s.xfer, dk_ndrive * sizeof (long)); 29918761Ssam if (nintv != 1) 30018761Ssam lseek(mf, (long)nl[X_SUM].n_value, L_SET); 30118761Ssam else 30218761Ssam lseek(mf, (long)nl[X_RATE].n_value, L_SET); 30318761Ssam read(mf, &rate, sizeof rate); 30418761Ssam lseek(mf, (long)nl[X_TOTAL].n_value, L_SET); 3051155Sbill read(mf, &total, sizeof total); 30610826Ssam osum = sum; 30718761Ssam lseek(mf, (long)nl[X_SUM].n_value, L_SET); 30810826Ssam read(mf, &sum, sizeof sum); 30918761Ssam lseek(mf, (long)nl[X_DEFICIT].n_value, L_SET); 3101155Sbill read(mf, &deficit, sizeof deficit); 3111448Sbill etime = 0; 31218761Ssam for (i=0; i < dk_ndrive; i++) { 3131448Sbill t = s.xfer[i]; 3141448Sbill s.xfer[i] -= s1.xfer[i]; 3151448Sbill s1.xfer[i] = t; 3161155Sbill } 3171155Sbill for (i=0; i < CPUSTATES; i++) { 3181448Sbill t = s.time[i]; 3191448Sbill s.time[i] -= s1.time[i]; 3201448Sbill s1.time[i] = t; 3211448Sbill etime += s.time[i]; 3221155Sbill } 3231155Sbill if(etime == 0.) 3241155Sbill etime = 1.; 3253162Stoy printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw); 32610826Ssam #define pgtok(a) ((a)*NBPG/1024) 32729664Ssam printf("%6d%6d", pgtok(total.t_avm), pgtok(total.t_free)); 32815266Ssam printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv, 32915266Ssam (rate.v_xsfrec+rate.v_xifrec)/nintv); 33010826Ssam printf("%4d", pgtok(rate.v_pgpgin)/nintv); 33110826Ssam printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv, 33210826Ssam pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv); 33318761Ssam etime /= (float)HZ; 33418761Ssam for (i = 0; i < dk_ndrive; i++) 33518761Ssam if (dr_select[i]) 33618761Ssam stats(i); 33715266Ssam printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv, 33815266Ssam rate.v_swtch/nintv); 3391155Sbill for(i=0; i<CPUSTATES; i++) { 3401155Sbill float f = stat1(i); 3411155Sbill if (i == 0) { /* US+NI */ 3421155Sbill i++; 3431155Sbill f += stat1(i); 3441155Sbill } 3451155Sbill printf("%3.0f", f); 3461155Sbill } 3471155Sbill printf("\n"); 3481155Sbill fflush(stdout); 3491155Sbill nintv = 1; 35018768Ssam if (--iter &&argc > 0) { 3511155Sbill sleep(atoi(argv[0])); 3521155Sbill goto loop; 3531155Sbill } 3541155Sbill } 3551155Sbill 35617262Smckusick printhdr() 35717262Smckusick { 35818761Ssam register int i, j; 35918761Ssam 36029664Ssam printf(" procs memory page "); 36118761Ssam i = (ndrives * 3 - 6) / 2; 36218761Ssam if (i < 0) 36318761Ssam i = 0; 36418761Ssam for (j = 0; j < i; j++) 36518761Ssam putchar(' '); 36618761Ssam printf("faults"); 36718761Ssam i = ndrives * 3 - 6 - i; 36818761Ssam for (j = 0; j < i; j++) 36918761Ssam putchar(' '); 37018761Ssam printf(" cpu\n"); 37129664Ssam printf(" r b w avm fre re at pi po fr de sr "); 37218761Ssam for (i = 0; i < dk_ndrive; i++) 37318761Ssam if (dr_select[i]) 37418761Ssam printf("%c%c ", dr_name[i][0], dr_name[i][2]); 37518761Ssam printf(" in sy cs us sy id\n"); 37618768Ssam lines = 19; 37717262Smckusick } 37817262Smckusick 3791155Sbill dotimes() 3801155Sbill { 3811155Sbill 38218761Ssam lseek(mf, (long)nl[X_REC].n_value, L_SET); 3831155Sbill read(mf, &s.rectime, sizeof s.rectime); 38418761Ssam lseek(mf, (long)nl[X_PGIN].n_value, L_SET); 3851155Sbill read(mf, &s.pgintime, sizeof s.pgintime); 38618761Ssam lseek(mf, (long)nl[X_SUM].n_value, L_SET); 3871155Sbill read(mf, &sum, sizeof sum); 3881155Sbill printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime); 3891155Sbill printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec); 3901155Sbill printf("\n"); 3911155Sbill printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10); 3921155Sbill printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0)); 3931155Sbill } 3941155Sbill 39530069Ssam #if defined(tahoe) 39630069Ssam #include <tahoe/cpu.h> 39730069Ssam #endif 39830069Ssam 3991155Sbill dosum() 4001155Sbill { 40118761Ssam struct nchstats nchstats; 40225960Ssam struct xstats xstats; 40315807Smckusick long nchtotal; 40425960Ssam #if defined(tahoe) 40525960Ssam struct keystats keystats; 40625960Ssam #endif 4071155Sbill 40818761Ssam lseek(mf, (long)nl[X_SUM].n_value, L_SET); 4091155Sbill read(mf, &sum, sizeof sum); 4101155Sbill printf("%9d swap ins\n", sum.v_swpin); 4111155Sbill printf("%9d swap outs\n", sum.v_swpout); 4121155Sbill printf("%9d pages swapped in\n", sum.v_pswpin / CLSIZE); 4131155Sbill printf("%9d pages swapped out\n", sum.v_pswpout / CLSIZE); 4141155Sbill printf("%9d total address trans. faults taken\n", sum.v_faults); 4151155Sbill printf("%9d page ins\n", sum.v_pgin); 4161155Sbill printf("%9d page outs\n", sum.v_pgout); 4173612Sroot printf("%9d pages paged in\n", sum.v_pgpgin); 4183612Sroot printf("%9d pages paged out\n", sum.v_pgpgout); 4193612Sroot printf("%9d sequential process pages freed\n", sum.v_seqfree); 42012830Ssam printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec, 42129664Ssam pct(sum.v_fastpgrec, sum.v_pgrec)); 4221155Sbill printf("%9d reclaims from free list\n", sum.v_pgfrec); 4231155Sbill printf("%9d intransit blocking page faults\n", sum.v_intrans); 4241155Sbill printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE); 4251155Sbill printf("%9d zero fill page faults\n", sum.v_zfod / CLSIZE); 4261155Sbill printf("%9d executable fill pages created\n", sum.v_nexfod / CLSIZE); 4271155Sbill printf("%9d executable fill page faults\n", sum.v_exfod / CLSIZE); 4281155Sbill printf("%9d swap text pages found in free list\n", sum.v_xsfrec); 4291155Sbill printf("%9d inode text pages found in free list\n", sum.v_xifrec); 4301155Sbill printf("%9d file fill pages created\n", sum.v_nvrfod / CLSIZE); 4311155Sbill printf("%9d file fill page faults\n", sum.v_vrfod / CLSIZE); 4321155Sbill printf("%9d pages examined by the clock daemon\n", sum.v_scan); 4331155Sbill printf("%9d revolutions of the clock hand\n", sum.v_rev); 4341155Sbill printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE); 4351155Sbill printf("%9d cpu context switches\n", sum.v_swtch); 4361155Sbill printf("%9d device interrupts\n", sum.v_intr); 43717262Smckusick printf("%9d software interrupts\n", sum.v_soft); 43818761Ssam #ifdef vax 43924429Smckusick printf("%9d pseudo-dma dz interrupts\n", sum.v_pdma); 44018761Ssam #endif 4411155Sbill printf("%9d traps\n", sum.v_trap); 4421155Sbill printf("%9d system calls\n", sum.v_syscall); 44315807Smckusick lseek(mf, (long)nl[X_NCHSTATS].n_value, 0); 44418761Ssam read(mf, &nchstats, sizeof nchstats); 44518761Ssam nchtotal = nchstats.ncs_goodhits + nchstats.ncs_badhits + 44618761Ssam nchstats.ncs_falsehits + nchstats.ncs_miss + nchstats.ncs_long; 44715807Smckusick printf("%9d total name lookups", nchtotal); 44815807Smckusick printf(" (cache hits %d%% system %d%% per-process)\n", 44929664Ssam pct(nchstats.ncs_goodhits, nchtotal), 45029664Ssam pct(nchstats.ncs_pass2, nchtotal)); 45116586Ssam printf("%9s badhits %d, falsehits %d, toolong %d\n", "", 45218761Ssam nchstats.ncs_badhits, nchstats.ncs_falsehits, nchstats.ncs_long); 45325512Ssam lseek(mf, (long)nl[X_XSTATS].n_value, 0); 45425512Ssam read(mf, &xstats, sizeof xstats); 45525512Ssam printf("%9d total calls to xalloc (cache hits %d%%)\n", 45629664Ssam xstats.alloc, pct(xstats.alloc_cachehit, xstats.alloc)); 45725512Ssam printf("%9s sticky %d flushed %d unused %d\n", "", 45825512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 45925512Ssam printf("%9d total calls to xfree", xstats.free); 46025512Ssam printf(" (sticky %d cached %d swapped %d)\n", 46125512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 46225960Ssam #if defined(tahoe) 46325960Ssam lseek(mf, (long)nl[X_CKEYSTATS].n_value, 0); 46425960Ssam read(mf, &keystats, sizeof keystats); 46525960Ssam printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 46625960Ssam keystats.ks_allocs, "code cache keys allocated", 46733610Smckusick pct(keystats.ks_allocfree, keystats.ks_allocs), 46829664Ssam pct(keystats.ks_norefs, keystats.ks_allocs), 46929664Ssam pct(keystats.ks_taken, keystats.ks_allocs), 47029664Ssam pct(keystats.ks_shared, keystats.ks_allocs)); 47125960Ssam lseek(mf, (long)nl[X_DKEYSTATS].n_value, 0); 47225960Ssam read(mf, &keystats, sizeof keystats); 47325960Ssam printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 47425960Ssam keystats.ks_allocs, "data cache keys allocated", 47533610Smckusick pct(keystats.ks_allocfree, keystats.ks_allocs), 47629664Ssam pct(keystats.ks_norefs, keystats.ks_allocs), 47729664Ssam pct(keystats.ks_taken, keystats.ks_allocs), 47829664Ssam pct(keystats.ks_shared, keystats.ks_allocs)); 47925960Ssam #endif 4801155Sbill } 4811155Sbill 4821155Sbill doforkst() 4831155Sbill { 4841155Sbill 48518761Ssam lseek(mf, (long)nl[X_FORKSTAT].n_value, L_SET); 4861155Sbill read(mf, &forkstat, sizeof forkstat); 4871155Sbill printf("%d forks, %d pages, average=%.2f\n", 4881155Sbill forkstat.cntfork, forkstat.sizfork, 4891155Sbill (float) forkstat.sizfork / forkstat.cntfork); 4901155Sbill printf("%d vforks, %d pages, average=%.2f\n", 4911155Sbill forkstat.cntvfork, forkstat.sizvfork, 4921155Sbill (float)forkstat.sizvfork / forkstat.cntvfork); 4931155Sbill } 4941155Sbill 4951155Sbill stats(dn) 4961155Sbill { 4971155Sbill 49818761Ssam if (dn >= dk_ndrive) { 4991155Sbill printf(" 0"); 5001155Sbill return; 5011155Sbill } 5021448Sbill printf("%3.0f", s.xfer[dn]/etime); 5031155Sbill } 5041155Sbill 5051155Sbill double 5061155Sbill stat1(row) 5071155Sbill { 5081448Sbill double t; 5091448Sbill register i; 5101155Sbill 5111155Sbill t = 0; 5121155Sbill for(i=0; i<CPUSTATES; i++) 5131448Sbill t += s.time[i]; 5141448Sbill if(t == 0.) 5151448Sbill t = 1.; 5161448Sbill return(s.time[row]*100./t); 5171155Sbill } 5181155Sbill 5191155Sbill pct(top, bot) 5201155Sbill { 5211155Sbill 5221155Sbill if (bot == 0) 5231155Sbill return (0); 5241155Sbill return ((top * 100) / bot); 5251155Sbill } 5263162Stoy 52717262Smckusick dointr(nintv) 52817262Smckusick { 52917262Smckusick int nintr, inttotal; 53017262Smckusick long *intrcnt; 53117262Smckusick char *intrname, *malloc(); 53217262Smckusick 53317262Smckusick nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long); 53417262Smckusick intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value - 53517262Smckusick nl[X_INTRCNT].n_value); 53617262Smckusick intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value); 53717262Smckusick if (intrcnt == NULL || intrname == NULL) { 53817262Smckusick fprintf(stderr, "vmstat: out of memory\n"); 53917262Smckusick exit(9); 54017262Smckusick } 54118761Ssam lseek(mf, (long)nl[X_INTRCNT].n_value, L_SET); 54217262Smckusick read(mf, intrcnt, nintr * sizeof (long)); 54318761Ssam lseek(mf, (long)nl[X_INTRNAMES].n_value, L_SET); 54417262Smckusick read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value); 54517262Smckusick printf("interrupt total rate\n"); 54617262Smckusick inttotal = 0; 54717262Smckusick while (nintr--) { 54817262Smckusick if (*intrcnt) 54917262Smckusick printf("%-12s %8ld %8ld\n", intrname, 55017262Smckusick *intrcnt, *intrcnt / nintv); 55117262Smckusick intrname += strlen(intrname) + 1; 55217262Smckusick inttotal += *intrcnt++; 55317262Smckusick } 55417262Smckusick printf("Total %8ld %8ld\n", inttotal, inttotal / nintv); 55517262Smckusick } 55617262Smckusick 55733610Smckusick /* 55833610Smckusick * These names must be kept in sync with 55933610Smckusick * the types defined in <sys/malloc.h>. 56033610Smckusick */ 56133610Smckusick char *kmemnames[] = { 56236510Smarc "free", /* 0 M_FREE */ 56336510Smarc "mbuf", /* 1 M_MBUF */ 56436510Smarc "devbuf", /* 2 M_DEVBUF */ 56536510Smarc "socket", /* 3 M_SOCKET */ 56636510Smarc "pcb", /* 4 M_PCB */ 56736510Smarc "routetbl", /* 5 M_RTABLE */ 56836510Smarc "hosttbl", /* 6 M_HTABLE */ 56936510Smarc "fragtbl", /* 7 M_FTABLE */ 57036510Smarc "zombie", /* 8 M_ZOMBIE */ 57136510Smarc "ifaddr", /* 9 M_IFADDR */ 57236510Smarc "soopts", /* 10 M_SOOPTS */ 57336510Smarc "soname", /* 11 M_SONAME */ 57436510Smarc "namei", /* 12 M_NAMEI */ 57536510Smarc "gprof", /* 13 M_GPROF */ 57636510Smarc "ioctlops", /* 14 M_IOCTLOPS */ 57736510Smarc "superblk", /* 15 M_SUPERBLK */ 57836510Smarc "cred", /* 16 M_CRED */ 57936510Smarc "pgrp", /* 17 M_PGRP */ 58036510Smarc "session", /* 18 M_SESSION */ 58136513Smarc "iov", /* 19 M_IOV */ 58238262Smckusick "mount", /* 20 M_MOUNT */ 58338262Smckusick "fhandle", /* 21 M_FHANDLE */ 58438262Smckusick "NFS req", /* 22 M_NFSREQ */ 58538262Smckusick "NFS mount", /* 23 M_NFSMNT */ 58636510Smarc 0, 0, 0, 0, 0, 58736510Smarc 0, 0, 0, 0, 0, 58836510Smarc 0, 0, 0, 0, 0, 58936510Smarc 0, 0, 0, 0, 0, 59036510Smarc 0, 0, 0, 0, 0, 59136510Smarc "temp", /* 49 M_TEMP */ 59233610Smckusick }; 59333610Smckusick 59433610Smckusick domem() 59533610Smckusick { 59633610Smckusick struct kmemstats kmemstats[M_LAST]; 59733610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 59833610Smckusick register struct kmembuckets *kp; 59933610Smckusick register struct kmemstats *ks; 60033610Smckusick int i; 60133610Smckusick 60233610Smckusick lseek(mf, (long)nl[X_KMEMBUCKETS].n_value, L_SET); 60333610Smckusick read(mf, buckets, sizeof buckets); 60433610Smckusick printf("Memory statistics by bucket size\n"); 60533610Smckusick printf(" Size In Use Free Requests HighWater Couldfree\n"); 60633610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 60733610Smckusick if (kp->kb_calls == 0) 60833610Smckusick continue; 60933610Smckusick printf("%8d%9d%7d%11d%8d%11d\n", 1 << i, 61033610Smckusick kp->kb_total - kp->kb_totalfree, 61133610Smckusick kp->kb_totalfree, kp->kb_calls, 61233610Smckusick kp->kb_highwat, kp->kb_couldfree); 61333610Smckusick 61433610Smckusick } 61533610Smckusick lseek(mf, (long)nl[X_KMEMSTAT].n_value, L_SET); 61633610Smckusick read(mf, kmemstats, sizeof kmemstats); 61733610Smckusick printf("Memory statistics by type\n"); 61833610Smckusick printf(" Type In Use MemUse HighUse Limit Requests %s\n", 61933610Smckusick "TypeLimit KernLimit"); 62033610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 62133610Smckusick if (ks->ks_calls == 0) 62233610Smckusick continue; 62333610Smckusick printf("%10s%7d%8dK%9dK%6dK%9d%7d%10d\n", 62433610Smckusick kmemnames[i] ? kmemnames[i] : "undefined", 62533610Smckusick ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 62633610Smckusick (ks->ks_maxused + 1023) / 1024, 62733610Smckusick (ks->ks_limit + 1023) / 1024, ks->ks_calls, 62833610Smckusick ks->ks_limblocks, ks->ks_mapblocks); 62933610Smckusick } 63033610Smckusick } 63133610Smckusick 63218761Ssam #define steal(where, var) \ 63318761Ssam lseek(mf, where, L_SET); read(mf, &var, sizeof var); 6343162Stoy /* 6353162Stoy * Read the drive names out of kmem. 6363162Stoy */ 63710826Ssam #ifdef vax 63818761Ssam #include <vaxuba/ubavar.h> 63918761Ssam #include <vaxmba/mbavar.h> 64018761Ssam 6413162Stoy read_names() 6423162Stoy { 6433162Stoy struct mba_device mdev; 6443162Stoy register struct mba_device *mp; 6453162Stoy struct mba_driver mdrv; 6463162Stoy short two_char; 6473162Stoy char *cp = (char *) &two_char; 6483162Stoy struct uba_device udev, *up; 6493162Stoy struct uba_driver udrv; 6503162Stoy 6513162Stoy mp = (struct mba_device *) nl[X_MBDINIT].n_value; 6523162Stoy up = (struct uba_device *) nl[X_UBDINIT].n_value; 6533492Sroot if (up == 0) { 65410826Ssam fprintf(stderr, "vmstat: Disk init info not in namelist\n"); 6553162Stoy exit(1); 6563162Stoy } 6573492Sroot if (mp) for (;;) { 6583162Stoy steal(mp++, mdev); 6593162Stoy if (mdev.mi_driver == 0) 6603162Stoy break; 6613162Stoy if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 6623162Stoy continue; 6633162Stoy steal(mdev.mi_driver, mdrv); 6643162Stoy steal(mdrv.md_dname, two_char); 66518761Ssam sprintf(dr_name[mdev.mi_dk], "%c%c%d", 66618761Ssam cp[0], cp[1], mdev.mi_unit); 6673162Stoy } 6683492Sroot for (;;) { 6693162Stoy steal(up++, udev); 6703162Stoy if (udev.ui_driver == 0) 6713162Stoy break; 6723162Stoy if (udev.ui_dk < 0 || udev.ui_alive == 0) 6733162Stoy continue; 6743162Stoy steal(udev.ui_driver, udrv); 6753162Stoy steal(udrv.ud_dname, two_char); 67618761Ssam sprintf(dr_name[udev.ui_dk], "%c%c%d", 67718761Ssam cp[0], cp[1], udev.ui_unit); 6783162Stoy } 6793162Stoy } 68010826Ssam #endif 68125708Ssam 68225708Ssam #ifdef tahoe 68325708Ssam #include <tahoevba/vbavar.h> 68425708Ssam 68525708Ssam /* 68625708Ssam * Read the drive names out of kmem. 68725708Ssam */ 68825708Ssam read_names() 68925708Ssam { 69025708Ssam struct vba_device udev, *up; 69125708Ssam struct vba_driver udrv; 69225708Ssam short two_char; 69325708Ssam char *cp = (char *)&two_char; 69425708Ssam 69525708Ssam up = (struct vba_device *) nl[X_VBDINIT].n_value; 69625708Ssam if (up == 0) { 69725708Ssam fprintf(stderr, "vmstat: Disk init info not in namelist\n"); 69825708Ssam exit(1); 69925708Ssam } 70025708Ssam for (;;) { 70125708Ssam steal(up++, udev); 70225708Ssam if (udev.ui_driver == 0) 70325708Ssam break; 70425708Ssam if (udev.ui_dk < 0 || udev.ui_alive == 0) 70525708Ssam continue; 70625708Ssam steal(udev.ui_driver, udrv); 70725708Ssam steal(udrv.ud_dname, two_char); 70825708Ssam sprintf(dr_name[udev.ui_dk], "%c%c%d", 70925708Ssam cp[0], cp[1], udev.ui_unit); 71025708Ssam } 71125708Ssam } 71225708Ssam #endif 713