121585Sdist /* 248570Sbostic * Copyright (c) 1980, 1986, 1991 The Regents of the University of California. 336580Sbostic * All rights reserved. 436580Sbostic * 542784Sbostic * %sccs.include.redist.c% 621585Sdist */ 721585Sdist 810826Ssam #ifndef lint 921585Sdist char copyright[] = 1048570Sbostic "@(#) Copyright (c) 1980, 1986, 1991 The Regents of the University of California.\n\ 1121585Sdist All rights reserved.\n"; 1236580Sbostic #endif /* not lint */ 1310826Ssam 1421585Sdist #ifndef lint 15*51359Smckusick static char sccsid[] = "@(#)vmstat.c 5.32 (Berkeley) 10/10/91"; 1636580Sbostic #endif /* not lint */ 1721585Sdist 181155Sbill #include <sys/param.h> 1950004Skarels #include <sys/time.h> 2050004Skarels #include <sys/proc.h> 2146892Sbostic #include <sys/user.h> 2229664Ssam #include <sys/dkstat.h> 233162Stoy #include <sys/buf.h> 2417262Smckusick #include <sys/namei.h> 2533610Smckusick #include <sys/malloc.h> 2650004Skarels #include <sys/signal.h> 2750004Skarels #include <sys/fcntl.h> 2850004Skarels #include <sys/ioctl.h> 29*51359Smckusick #include <sys/kinfo.h> 3050103Skarels #include <vm/vm.h> 3148570Sbostic #include <time.h> 3248570Sbostic #include <nlist.h> 3348570Sbostic #include <kvm.h> 3445834Sbostic #include <errno.h> 3548570Sbostic #include <unistd.h> 3645834Sbostic #include <stdio.h> 3748570Sbostic #include <ctype.h> 3845834Sbostic #include <stdlib.h> 3945834Sbostic #include <string.h> 4037912Sbostic #include <paths.h> 411155Sbill 4250103Skarels #define NEWVM /* XXX till old has been updated or purged */ 431155Sbill struct nlist nl[] = { 441448Sbill #define X_CPTIME 0 451448Sbill { "_cp_time" }, 46*51359Smckusick #define X_DK_NDRIVE 1 47*51359Smckusick { "_dk_ndrive" }, 4850006Skarels #define X_SUM 2 49*51359Smckusick { "_cnt" }, 5050006Skarels #define X_BOOTTIME 3 519249Ssam { "_boottime" }, 5250006Skarels #define X_DKXFER 4 531448Sbill { "_dk_xfer" }, 5450006Skarels #define X_HZ 5 553162Stoy { "_hz" }, 5650006Skarels #define X_PHZ 6 5715266Ssam { "_phz" }, 5850006Skarels #define X_NCHSTATS 7 5915807Smckusick { "_nchstats" }, 6050006Skarels #define X_INTRNAMES 8 6117262Smckusick { "_intrnames" }, 6250006Skarels #define X_EINTRNAMES 9 6317262Smckusick { "_eintrnames" }, 6450006Skarels #define X_INTRCNT 10 6517262Smckusick { "_intrcnt" }, 6650006Skarels #define X_EINTRCNT 11 6717262Smckusick { "_eintrcnt" }, 68*51359Smckusick #define X_KMEMSTAT 12 6933610Smckusick { "_kmemstats" }, 70*51359Smckusick #define X_KMEMBUCKETS 13 7133610Smckusick { "_bucket" }, 7250103Skarels #ifdef notdef 73*51359Smckusick #define X_DEFICIT 14 7450004Skarels { "_deficit" }, 75*51359Smckusick #define X_FORKSTAT 15 7650004Skarels { "_forkstat" }, 77*51359Smckusick #define X_REC 16 7850004Skarels { "_rectime" }, 79*51359Smckusick #define X_PGIN 17 8050004Skarels { "_pgintime" }, 81*51359Smckusick #define X_XSTATS 18 8250004Skarels { "_xstats" }, 83*51359Smckusick #define X_END 18 8450103Skarels #else 85*51359Smckusick #define X_END 14 8650004Skarels #endif 8748570Sbostic #ifdef hp300 88*51359Smckusick #define X_HPDINIT (X_END) 8948570Sbostic { "_hp_dinit" }, 9010826Ssam #endif 9125708Ssam #ifdef tahoe 92*51359Smckusick #define X_VBDINIT (X_END) 9325708Ssam { "_vbdinit" }, 94*51359Smckusick #define X_CKEYSTATS (X_END+1) 9525960Ssam { "_ckeystats" }, 96*51359Smckusick #define X_DKEYSTATS (X_END+2) 9725960Ssam { "_dkeystats" }, 9825708Ssam #endif 9948570Sbostic #ifdef vax 100*51359Smckusick #define X_MBDINIT (X_END) 10148570Sbostic { "_mbdinit" }, 102*51359Smckusick #define X_UBDINIT (X_END+1) 10348570Sbostic { "_ubdinit" }, 10442952Sbostic #endif 10510826Ssam { "" }, 1061155Sbill }; 1071155Sbill 10848570Sbostic struct _disk { 10948570Sbostic long time[CPUSTATES]; 11048570Sbostic long *xfer; 11148570Sbostic } cur, last; 11218761Ssam 11350006Skarels struct vmmeter sum, osum; 11450004Skarels char *vmunix = _PATH_UNIX; 11550004Skarels char **dr_name; 11650004Skarels int *dr_select, dk_ndrive, ndrives; 1171155Sbill 11850004Skarels int winlines = 20; 11950004Skarels 12045834Sbostic #define FORKSTAT 0x01 12145834Sbostic #define INTRSTAT 0x02 12245834Sbostic #define MEMSTAT 0x04 12345834Sbostic #define SUMSTAT 0x08 12445834Sbostic #define TIMESTAT 0x10 12545834Sbostic #define VMSTAT 0x20 12645834Sbostic 12748570Sbostic #include "names.c" /* disk names -- machine dependent */ 12848570Sbostic 12950004Skarels void cpustats(), dkstats(), dointr(), domem(), dosum(); 13050103Skarels void dovmstat(), kread(), usage(); 13150103Skarels #ifdef notdef 13250004Skarels void dotimes(), doforkst(); 13350004Skarels #endif 13448570Sbostic 1351155Sbill main(argc, argv) 13645834Sbostic register int argc; 13745834Sbostic register char **argv; 1381155Sbill { 13945834Sbostic extern int optind; 14045834Sbostic extern char *optarg; 14148570Sbostic register int c, todo; 14248570Sbostic u_int interval; 14348570Sbostic int reps; 14448570Sbostic char *kmem; 1451155Sbill 14648570Sbostic kmem = NULL; 14748570Sbostic interval = reps = todo = 0; 14850103Skarels while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) { 14945834Sbostic switch (c) { 15048570Sbostic case 'c': 15148570Sbostic reps = atoi(optarg); 15248570Sbostic break; 15350103Skarels #ifndef notdef 15445834Sbostic case 'f': 15545834Sbostic todo |= FORKSTAT; 15645834Sbostic break; 15750004Skarels #endif 15845834Sbostic case 'i': 15945834Sbostic todo |= INTRSTAT; 16045834Sbostic break; 16148570Sbostic case 'M': 16245834Sbostic kmem = optarg; 16345834Sbostic break; 16445834Sbostic case 'm': 16545834Sbostic todo |= MEMSTAT; 16645834Sbostic break; 16748570Sbostic case 'N': 16848570Sbostic vmunix = optarg; 16948570Sbostic break; 17045834Sbostic case 's': 17145834Sbostic todo |= SUMSTAT; 17245834Sbostic break; 17350103Skarels #ifndef notdef 17445834Sbostic case 't': 17545834Sbostic todo |= TIMESTAT; 17645834Sbostic break; 17750004Skarels #endif 17848570Sbostic case 'w': 17948570Sbostic interval = atoi(optarg); 18045834Sbostic break; 18145834Sbostic case '?': 18248570Sbostic default: 18345834Sbostic usage(); 18445834Sbostic } 18545834Sbostic } 18648570Sbostic argc -= optind; 18748570Sbostic argv += optind; 18845834Sbostic 18945834Sbostic if (todo == 0) 19045834Sbostic todo = VMSTAT; 19145834Sbostic 19248570Sbostic if (kvm_openfiles(vmunix, kmem, NULL) < 0) { 19348570Sbostic (void)fprintf(stderr, 19448570Sbostic "vmstat: kvm_openfiles: %s\n", kvm_geterr()); 1951155Sbill exit(1); 1961155Sbill } 19745834Sbostic 19850004Skarels if ((c = kvm_nlist(nl)) != 0) { 19950004Skarels if (c > 0) { 20050004Skarels (void)fprintf(stderr, 20150004Skarels "vmstat: undefined symbols in %s:", vmunix); 20250004Skarels for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++) 20350004Skarels if (nl[c].n_type == 0) 20450004Skarels printf(" %s", nl[c].n_name); 20550004Skarels (void)fputc('\n', stderr); 20650004Skarels } else 20750004Skarels (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", 20850004Skarels kvm_geterr()); 2091155Sbill exit(1); 2101155Sbill } 2111155Sbill 21248570Sbostic if (todo & VMSTAT) { 21348570Sbostic char **getdrivedata(); 21450004Skarels struct winsize winsize; 21548570Sbostic 21648570Sbostic argv = getdrivedata(argv); 21750004Skarels winsize.ws_row = 0; 21850004Skarels (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 21950004Skarels if (winsize.ws_row > 0) 22050004Skarels winlines = winsize.ws_row; 22150004Skarels 22248570Sbostic } 22348570Sbostic 22448570Sbostic #define BACKWARD_COMPATIBILITY 22548570Sbostic #ifdef BACKWARD_COMPATIBILITY 22648570Sbostic if (*argv) { 22748570Sbostic interval = atoi(*argv); 22848570Sbostic if (*++argv) 22948570Sbostic reps = atoi(*argv); 23048570Sbostic } 23148570Sbostic #endif 23248570Sbostic 23348613Sbostic if (interval) { 23448613Sbostic if (!reps) 23548613Sbostic reps = -1; 23650103Skarels } else if (reps) 23750103Skarels interval = 1; 23848613Sbostic 23950103Skarels #ifdef notdef 24045834Sbostic if (todo & FORKSTAT) 24145834Sbostic doforkst(); 24250004Skarels #endif 24345834Sbostic if (todo & MEMSTAT) 24445834Sbostic domem(); 24545834Sbostic if (todo & SUMSTAT) 24645834Sbostic dosum(); 24750103Skarels #ifdef notdef 24845834Sbostic if (todo & TIMESTAT) 24945834Sbostic dotimes(); 25050004Skarels #endif 25145834Sbostic if (todo & INTRSTAT) 25245834Sbostic dointr(); 25348570Sbostic if (todo & VMSTAT) 25448570Sbostic dovmstat(interval, reps); 25545834Sbostic exit(0); 25645834Sbostic } 25710826Ssam 25848570Sbostic char ** 25948570Sbostic getdrivedata(argv) 26045834Sbostic char **argv; 26145834Sbostic { 26245834Sbostic register int i; 26345834Sbostic register char **cp; 26445834Sbostic char buf[30]; 26545834Sbostic 26648570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 26718761Ssam if (dk_ndrive <= 0) { 26848570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 26918761Ssam exit(1); 27018761Ssam } 27148570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 27248570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 27345834Sbostic for (i = 0; i < dk_ndrive; i++) 27445834Sbostic dr_name[i] = NULL; 27548570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 27648570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 2773162Stoy read_names(); 27848570Sbostic for (i = 0; i < dk_ndrive; i++) 27945834Sbostic if (dr_name[i] == NULL) { 28048570Sbostic (void)sprintf(buf, "??%d", i); 28145834Sbostic dr_name[i] = strdup(buf); 28245834Sbostic } 28345834Sbostic 28418761Ssam /* 28548570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives 28648570Sbostic * supplied as arguments, default drives. If everything isn't filled 28748570Sbostic * in and there are drives not taken care of, display the first few 28848570Sbostic * that fit. 28918761Ssam */ 29048570Sbostic #define BACKWARD_COMPATIBILITY 29148570Sbostic for (ndrives = 0; *argv; ++argv) { 29248570Sbostic #ifdef BACKWARD_COMPATIBILITY 29348570Sbostic if (isdigit(**argv)) 29448570Sbostic break; 29548570Sbostic #endif 29618761Ssam for (i = 0; i < dk_ndrive; i++) { 29748570Sbostic if (strcmp(dr_name[i], *argv)) 29818761Ssam continue; 29918761Ssam dr_select[i] = 1; 30048570Sbostic ++ndrives; 30145834Sbostic break; 30218761Ssam } 30318761Ssam } 30418761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 30518761Ssam if (dr_select[i]) 30618761Ssam continue; 30718761Ssam for (cp = defdrives; *cp; cp++) 30818761Ssam if (strcmp(dr_name[i], *cp) == 0) { 30918761Ssam dr_select[i] = 1; 31048570Sbostic ++ndrives; 31118761Ssam break; 31218761Ssam } 31318761Ssam } 31418761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 31518761Ssam if (dr_select[i]) 31618761Ssam continue; 31718761Ssam dr_select[i] = 1; 31848570Sbostic ++ndrives; 31918761Ssam } 32048570Sbostic return(argv); 32145834Sbostic } 32245834Sbostic 32345834Sbostic long 32445834Sbostic getuptime() 32545834Sbostic { 32648570Sbostic static time_t now, boottime; 32748570Sbostic time_t uptime; 32845834Sbostic 32945834Sbostic if (boottime == 0) 33048570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime)); 33148570Sbostic (void)time(&now); 33245834Sbostic uptime = now - boottime; 33345834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 33448570Sbostic (void)fprintf(stderr, 33545834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 33645834Sbostic exit(1); 33745834Sbostic } 33848570Sbostic return(uptime); 33945834Sbostic } 34045834Sbostic 34150006Skarels int hz, hdrcnt; 34248613Sbostic 34348570Sbostic void 34448570Sbostic dovmstat(interval, reps) 34548570Sbostic u_int interval; 34648570Sbostic int reps; 34745834Sbostic { 34848570Sbostic struct vmtotal total; 34950103Skarels time_t uptime, halfuptime; 35050004Skarels void needhdr(); 351*51359Smckusick int size; 35245834Sbostic 35348570Sbostic uptime = getuptime(); 35450103Skarels halfuptime = uptime / 2; 35550004Skarels (void)signal(SIGCONT, needhdr); 35648570Sbostic 35748570Sbostic if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 35848613Sbostic kread(X_PHZ, &hz, sizeof(hz)); 35948613Sbostic if (!hz) 36048613Sbostic kread(X_HZ, &hz, sizeof(hz)); 36148570Sbostic 36248570Sbostic for (hdrcnt = 1;;) { 36350004Skarels if (!--hdrcnt) 36448570Sbostic printhdr(); 36548570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time)); 36648570Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 36750006Skarels kread(X_SUM, &sum, sizeof(sum)); 368*51359Smckusick size = sizeof(total); 369*51359Smckusick if (getkerninfo(KINFO_METER, &total, &size, 0) < 0) { 370*51359Smckusick printf("Can't get kerninfo: %s\n", strerror(errno)); 371*51359Smckusick bzero(&total, sizeof(total)); 372*51359Smckusick } 373*51359Smckusick (void)printf("%2d%2d%2d", 37448570Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 375*51359Smckusick #define pgtok(a) ((a) * sum.v_page_size >> 10) 37650103Skarels #define rate(x) (((x) + halfuptime) / uptime) /* round */ 377*51359Smckusick (void)printf("%6ld%6ld ", 37848570Sbostic pgtok(total.t_avm), pgtok(total.t_free)); 37950006Skarels #ifdef NEWVM 380*51359Smckusick (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults)); 38150006Skarels (void)printf("%3lu ", 382*51359Smckusick rate(sum.v_reactivated - osum.v_reactivated)); 383*51359Smckusick (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins)); 38450006Skarels (void)printf("%3lu %3lu ", 385*51359Smckusick rate(sum.v_pageouts - osum.v_pageouts), 0); 38650006Skarels #else 38750006Skarels (void)printf("%3lu %2lu ", 38850103Skarels rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - 38950103Skarels (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))), 39050103Skarels rate(sum.v_xsfrec + sum.v_xifrec - 39150103Skarels osum.v_xsfrec - osum.v_xifrec)); 39250006Skarels (void)printf("%3lu ", 39350103Skarels rate(pgtok(sum.v_pgpgin - osum.v_pgpgin))); 39450006Skarels (void)printf("%3lu %3lu ", 39550103Skarels rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)), 39650103Skarels rate(pgtok(sum.v_dfree - osum.v_dfree))); 39750006Skarels (void)printf("%3d ", pgtok(deficit)); 39850006Skarels #endif 39950103Skarels (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan)); 40048613Sbostic dkstats(); 40150006Skarels (void)printf("%4lu %4lu %3lu ", 40250103Skarels rate(sum.v_intr - osum.v_intr), 40350103Skarels rate(sum.v_syscall - osum.v_syscall), 40450103Skarels rate(sum.v_swtch - osum.v_swtch)); 40548613Sbostic cpustats(); 40648570Sbostic (void)printf("\n"); 40748570Sbostic (void)fflush(stdout); 40848613Sbostic if (reps >= 0 && --reps <= 0) 40948570Sbostic break; 41050006Skarels osum = sum; 41150103Skarels uptime = interval; 41250103Skarels /* 41350103Skarels * We round upward to avoid losing low-frequency events 41450103Skarels * (i.e., >= 1 per interval but < 1 per second). 41550103Skarels */ 41650103Skarels halfuptime = (uptime + 1) / 2; 41748613Sbostic (void)sleep(interval); 4181155Sbill } 4191155Sbill } 4201155Sbill 42117262Smckusick printhdr() 42217262Smckusick { 42348570Sbostic register int i; 42418761Ssam 42550006Skarels (void)printf(" procs memory page%*s", 20, ""); 42648570Sbostic if (ndrives > 1) 42750006Skarels (void)printf("disks %*s faults cpu\n", 42848570Sbostic ndrives * 3 - 6, ""); 42948570Sbostic else 43050006Skarels (void)printf("%*s faults cpu\n", ndrives * 3, ""); 43150006Skarels #ifndef NEWVM 43248570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr "); 43350006Skarels #else 43450006Skarels (void)printf(" r b w avm fre flt re pi po fr sr "); 43550006Skarels #endif 43618761Ssam for (i = 0; i < dk_ndrive; i++) 43718761Ssam if (dr_select[i]) 43848570Sbostic (void)printf("%c%c ", dr_name[i][0], 43945834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 44050006Skarels (void)printf(" in sy cs us sy id\n"); 44150004Skarels hdrcnt = winlines - 2; 44217262Smckusick } 44317262Smckusick 44450004Skarels /* 44550004Skarels * Force a header to be prepended to the next output. 44650004Skarels */ 44748570Sbostic void 44850004Skarels needhdr() 44950004Skarels { 45050004Skarels 45150004Skarels hdrcnt = 1; 45250004Skarels } 45350004Skarels 45450103Skarels #ifdef notdef 45550004Skarels void 4561155Sbill dotimes() 4571155Sbill { 45848570Sbostic u_int pgintime, rectime; 4591155Sbill 46048570Sbostic kread(X_REC, &rectime, sizeof(rectime)); 46148570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime)); 46248570Sbostic kread(X_SUM, &sum, sizeof(sum)); 46348570Sbostic (void)printf("%u reclaims, %u total time (usec)\n", 46448570Sbostic sum.v_pgrec, rectime); 46548570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 46648570Sbostic (void)printf("\n"); 46748570Sbostic (void)printf("%u page ins, %u total time (msec)\n", 46848570Sbostic sum.v_pgin, pgintime / 10); 46948570Sbostic (void)printf("average: %8.1f msec / page in\n", 47048570Sbostic pgintime / (sum.v_pgin * 10.0)); 4711155Sbill } 47250004Skarels #endif 4731155Sbill 47445834Sbostic pct(top, bot) 47545834Sbostic long top, bot; 47645834Sbostic { 47745834Sbostic if (bot == 0) 47848570Sbostic return(0); 47948570Sbostic return((top * 100) / bot); 48045834Sbostic } 48145834Sbostic 48245834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 48345834Sbostic 48430069Ssam #if defined(tahoe) 48545834Sbostic #include <machine/cpu.h> 48630069Ssam #endif 48730069Ssam 48848570Sbostic void 4891155Sbill dosum() 4901155Sbill { 49118761Ssam struct nchstats nchstats; 49250004Skarels #ifndef NEWVM 49325960Ssam struct xstats xstats; 49450004Skarels #endif 49515807Smckusick long nchtotal; 49625960Ssam #if defined(tahoe) 49725960Ssam struct keystats keystats; 49825960Ssam #endif 4991155Sbill 50048570Sbostic kread(X_SUM, &sum, sizeof(sum)); 501*51359Smckusick (void)printf("%9u cpu context switches\n", sum.v_swtch); 502*51359Smckusick (void)printf("%9u device interrupts\n", sum.v_intr); 503*51359Smckusick (void)printf("%9u software interrupts\n", sum.v_soft); 504*51359Smckusick #ifdef vax 505*51359Smckusick (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 506*51359Smckusick #endif 507*51359Smckusick (void)printf("%9u traps\n", sum.v_trap); 508*51359Smckusick (void)printf("%9u system calls\n", sum.v_syscall); 509*51359Smckusick (void)printf("%9u total faults taken\n", sum.v_faults); 51048570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin); 51148570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout); 51248570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 51348570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 514*51359Smckusick (void)printf("%9u page ins\n", sum.v_pageins); 515*51359Smckusick (void)printf("%9u page outs\n", sum.v_pageouts); 51648570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin); 51748570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout); 518*51359Smckusick (void)printf("%9u pages reactivated\n", sum.v_reactivated); 519*51359Smckusick (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 520*51359Smckusick (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 521*51359Smckusick (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 522*51359Smckusick (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 523*51359Smckusick (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 524*51359Smckusick #ifdef NEWVM 525*51359Smckusick (void)printf("%9u VM object cache lookups\n", sum.v_lookups); 526*51359Smckusick (void)printf("%9u VM object hits\n", sum.v_hits); 527*51359Smckusick (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 528*51359Smckusick (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 529*51359Smckusick (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 530*51359Smckusick (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 531*51359Smckusick (void)printf("%9u pages free\n", sum.v_free_count); 532*51359Smckusick (void)printf("%9u pages wired down\n", sum.v_wire_count); 533*51359Smckusick (void)printf("%9u pages active\n", sum.v_active_count); 534*51359Smckusick (void)printf("%9u pages inactive\n", sum.v_inactive_count); 535*51359Smckusick (void)printf("%9u bytes per page\n", sum.v_page_size); 536*51359Smckusick #else 53748570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 53848570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 53945834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 54048570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 54148570Sbostic (void)printf("%9u executable fill pages created\n", 54245834Sbostic sum.v_nexfod / CLSIZE); 54348570Sbostic (void)printf("%9u executable fill page faults\n", 54445834Sbostic sum.v_exfod / CLSIZE); 54548570Sbostic (void)printf("%9u swap text pages found in free list\n", 54645834Sbostic sum.v_xsfrec); 54748570Sbostic (void)printf("%9u inode text pages found in free list\n", 54845834Sbostic sum.v_xifrec); 54948570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 55048570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 55148570Sbostic (void)printf("%9u pages freed by the clock daemon\n", 55245834Sbostic sum.v_dfree / CLSIZE); 55350006Skarels #endif 55448570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 55538773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 55638773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 55738773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 55848570Sbostic (void)printf("%9ld total name lookups\n", nchtotal); 55948570Sbostic (void)printf( 56045834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 56145834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 56245834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 56345834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 56448570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 56545834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 56645834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 56745834Sbostic PCT(nchstats.ncs_long, nchtotal)); 56850004Skarels #ifndef NEWVM 56948570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats)); 57048570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 57145834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 57248570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 57325512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 57448570Sbostic (void)printf("%9lu total calls to xfree", xstats.free); 57548570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 57625512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 57750004Skarels #endif 57825960Ssam #if defined(tahoe) 57948570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 58048570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 58125960Ssam keystats.ks_allocs, "code cache keys allocated", 58245834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 58345834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 58445834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 58545834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 58648570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 58748570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 58825960Ssam keystats.ks_allocs, "data cache keys allocated", 58945834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 59045834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 59145834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 59245834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 59325960Ssam #endif 5941155Sbill } 5951155Sbill 59650103Skarels #ifdef notdef 59748570Sbostic void 5981155Sbill doforkst() 5991155Sbill { 60048570Sbostic struct forkstat fks; 6011155Sbill 60248570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 60348570Sbostic (void)printf("%d forks, %d pages, average %.2f\n", 60448570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 60548570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n", 60648570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 6071155Sbill } 60850004Skarels #endif 6091155Sbill 61048570Sbostic void 61148613Sbostic dkstats() 6121155Sbill { 61348613Sbostic register int dn, state; 61448613Sbostic double etime; 61548613Sbostic long tmp; 61648613Sbostic 61748613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 61848613Sbostic tmp = cur.xfer[dn]; 61948613Sbostic cur.xfer[dn] -= last.xfer[dn]; 62048613Sbostic last.xfer[dn] = tmp; 62148613Sbostic } 62248613Sbostic etime = 0; 62348613Sbostic for (state = 0; state < CPUSTATES; ++state) { 62448613Sbostic tmp = cur.time[state]; 62548613Sbostic cur.time[state] -= last.time[state]; 62648613Sbostic last.time[state] = tmp; 62748613Sbostic etime += cur.time[state]; 62848613Sbostic } 62948613Sbostic if (etime == 0) 63048613Sbostic etime = 1; 63148613Sbostic etime /= hz; 63248613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 63348613Sbostic if (!dr_select[dn]) 63448613Sbostic continue; 63550006Skarels (void)printf("%2.0f ", cur.xfer[dn] / etime); 63648613Sbostic } 6371155Sbill } 6381155Sbill 63948613Sbostic void 64048613Sbostic cpustats() 6411155Sbill { 64248613Sbostic register int state; 64348613Sbostic double pct, total; 6441155Sbill 64548613Sbostic total = 0; 64648613Sbostic for (state = 0; state < CPUSTATES; ++state) 64748613Sbostic total += cur.time[state]; 64848613Sbostic if (total) 64948613Sbostic pct = 100 / total; 65048613Sbostic else 65148613Sbostic pct = 0; 65250006Skarels (void)printf("%2.0f ", /* user + nice */ 65348613Sbostic (cur.time[0] + cur.time[1]) * pct); 65450006Skarels (void)printf("%2.0f ", cur.time[2] * pct); /* system */ 65550006Skarels (void)printf("%2.0f", cur.time[3] * pct); /* idle */ 6561155Sbill } 6571155Sbill 65848570Sbostic void 65945834Sbostic dointr() 6601155Sbill { 66148570Sbostic register long *intrcnt, inttotal, uptime; 66245834Sbostic register int nintr, inamlen; 66345834Sbostic register char *intrname; 6641155Sbill 66548570Sbostic uptime = getuptime(); 66645834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 66745834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 66848570Sbostic intrcnt = malloc((size_t)nintr); 66945834Sbostic intrname = malloc((size_t)inamlen); 67017262Smckusick if (intrcnt == NULL || intrname == NULL) { 67148570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 67248570Sbostic exit(1); 67317262Smckusick } 67448570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr); 67545834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 67648570Sbostic (void)printf("interrupt total rate\n"); 67717262Smckusick inttotal = 0; 67845834Sbostic nintr /= sizeof(long); 67945834Sbostic while (--nintr >= 0) { 68017262Smckusick if (*intrcnt) 68148570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname, 68245834Sbostic *intrcnt, *intrcnt / uptime); 68317262Smckusick intrname += strlen(intrname) + 1; 68417262Smckusick inttotal += *intrcnt++; 68517262Smckusick } 68648570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 68717262Smckusick } 68817262Smckusick 68933610Smckusick /* 69045152Smckusick * These names are defined in <sys/malloc.h>. 69133610Smckusick */ 69245152Smckusick char *kmemnames[] = INITKMEMNAMES; 69333610Smckusick 69448570Sbostic void 69533610Smckusick domem() 69633610Smckusick { 69745834Sbostic register struct kmembuckets *kp; 69845834Sbostic register struct kmemstats *ks; 69945834Sbostic register int i; 70050004Skarels int size; 70150004Skarels long totuse = 0, totfree = 0, totreq = 0; 70233610Smckusick struct kmemstats kmemstats[M_LAST]; 70333610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 70433610Smckusick 70548570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 70648570Sbostic (void)printf("Memory statistics by bucket size\n"); 70748570Sbostic (void)printf( 70845834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 70933610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 71033610Smckusick if (kp->kb_calls == 0) 71133610Smckusick continue; 71250004Skarels size = 1 << i; 71350006Skarels (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, 71433610Smckusick kp->kb_total - kp->kb_totalfree, 71533610Smckusick kp->kb_totalfree, kp->kb_calls, 71633610Smckusick kp->kb_highwat, kp->kb_couldfree); 71750004Skarels totfree += size * kp->kb_totalfree; 71833610Smckusick } 71950004Skarels 72048570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 72148570Sbostic (void)printf("\nMemory statistics by type\n"); 72248570Sbostic (void)printf( 72348570Sbostic " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 72433610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 72533610Smckusick if (ks->ks_calls == 0) 72633610Smckusick continue; 72750006Skarels (void)printf("%10s %6ld %7ldK %8ldK %5ldK %8ld %6u %9u\n", 72848570Sbostic kmemnames[i] ? kmemnames[i] : "undefined", 72948570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 73048570Sbostic (ks->ks_maxused + 1023) / 1024, 73148570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls, 73248570Sbostic ks->ks_limblocks, ks->ks_mapblocks); 73350004Skarels totuse += ks->ks_memuse; 73450004Skarels totreq += ks->ks_calls; 73533610Smckusick } 73650004Skarels (void)printf("\nMemory Totals: In Use Free Requests\n"); 73750004Skarels (void)printf(" %7ldK %6ldK %8ld\n", 73850004Skarels (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 73933610Smckusick } 74033610Smckusick 74125708Ssam /* 74248570Sbostic * kread reads something from the kernel, given its nlist index. 74325708Ssam */ 74448570Sbostic void 74548570Sbostic kread(nlx, addr, size) 74648570Sbostic int nlx; 74748570Sbostic void *addr; 74848570Sbostic size_t size; 74925708Ssam { 75048570Sbostic char *sym; 75125708Ssam 75248570Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 75348570Sbostic sym = nl[nlx].n_name; 75448570Sbostic if (*sym == '_') 75548570Sbostic ++sym; 75648570Sbostic (void)fprintf(stderr, 75748570Sbostic "vmstat: %s: symbol %s not defined\n", vmunix, sym); 75825708Ssam exit(1); 75925708Ssam } 76048570Sbostic if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { 76148570Sbostic sym = nl[nlx].n_name; 76248570Sbostic if (*sym == '_') 76348570Sbostic ++sym; 76448570Sbostic (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); 76548570Sbostic exit(1); 76625708Ssam } 76725708Ssam } 76842952Sbostic 76948570Sbostic void 77048570Sbostic usage() 77142952Sbostic { 77248570Sbostic (void)fprintf(stderr, 77350004Skarels #ifndef NEWVM 77448570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \ 77550103Skarels [-N system] [-w wait] [disks]\n"); 77650004Skarels #else 77750004Skarels "usage: vmstat [-ims] [-c count] [-M core] \ 77850103Skarels [-N system] [-w wait] [disks]\n"); 77950004Skarels #endif 78048570Sbostic exit(1); 78142952Sbostic } 782