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*55663Sbostic static char sccsid[] = "@(#)vmstat.c 5.35 (Berkeley) 07/24/92"; 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> 2951359Smckusick #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> 4154272Smccanne #include <limits.h> 421155Sbill 4350103Skarels #define NEWVM /* XXX till old has been updated or purged */ 441155Sbill struct nlist nl[] = { 451448Sbill #define X_CPTIME 0 461448Sbill { "_cp_time" }, 4751359Smckusick #define X_DK_NDRIVE 1 4851359Smckusick { "_dk_ndrive" }, 4950006Skarels #define X_SUM 2 5051359Smckusick { "_cnt" }, 5150006Skarels #define X_BOOTTIME 3 529249Ssam { "_boottime" }, 5350006Skarels #define X_DKXFER 4 541448Sbill { "_dk_xfer" }, 5550006Skarels #define X_HZ 5 563162Stoy { "_hz" }, 5754272Smccanne #define X_STATHZ 6 5854272Smccanne { "_stathz" }, 5950006Skarels #define X_NCHSTATS 7 6015807Smckusick { "_nchstats" }, 6150006Skarels #define X_INTRNAMES 8 6217262Smckusick { "_intrnames" }, 6350006Skarels #define X_EINTRNAMES 9 6417262Smckusick { "_eintrnames" }, 6550006Skarels #define X_INTRCNT 10 6617262Smckusick { "_intrcnt" }, 6750006Skarels #define X_EINTRCNT 11 6817262Smckusick { "_eintrcnt" }, 6951359Smckusick #define X_KMEMSTAT 12 7033610Smckusick { "_kmemstats" }, 7151359Smckusick #define X_KMEMBUCKETS 13 7233610Smckusick { "_bucket" }, 7350103Skarels #ifdef notdef 7451359Smckusick #define X_DEFICIT 14 7550004Skarels { "_deficit" }, 7651359Smckusick #define X_FORKSTAT 15 7750004Skarels { "_forkstat" }, 7851359Smckusick #define X_REC 16 7950004Skarels { "_rectime" }, 8051359Smckusick #define X_PGIN 17 8150004Skarels { "_pgintime" }, 8251359Smckusick #define X_XSTATS 18 8350004Skarels { "_xstats" }, 8451359Smckusick #define X_END 18 8550103Skarels #else 8651359Smckusick #define X_END 14 8750004Skarels #endif 8848570Sbostic #ifdef hp300 8951359Smckusick #define X_HPDINIT (X_END) 9048570Sbostic { "_hp_dinit" }, 9110826Ssam #endif 9225708Ssam #ifdef tahoe 9351359Smckusick #define X_VBDINIT (X_END) 9425708Ssam { "_vbdinit" }, 9551359Smckusick #define X_CKEYSTATS (X_END+1) 9625960Ssam { "_ckeystats" }, 9751359Smckusick #define X_DKEYSTATS (X_END+2) 9825960Ssam { "_dkeystats" }, 9925708Ssam #endif 10048570Sbostic #ifdef vax 10151359Smckusick #define X_MBDINIT (X_END) 10248570Sbostic { "_mbdinit" }, 10351359Smckusick #define X_UBDINIT (X_END+1) 10448570Sbostic { "_ubdinit" }, 10542952Sbostic #endif 10610826Ssam { "" }, 1071155Sbill }; 1081155Sbill 10948570Sbostic struct _disk { 11048570Sbostic long time[CPUSTATES]; 11148570Sbostic long *xfer; 11248570Sbostic } cur, last; 11318761Ssam 11450006Skarels struct vmmeter sum, osum; 11550004Skarels char **dr_name; 11650004Skarels int *dr_select, dk_ndrive, ndrives; 1171155Sbill 11850004Skarels int winlines = 20; 11950004Skarels 12054272Smccanne kvm_t *kd; 12154272Smccanne 12245834Sbostic #define FORKSTAT 0x01 12345834Sbostic #define INTRSTAT 0x02 12445834Sbostic #define MEMSTAT 0x04 12545834Sbostic #define SUMSTAT 0x08 12645834Sbostic #define TIMESTAT 0x10 12745834Sbostic #define VMSTAT 0x20 12845834Sbostic 12948570Sbostic #include "names.c" /* disk names -- machine dependent */ 13048570Sbostic 13150004Skarels void cpustats(), dkstats(), dointr(), domem(), dosum(); 13250103Skarels void dovmstat(), kread(), usage(); 13350103Skarels #ifdef notdef 13450004Skarels void dotimes(), doforkst(); 13550004Skarels #endif 13648570Sbostic 1371155Sbill main(argc, argv) 13845834Sbostic register int argc; 13945834Sbostic register char **argv; 1401155Sbill { 14145834Sbostic extern int optind; 14245834Sbostic extern char *optarg; 14348570Sbostic register int c, todo; 14448570Sbostic u_int interval; 14548570Sbostic int reps; 14652243Sbostic char *memf, *nlistf; 14754272Smccanne char errbuf[_POSIX2_LINE_MAX]; 1481155Sbill 14952243Sbostic memf = nlistf = NULL; 15048570Sbostic interval = reps = todo = 0; 15150103Skarels while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) { 15245834Sbostic switch (c) { 15348570Sbostic case 'c': 15448570Sbostic reps = atoi(optarg); 15548570Sbostic break; 15650103Skarels #ifndef notdef 15745834Sbostic case 'f': 15845834Sbostic todo |= FORKSTAT; 15945834Sbostic break; 16050004Skarels #endif 16145834Sbostic case 'i': 16245834Sbostic todo |= INTRSTAT; 16345834Sbostic break; 16448570Sbostic case 'M': 16552243Sbostic memf = optarg; 16645834Sbostic break; 16745834Sbostic case 'm': 16845834Sbostic todo |= MEMSTAT; 16945834Sbostic break; 17048570Sbostic case 'N': 17152243Sbostic nlistf = optarg; 17248570Sbostic break; 17345834Sbostic case 's': 17445834Sbostic todo |= SUMSTAT; 17545834Sbostic break; 17650103Skarels #ifndef notdef 17745834Sbostic case 't': 17845834Sbostic todo |= TIMESTAT; 17945834Sbostic break; 18050004Skarels #endif 18148570Sbostic case 'w': 18248570Sbostic interval = atoi(optarg); 18345834Sbostic break; 18445834Sbostic case '?': 18548570Sbostic default: 18645834Sbostic usage(); 18745834Sbostic } 18845834Sbostic } 18948570Sbostic argc -= optind; 19048570Sbostic argv += optind; 19145834Sbostic 19245834Sbostic if (todo == 0) 19345834Sbostic todo = VMSTAT; 19445834Sbostic 19552243Sbostic /* 19652243Sbostic * Discard setgid privileges if not the running kernel so that bad 19752243Sbostic * guys can't print interesting stuff from kernel memory. 19852243Sbostic */ 19952243Sbostic if (nlistf != NULL || memf != NULL) 20052243Sbostic setgid(getgid()); 20152243Sbostic 20254272Smccanne kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 20354272Smccanne if (kd == 0) { 20448570Sbostic (void)fprintf(stderr, 20554272Smccanne "vmstat: kvm_openfiles: %s\n", errbuf); 2061155Sbill exit(1); 2071155Sbill } 20845834Sbostic 20954272Smccanne if ((c = kvm_nlist(kd, nl)) != 0) { 21050004Skarels if (c > 0) { 21150004Skarels (void)fprintf(stderr, 21252243Sbostic "vmstat: undefined symbols: "); 21350004Skarels for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++) 21450004Skarels if (nl[c].n_type == 0) 21550004Skarels printf(" %s", nl[c].n_name); 21650004Skarels (void)fputc('\n', stderr); 21750004Skarels } else 21850004Skarels (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", 21954272Smccanne kvm_geterr(kd)); 2201155Sbill exit(1); 2211155Sbill } 2221155Sbill 22348570Sbostic if (todo & VMSTAT) { 22448570Sbostic char **getdrivedata(); 22550004Skarels struct winsize winsize; 22648570Sbostic 22748570Sbostic argv = getdrivedata(argv); 22850004Skarels winsize.ws_row = 0; 22950004Skarels (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 23050004Skarels if (winsize.ws_row > 0) 23150004Skarels winlines = winsize.ws_row; 23250004Skarels 23348570Sbostic } 23448570Sbostic 23548570Sbostic #define BACKWARD_COMPATIBILITY 23648570Sbostic #ifdef BACKWARD_COMPATIBILITY 23748570Sbostic if (*argv) { 23848570Sbostic interval = atoi(*argv); 23948570Sbostic if (*++argv) 24048570Sbostic reps = atoi(*argv); 24148570Sbostic } 24248570Sbostic #endif 24348570Sbostic 24448613Sbostic if (interval) { 24548613Sbostic if (!reps) 24648613Sbostic reps = -1; 24750103Skarels } else if (reps) 24850103Skarels interval = 1; 24948613Sbostic 25050103Skarels #ifdef notdef 25145834Sbostic if (todo & FORKSTAT) 25245834Sbostic doforkst(); 25350004Skarels #endif 25445834Sbostic if (todo & MEMSTAT) 25545834Sbostic domem(); 25645834Sbostic if (todo & SUMSTAT) 25745834Sbostic dosum(); 25850103Skarels #ifdef notdef 25945834Sbostic if (todo & TIMESTAT) 26045834Sbostic dotimes(); 26150004Skarels #endif 26245834Sbostic if (todo & INTRSTAT) 26345834Sbostic dointr(); 26448570Sbostic if (todo & VMSTAT) 26548570Sbostic dovmstat(interval, reps); 26645834Sbostic exit(0); 26745834Sbostic } 26810826Ssam 26948570Sbostic char ** 27048570Sbostic getdrivedata(argv) 27145834Sbostic char **argv; 27245834Sbostic { 27345834Sbostic register int i; 27445834Sbostic register char **cp; 27545834Sbostic char buf[30]; 27645834Sbostic 27748570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 27818761Ssam if (dk_ndrive <= 0) { 27948570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 28018761Ssam exit(1); 28118761Ssam } 28248570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 28348570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 28445834Sbostic for (i = 0; i < dk_ndrive; i++) 28545834Sbostic dr_name[i] = NULL; 28648570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 28748570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 288*55663Sbostic if (!read_names()) 289*55663Sbostic exit (1); 29048570Sbostic for (i = 0; i < dk_ndrive; i++) 29145834Sbostic if (dr_name[i] == NULL) { 29248570Sbostic (void)sprintf(buf, "??%d", i); 29345834Sbostic dr_name[i] = strdup(buf); 29445834Sbostic } 29545834Sbostic 29618761Ssam /* 29748570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives 29848570Sbostic * supplied as arguments, default drives. If everything isn't filled 29948570Sbostic * in and there are drives not taken care of, display the first few 30048570Sbostic * that fit. 30118761Ssam */ 30248570Sbostic #define BACKWARD_COMPATIBILITY 30348570Sbostic for (ndrives = 0; *argv; ++argv) { 30448570Sbostic #ifdef BACKWARD_COMPATIBILITY 30548570Sbostic if (isdigit(**argv)) 30648570Sbostic break; 30748570Sbostic #endif 30818761Ssam for (i = 0; i < dk_ndrive; i++) { 30948570Sbostic if (strcmp(dr_name[i], *argv)) 31018761Ssam continue; 31118761Ssam dr_select[i] = 1; 31248570Sbostic ++ndrives; 31345834Sbostic break; 31418761Ssam } 31518761Ssam } 31618761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 31718761Ssam if (dr_select[i]) 31818761Ssam continue; 31918761Ssam for (cp = defdrives; *cp; cp++) 32018761Ssam if (strcmp(dr_name[i], *cp) == 0) { 32118761Ssam dr_select[i] = 1; 32248570Sbostic ++ndrives; 32318761Ssam break; 32418761Ssam } 32518761Ssam } 32618761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 32718761Ssam if (dr_select[i]) 32818761Ssam continue; 32918761Ssam dr_select[i] = 1; 33048570Sbostic ++ndrives; 33118761Ssam } 33248570Sbostic return(argv); 33345834Sbostic } 33445834Sbostic 33545834Sbostic long 33645834Sbostic getuptime() 33745834Sbostic { 33848570Sbostic static time_t now, boottime; 33948570Sbostic time_t uptime; 34045834Sbostic 34145834Sbostic if (boottime == 0) 34248570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime)); 34348570Sbostic (void)time(&now); 34445834Sbostic uptime = now - boottime; 34545834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 34648570Sbostic (void)fprintf(stderr, 34745834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 34845834Sbostic exit(1); 34945834Sbostic } 35048570Sbostic return(uptime); 35145834Sbostic } 35245834Sbostic 35350006Skarels int hz, hdrcnt; 35448613Sbostic 35548570Sbostic void 35648570Sbostic dovmstat(interval, reps) 35748570Sbostic u_int interval; 35848570Sbostic int reps; 35945834Sbostic { 36048570Sbostic struct vmtotal total; 36150103Skarels time_t uptime, halfuptime; 36250004Skarels void needhdr(); 36351359Smckusick int size; 36445834Sbostic 36548570Sbostic uptime = getuptime(); 36650103Skarels halfuptime = uptime / 2; 36750004Skarels (void)signal(SIGCONT, needhdr); 36848570Sbostic 36954272Smccanne if (nl[X_STATHZ].n_type != 0 && nl[X_STATHZ].n_value != 0) 37054272Smccanne kread(X_STATHZ, &hz, sizeof(hz)); 37148613Sbostic if (!hz) 37248613Sbostic kread(X_HZ, &hz, sizeof(hz)); 37348570Sbostic 37448570Sbostic for (hdrcnt = 1;;) { 37550004Skarels if (!--hdrcnt) 37648570Sbostic printhdr(); 37748570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time)); 37848570Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 37950006Skarels kread(X_SUM, &sum, sizeof(sum)); 38051359Smckusick size = sizeof(total); 38151359Smckusick if (getkerninfo(KINFO_METER, &total, &size, 0) < 0) { 38251359Smckusick printf("Can't get kerninfo: %s\n", strerror(errno)); 38351359Smckusick bzero(&total, sizeof(total)); 38451359Smckusick } 38551359Smckusick (void)printf("%2d%2d%2d", 38648570Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 38751359Smckusick #define pgtok(a) ((a) * sum.v_page_size >> 10) 38850103Skarels #define rate(x) (((x) + halfuptime) / uptime) /* round */ 38951359Smckusick (void)printf("%6ld%6ld ", 39048570Sbostic pgtok(total.t_avm), pgtok(total.t_free)); 39150006Skarels #ifdef NEWVM 39251359Smckusick (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults)); 39350006Skarels (void)printf("%3lu ", 39451359Smckusick rate(sum.v_reactivated - osum.v_reactivated)); 39551359Smckusick (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins)); 39650006Skarels (void)printf("%3lu %3lu ", 39751359Smckusick rate(sum.v_pageouts - osum.v_pageouts), 0); 39850006Skarels #else 39950006Skarels (void)printf("%3lu %2lu ", 40050103Skarels rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - 40150103Skarels (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))), 40250103Skarels rate(sum.v_xsfrec + sum.v_xifrec - 40350103Skarels osum.v_xsfrec - osum.v_xifrec)); 40450006Skarels (void)printf("%3lu ", 40550103Skarels rate(pgtok(sum.v_pgpgin - osum.v_pgpgin))); 40650006Skarels (void)printf("%3lu %3lu ", 40750103Skarels rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)), 40850103Skarels rate(pgtok(sum.v_dfree - osum.v_dfree))); 40950006Skarels (void)printf("%3d ", pgtok(deficit)); 41050006Skarels #endif 41150103Skarels (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan)); 41248613Sbostic dkstats(); 41350006Skarels (void)printf("%4lu %4lu %3lu ", 41450103Skarels rate(sum.v_intr - osum.v_intr), 41550103Skarels rate(sum.v_syscall - osum.v_syscall), 41650103Skarels rate(sum.v_swtch - osum.v_swtch)); 41748613Sbostic cpustats(); 41848570Sbostic (void)printf("\n"); 41948570Sbostic (void)fflush(stdout); 42048613Sbostic if (reps >= 0 && --reps <= 0) 42148570Sbostic break; 42250006Skarels osum = sum; 42350103Skarels uptime = interval; 42450103Skarels /* 42550103Skarels * We round upward to avoid losing low-frequency events 42650103Skarels * (i.e., >= 1 per interval but < 1 per second). 42750103Skarels */ 42850103Skarels halfuptime = (uptime + 1) / 2; 42948613Sbostic (void)sleep(interval); 4301155Sbill } 4311155Sbill } 4321155Sbill 43317262Smckusick printhdr() 43417262Smckusick { 43548570Sbostic register int i; 43618761Ssam 43750006Skarels (void)printf(" procs memory page%*s", 20, ""); 43848570Sbostic if (ndrives > 1) 43950006Skarels (void)printf("disks %*s faults cpu\n", 44048570Sbostic ndrives * 3 - 6, ""); 44148570Sbostic else 44250006Skarels (void)printf("%*s faults cpu\n", ndrives * 3, ""); 44350006Skarels #ifndef NEWVM 44448570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr "); 44550006Skarels #else 44650006Skarels (void)printf(" r b w avm fre flt re pi po fr sr "); 44750006Skarels #endif 44818761Ssam for (i = 0; i < dk_ndrive; i++) 44918761Ssam if (dr_select[i]) 45048570Sbostic (void)printf("%c%c ", dr_name[i][0], 45145834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 45250006Skarels (void)printf(" in sy cs us sy id\n"); 45350004Skarels hdrcnt = winlines - 2; 45417262Smckusick } 45517262Smckusick 45650004Skarels /* 45750004Skarels * Force a header to be prepended to the next output. 45850004Skarels */ 45948570Sbostic void 46050004Skarels needhdr() 46150004Skarels { 46250004Skarels 46350004Skarels hdrcnt = 1; 46450004Skarels } 46550004Skarels 46650103Skarels #ifdef notdef 46750004Skarels void 4681155Sbill dotimes() 4691155Sbill { 47048570Sbostic u_int pgintime, rectime; 4711155Sbill 47248570Sbostic kread(X_REC, &rectime, sizeof(rectime)); 47348570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime)); 47448570Sbostic kread(X_SUM, &sum, sizeof(sum)); 47548570Sbostic (void)printf("%u reclaims, %u total time (usec)\n", 47648570Sbostic sum.v_pgrec, rectime); 47748570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 47848570Sbostic (void)printf("\n"); 47948570Sbostic (void)printf("%u page ins, %u total time (msec)\n", 48048570Sbostic sum.v_pgin, pgintime / 10); 48148570Sbostic (void)printf("average: %8.1f msec / page in\n", 48248570Sbostic pgintime / (sum.v_pgin * 10.0)); 4831155Sbill } 48450004Skarels #endif 4851155Sbill 48645834Sbostic pct(top, bot) 48745834Sbostic long top, bot; 48845834Sbostic { 48945834Sbostic if (bot == 0) 49048570Sbostic return(0); 49148570Sbostic return((top * 100) / bot); 49245834Sbostic } 49345834Sbostic 49445834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 49545834Sbostic 49630069Ssam #if defined(tahoe) 49745834Sbostic #include <machine/cpu.h> 49830069Ssam #endif 49930069Ssam 50048570Sbostic void 5011155Sbill dosum() 5021155Sbill { 50318761Ssam struct nchstats nchstats; 50450004Skarels #ifndef NEWVM 50525960Ssam struct xstats xstats; 50650004Skarels #endif 50715807Smckusick long nchtotal; 50825960Ssam #if defined(tahoe) 50925960Ssam struct keystats keystats; 51025960Ssam #endif 5111155Sbill 51248570Sbostic kread(X_SUM, &sum, sizeof(sum)); 51351359Smckusick (void)printf("%9u cpu context switches\n", sum.v_swtch); 51451359Smckusick (void)printf("%9u device interrupts\n", sum.v_intr); 51551359Smckusick (void)printf("%9u software interrupts\n", sum.v_soft); 51651359Smckusick #ifdef vax 51751359Smckusick (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 51851359Smckusick #endif 51951359Smckusick (void)printf("%9u traps\n", sum.v_trap); 52051359Smckusick (void)printf("%9u system calls\n", sum.v_syscall); 52151359Smckusick (void)printf("%9u total faults taken\n", sum.v_faults); 52248570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin); 52348570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout); 52448570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 52548570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 52651359Smckusick (void)printf("%9u page ins\n", sum.v_pageins); 52751359Smckusick (void)printf("%9u page outs\n", sum.v_pageouts); 52848570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin); 52948570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout); 53051359Smckusick (void)printf("%9u pages reactivated\n", sum.v_reactivated); 53151359Smckusick (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 53251359Smckusick (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 53351359Smckusick (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 53451359Smckusick (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 53551359Smckusick (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 53651359Smckusick #ifdef NEWVM 53751359Smckusick (void)printf("%9u VM object cache lookups\n", sum.v_lookups); 53851359Smckusick (void)printf("%9u VM object hits\n", sum.v_hits); 53951359Smckusick (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 54051359Smckusick (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 54151359Smckusick (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 54251359Smckusick (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 54351359Smckusick (void)printf("%9u pages free\n", sum.v_free_count); 54451359Smckusick (void)printf("%9u pages wired down\n", sum.v_wire_count); 54551359Smckusick (void)printf("%9u pages active\n", sum.v_active_count); 54651359Smckusick (void)printf("%9u pages inactive\n", sum.v_inactive_count); 54751359Smckusick (void)printf("%9u bytes per page\n", sum.v_page_size); 54851359Smckusick #else 54948570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 55048570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 55145834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 55248570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 55348570Sbostic (void)printf("%9u executable fill pages created\n", 55445834Sbostic sum.v_nexfod / CLSIZE); 55548570Sbostic (void)printf("%9u executable fill page faults\n", 55645834Sbostic sum.v_exfod / CLSIZE); 55748570Sbostic (void)printf("%9u swap text pages found in free list\n", 55845834Sbostic sum.v_xsfrec); 55948570Sbostic (void)printf("%9u inode text pages found in free list\n", 56045834Sbostic sum.v_xifrec); 56148570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 56248570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 56348570Sbostic (void)printf("%9u pages freed by the clock daemon\n", 56445834Sbostic sum.v_dfree / CLSIZE); 56550006Skarels #endif 56648570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 56738773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 56838773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 56938773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 57048570Sbostic (void)printf("%9ld total name lookups\n", nchtotal); 57148570Sbostic (void)printf( 57245834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 57345834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 57445834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 57545834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 57648570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 57745834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 57845834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 57945834Sbostic PCT(nchstats.ncs_long, nchtotal)); 58050004Skarels #ifndef NEWVM 58148570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats)); 58248570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 58345834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 58448570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 58525512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 58648570Sbostic (void)printf("%9lu total calls to xfree", xstats.free); 58748570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 58825512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 58950004Skarels #endif 59025960Ssam #if defined(tahoe) 59148570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 59248570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 59325960Ssam keystats.ks_allocs, "code cache keys allocated", 59445834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 59545834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 59645834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 59745834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 59848570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 59948570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 60025960Ssam keystats.ks_allocs, "data cache keys allocated", 60145834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 60245834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 60345834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 60445834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 60525960Ssam #endif 6061155Sbill } 6071155Sbill 60850103Skarels #ifdef notdef 60948570Sbostic void 6101155Sbill doforkst() 6111155Sbill { 61248570Sbostic struct forkstat fks; 6131155Sbill 61448570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 61548570Sbostic (void)printf("%d forks, %d pages, average %.2f\n", 61648570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 61748570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n", 61848570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 6191155Sbill } 62050004Skarels #endif 6211155Sbill 62248570Sbostic void 62348613Sbostic dkstats() 6241155Sbill { 62548613Sbostic register int dn, state; 62648613Sbostic double etime; 62748613Sbostic long tmp; 62848613Sbostic 62948613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 63048613Sbostic tmp = cur.xfer[dn]; 63148613Sbostic cur.xfer[dn] -= last.xfer[dn]; 63248613Sbostic last.xfer[dn] = tmp; 63348613Sbostic } 63448613Sbostic etime = 0; 63548613Sbostic for (state = 0; state < CPUSTATES; ++state) { 63648613Sbostic tmp = cur.time[state]; 63748613Sbostic cur.time[state] -= last.time[state]; 63848613Sbostic last.time[state] = tmp; 63948613Sbostic etime += cur.time[state]; 64048613Sbostic } 64148613Sbostic if (etime == 0) 64248613Sbostic etime = 1; 64348613Sbostic etime /= hz; 64448613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 64548613Sbostic if (!dr_select[dn]) 64648613Sbostic continue; 64750006Skarels (void)printf("%2.0f ", cur.xfer[dn] / etime); 64848613Sbostic } 6491155Sbill } 6501155Sbill 65148613Sbostic void 65248613Sbostic cpustats() 6531155Sbill { 65448613Sbostic register int state; 65548613Sbostic double pct, total; 6561155Sbill 65748613Sbostic total = 0; 65848613Sbostic for (state = 0; state < CPUSTATES; ++state) 65948613Sbostic total += cur.time[state]; 66048613Sbostic if (total) 66148613Sbostic pct = 100 / total; 66248613Sbostic else 66348613Sbostic pct = 0; 66450006Skarels (void)printf("%2.0f ", /* user + nice */ 66548613Sbostic (cur.time[0] + cur.time[1]) * pct); 66650006Skarels (void)printf("%2.0f ", cur.time[2] * pct); /* system */ 66750006Skarels (void)printf("%2.0f", cur.time[3] * pct); /* idle */ 6681155Sbill } 6691155Sbill 67048570Sbostic void 67145834Sbostic dointr() 6721155Sbill { 67348570Sbostic register long *intrcnt, inttotal, uptime; 67445834Sbostic register int nintr, inamlen; 67545834Sbostic register char *intrname; 6761155Sbill 67748570Sbostic uptime = getuptime(); 67845834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 67945834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 68048570Sbostic intrcnt = malloc((size_t)nintr); 68145834Sbostic intrname = malloc((size_t)inamlen); 68217262Smckusick if (intrcnt == NULL || intrname == NULL) { 68348570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 68448570Sbostic exit(1); 68517262Smckusick } 68648570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr); 68745834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 68848570Sbostic (void)printf("interrupt total rate\n"); 68917262Smckusick inttotal = 0; 69045834Sbostic nintr /= sizeof(long); 69145834Sbostic while (--nintr >= 0) { 69217262Smckusick if (*intrcnt) 69348570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname, 69445834Sbostic *intrcnt, *intrcnt / uptime); 69517262Smckusick intrname += strlen(intrname) + 1; 69617262Smckusick inttotal += *intrcnt++; 69717262Smckusick } 69848570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 69917262Smckusick } 70017262Smckusick 70133610Smckusick /* 70245152Smckusick * These names are defined in <sys/malloc.h>. 70333610Smckusick */ 70445152Smckusick char *kmemnames[] = INITKMEMNAMES; 70533610Smckusick 70648570Sbostic void 70733610Smckusick domem() 70833610Smckusick { 70945834Sbostic register struct kmembuckets *kp; 71045834Sbostic register struct kmemstats *ks; 71145834Sbostic register int i; 71250004Skarels int size; 71350004Skarels long totuse = 0, totfree = 0, totreq = 0; 71433610Smckusick struct kmemstats kmemstats[M_LAST]; 71533610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 71633610Smckusick 71748570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 71848570Sbostic (void)printf("Memory statistics by bucket size\n"); 71948570Sbostic (void)printf( 72045834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 72133610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 72233610Smckusick if (kp->kb_calls == 0) 72333610Smckusick continue; 72450004Skarels size = 1 << i; 72550006Skarels (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, 72633610Smckusick kp->kb_total - kp->kb_totalfree, 72733610Smckusick kp->kb_totalfree, kp->kb_calls, 72833610Smckusick kp->kb_highwat, kp->kb_couldfree); 72950004Skarels totfree += size * kp->kb_totalfree; 73033610Smckusick } 73150004Skarels 73248570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 73348570Sbostic (void)printf("\nMemory statistics by type\n"); 73448570Sbostic (void)printf( 73548570Sbostic " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 73633610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 73733610Smckusick if (ks->ks_calls == 0) 73833610Smckusick continue; 73950006Skarels (void)printf("%10s %6ld %7ldK %8ldK %5ldK %8ld %6u %9u\n", 74048570Sbostic kmemnames[i] ? kmemnames[i] : "undefined", 74148570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 74248570Sbostic (ks->ks_maxused + 1023) / 1024, 74348570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls, 74448570Sbostic ks->ks_limblocks, ks->ks_mapblocks); 74550004Skarels totuse += ks->ks_memuse; 74650004Skarels totreq += ks->ks_calls; 74733610Smckusick } 74850004Skarels (void)printf("\nMemory Totals: In Use Free Requests\n"); 74950004Skarels (void)printf(" %7ldK %6ldK %8ld\n", 75050004Skarels (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 75133610Smckusick } 75233610Smckusick 75325708Ssam /* 75448570Sbostic * kread reads something from the kernel, given its nlist index. 75525708Ssam */ 75648570Sbostic void 75748570Sbostic kread(nlx, addr, size) 75848570Sbostic int nlx; 75948570Sbostic void *addr; 76048570Sbostic size_t size; 76125708Ssam { 76248570Sbostic char *sym; 76325708Ssam 76448570Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 76548570Sbostic sym = nl[nlx].n_name; 76648570Sbostic if (*sym == '_') 76748570Sbostic ++sym; 76848570Sbostic (void)fprintf(stderr, 76952243Sbostic "vmstat: symbol %s not defined\n", sym); 77025708Ssam exit(1); 77125708Ssam } 77254272Smccanne if (kvm_read(kd, nl[nlx].n_value, addr, size) != size) { 77348570Sbostic sym = nl[nlx].n_name; 77448570Sbostic if (*sym == '_') 77548570Sbostic ++sym; 77654272Smccanne (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd)); 77748570Sbostic exit(1); 77825708Ssam } 77925708Ssam } 78042952Sbostic 78148570Sbostic void 78248570Sbostic usage() 78342952Sbostic { 78448570Sbostic (void)fprintf(stderr, 78550004Skarels #ifndef NEWVM 78648570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \ 78750103Skarels [-N system] [-w wait] [disks]\n"); 78850004Skarels #else 78950004Skarels "usage: vmstat [-ims] [-c count] [-M core] \ 79050103Skarels [-N system] [-w wait] [disks]\n"); 79150004Skarels #endif 79248570Sbostic exit(1); 79342952Sbostic } 794