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*58904Smckusick static char sccsid[] = "@(#)vmstat.c 5.42 (Berkeley) 03/31/93"; 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*58904Smckusick #include <sys/sysctl.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 */ 4456572Sbostic struct nlist namelist[] = { 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 8856176Sbostic #if defined(hp300) || defined(luna68k) 8951359Smckusick #define X_HPDINIT (X_END) 9048570Sbostic { "_hp_dinit" }, 9110826Ssam #endif 9258837Sralph #ifdef mips 9358837Sralph #define X_SCSI_DINIT (X_END) 9458837Sralph { "_scsi_dinit" }, 9558837Sralph #endif 9625708Ssam #ifdef tahoe 9751359Smckusick #define X_VBDINIT (X_END) 9825708Ssam { "_vbdinit" }, 9951359Smckusick #define X_CKEYSTATS (X_END+1) 10025960Ssam { "_ckeystats" }, 10151359Smckusick #define X_DKEYSTATS (X_END+2) 10225960Ssam { "_dkeystats" }, 10325708Ssam #endif 10448570Sbostic #ifdef vax 10551359Smckusick #define X_MBDINIT (X_END) 10648570Sbostic { "_mbdinit" }, 10751359Smckusick #define X_UBDINIT (X_END+1) 10848570Sbostic { "_ubdinit" }, 10942952Sbostic #endif 11010826Ssam { "" }, 1111155Sbill }; 1121155Sbill 11348570Sbostic struct _disk { 11448570Sbostic long time[CPUSTATES]; 11548570Sbostic long *xfer; 11648570Sbostic } cur, last; 11718761Ssam 11850006Skarels struct vmmeter sum, osum; 11950004Skarels char **dr_name; 12050004Skarels int *dr_select, dk_ndrive, ndrives; 1211155Sbill 12250004Skarels int winlines = 20; 12350004Skarels 12454272Smccanne kvm_t *kd; 12554272Smccanne 12645834Sbostic #define FORKSTAT 0x01 12745834Sbostic #define INTRSTAT 0x02 12845834Sbostic #define MEMSTAT 0x04 12945834Sbostic #define SUMSTAT 0x08 13045834Sbostic #define TIMESTAT 0x10 13145834Sbostic #define VMSTAT 0x20 13245834Sbostic 13348570Sbostic #include "names.c" /* disk names -- machine dependent */ 13448570Sbostic 13550004Skarels void cpustats(), dkstats(), dointr(), domem(), dosum(); 13650103Skarels void dovmstat(), kread(), usage(); 13750103Skarels #ifdef notdef 13850004Skarels void dotimes(), doforkst(); 13950004Skarels #endif 14048570Sbostic 1411155Sbill main(argc, argv) 14245834Sbostic register int argc; 14345834Sbostic register char **argv; 1441155Sbill { 14545834Sbostic extern int optind; 14645834Sbostic extern char *optarg; 14748570Sbostic register int c, todo; 14848570Sbostic u_int interval; 14948570Sbostic int reps; 15052243Sbostic char *memf, *nlistf; 15154272Smccanne char errbuf[_POSIX2_LINE_MAX]; 1521155Sbill 15352243Sbostic memf = nlistf = NULL; 15448570Sbostic interval = reps = todo = 0; 15550103Skarels while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) { 15645834Sbostic switch (c) { 15748570Sbostic case 'c': 15848570Sbostic reps = atoi(optarg); 15948570Sbostic break; 16050103Skarels #ifndef notdef 16145834Sbostic case 'f': 16245834Sbostic todo |= FORKSTAT; 16345834Sbostic break; 16450004Skarels #endif 16545834Sbostic case 'i': 16645834Sbostic todo |= INTRSTAT; 16745834Sbostic break; 16848570Sbostic case 'M': 16952243Sbostic memf = optarg; 17045834Sbostic break; 17145834Sbostic case 'm': 17245834Sbostic todo |= MEMSTAT; 17345834Sbostic break; 17448570Sbostic case 'N': 17552243Sbostic nlistf = optarg; 17648570Sbostic break; 17745834Sbostic case 's': 17845834Sbostic todo |= SUMSTAT; 17945834Sbostic break; 18050103Skarels #ifndef notdef 18145834Sbostic case 't': 18245834Sbostic todo |= TIMESTAT; 18345834Sbostic break; 18450004Skarels #endif 18548570Sbostic case 'w': 18648570Sbostic interval = atoi(optarg); 18745834Sbostic break; 18845834Sbostic case '?': 18948570Sbostic default: 19045834Sbostic usage(); 19145834Sbostic } 19245834Sbostic } 19348570Sbostic argc -= optind; 19448570Sbostic argv += optind; 19545834Sbostic 19645834Sbostic if (todo == 0) 19745834Sbostic todo = VMSTAT; 19845834Sbostic 19952243Sbostic /* 20052243Sbostic * Discard setgid privileges if not the running kernel so that bad 20152243Sbostic * guys can't print interesting stuff from kernel memory. 20252243Sbostic */ 20352243Sbostic if (nlistf != NULL || memf != NULL) 20452243Sbostic setgid(getgid()); 20552243Sbostic 20654272Smccanne kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 20754272Smccanne if (kd == 0) { 20848570Sbostic (void)fprintf(stderr, 20954272Smccanne "vmstat: kvm_openfiles: %s\n", errbuf); 2101155Sbill exit(1); 2111155Sbill } 21245834Sbostic 21356572Sbostic if ((c = kvm_nlist(kd, namelist)) != 0) { 21450004Skarels if (c > 0) { 21550004Skarels (void)fprintf(stderr, 21658837Sralph "vmstat: undefined symbols:"); 21756572Sbostic for (c = 0; 21856572Sbostic c < sizeof(namelist)/sizeof(namelist[0]); c++) 21956572Sbostic if (namelist[c].n_type == 0) 22058837Sralph fprintf(stderr, " %s", 22158837Sralph namelist[c].n_name); 22250004Skarels (void)fputc('\n', stderr); 22350004Skarels } else 22450004Skarels (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", 22554272Smccanne kvm_geterr(kd)); 2261155Sbill exit(1); 2271155Sbill } 2281155Sbill 22948570Sbostic if (todo & VMSTAT) { 23048570Sbostic char **getdrivedata(); 23150004Skarels struct winsize winsize; 23248570Sbostic 23348570Sbostic argv = getdrivedata(argv); 23450004Skarels winsize.ws_row = 0; 23550004Skarels (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 23650004Skarels if (winsize.ws_row > 0) 23750004Skarels winlines = winsize.ws_row; 23850004Skarels 23948570Sbostic } 24048570Sbostic 24148570Sbostic #define BACKWARD_COMPATIBILITY 24248570Sbostic #ifdef BACKWARD_COMPATIBILITY 24348570Sbostic if (*argv) { 24448570Sbostic interval = atoi(*argv); 24548570Sbostic if (*++argv) 24648570Sbostic reps = atoi(*argv); 24748570Sbostic } 24848570Sbostic #endif 24948570Sbostic 25048613Sbostic if (interval) { 25148613Sbostic if (!reps) 25248613Sbostic reps = -1; 25350103Skarels } else if (reps) 25450103Skarels interval = 1; 25548613Sbostic 25650103Skarels #ifdef notdef 25745834Sbostic if (todo & FORKSTAT) 25845834Sbostic doforkst(); 25950004Skarels #endif 26045834Sbostic if (todo & MEMSTAT) 26145834Sbostic domem(); 26245834Sbostic if (todo & SUMSTAT) 26345834Sbostic dosum(); 26450103Skarels #ifdef notdef 26545834Sbostic if (todo & TIMESTAT) 26645834Sbostic dotimes(); 26750004Skarels #endif 26845834Sbostic if (todo & INTRSTAT) 26945834Sbostic dointr(); 27048570Sbostic if (todo & VMSTAT) 27148570Sbostic dovmstat(interval, reps); 27245834Sbostic exit(0); 27345834Sbostic } 27410826Ssam 27548570Sbostic char ** 27648570Sbostic getdrivedata(argv) 27745834Sbostic char **argv; 27845834Sbostic { 27945834Sbostic register int i; 28045834Sbostic register char **cp; 28145834Sbostic char buf[30]; 28245834Sbostic 28348570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 28418761Ssam if (dk_ndrive <= 0) { 28548570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 28618761Ssam exit(1); 28718761Ssam } 28848570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 28948570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 29045834Sbostic for (i = 0; i < dk_ndrive; i++) 29145834Sbostic dr_name[i] = NULL; 29248570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 29348570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 29455663Sbostic if (!read_names()) 29555663Sbostic exit (1); 29648570Sbostic for (i = 0; i < dk_ndrive; i++) 29745834Sbostic if (dr_name[i] == NULL) { 29848570Sbostic (void)sprintf(buf, "??%d", i); 29945834Sbostic dr_name[i] = strdup(buf); 30045834Sbostic } 30145834Sbostic 30218761Ssam /* 30348570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives 30448570Sbostic * supplied as arguments, default drives. If everything isn't filled 30548570Sbostic * in and there are drives not taken care of, display the first few 30648570Sbostic * that fit. 30718761Ssam */ 30848570Sbostic #define BACKWARD_COMPATIBILITY 30948570Sbostic for (ndrives = 0; *argv; ++argv) { 31048570Sbostic #ifdef BACKWARD_COMPATIBILITY 31148570Sbostic if (isdigit(**argv)) 31248570Sbostic break; 31348570Sbostic #endif 31418761Ssam for (i = 0; i < dk_ndrive; i++) { 31548570Sbostic if (strcmp(dr_name[i], *argv)) 31618761Ssam continue; 31718761Ssam dr_select[i] = 1; 31848570Sbostic ++ndrives; 31945834Sbostic break; 32018761Ssam } 32118761Ssam } 32218761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 32318761Ssam if (dr_select[i]) 32418761Ssam continue; 32518761Ssam for (cp = defdrives; *cp; cp++) 32618761Ssam if (strcmp(dr_name[i], *cp) == 0) { 32718761Ssam dr_select[i] = 1; 32848570Sbostic ++ndrives; 32918761Ssam break; 33018761Ssam } 33118761Ssam } 33218761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 33318761Ssam if (dr_select[i]) 33418761Ssam continue; 33518761Ssam dr_select[i] = 1; 33648570Sbostic ++ndrives; 33718761Ssam } 33848570Sbostic return(argv); 33945834Sbostic } 34045834Sbostic 34145834Sbostic long 34245834Sbostic getuptime() 34345834Sbostic { 34448570Sbostic static time_t now, boottime; 34548570Sbostic time_t uptime; 34645834Sbostic 34745834Sbostic if (boottime == 0) 34848570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime)); 34948570Sbostic (void)time(&now); 35045834Sbostic uptime = now - boottime; 35145834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 35248570Sbostic (void)fprintf(stderr, 35345834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 35445834Sbostic exit(1); 35545834Sbostic } 35648570Sbostic return(uptime); 35745834Sbostic } 35845834Sbostic 35950006Skarels int hz, hdrcnt; 36048613Sbostic 36148570Sbostic void 36248570Sbostic dovmstat(interval, reps) 36348570Sbostic u_int interval; 36448570Sbostic int reps; 36545834Sbostic { 36648570Sbostic struct vmtotal total; 36750103Skarels time_t uptime, halfuptime; 36850004Skarels void needhdr(); 369*58904Smckusick int mib[2], size; 37045834Sbostic 37148570Sbostic uptime = getuptime(); 37250103Skarels halfuptime = uptime / 2; 37350004Skarels (void)signal(SIGCONT, needhdr); 37448570Sbostic 37556572Sbostic if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0) 37654272Smccanne kread(X_STATHZ, &hz, sizeof(hz)); 37748613Sbostic if (!hz) 37848613Sbostic kread(X_HZ, &hz, sizeof(hz)); 37948570Sbostic 38048570Sbostic for (hdrcnt = 1;;) { 38150004Skarels if (!--hdrcnt) 38248570Sbostic printhdr(); 38348570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time)); 38456107Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive); 38550006Skarels kread(X_SUM, &sum, sizeof(sum)); 38651359Smckusick size = sizeof(total); 387*58904Smckusick mib[0] = CTL_VM; 388*58904Smckusick mib[1] = VM_METER; 389*58904Smckusick if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) { 39051359Smckusick printf("Can't get kerninfo: %s\n", strerror(errno)); 39151359Smckusick bzero(&total, sizeof(total)); 39251359Smckusick } 39351359Smckusick (void)printf("%2d%2d%2d", 39448570Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 39551359Smckusick #define pgtok(a) ((a) * sum.v_page_size >> 10) 39650103Skarels #define rate(x) (((x) + halfuptime) / uptime) /* round */ 39751359Smckusick (void)printf("%6ld%6ld ", 39848570Sbostic pgtok(total.t_avm), pgtok(total.t_free)); 39950006Skarels #ifdef NEWVM 40051359Smckusick (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults)); 40150006Skarels (void)printf("%3lu ", 40251359Smckusick rate(sum.v_reactivated - osum.v_reactivated)); 40351359Smckusick (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins)); 40450006Skarels (void)printf("%3lu %3lu ", 40551359Smckusick rate(sum.v_pageouts - osum.v_pageouts), 0); 40650006Skarels #else 40750006Skarels (void)printf("%3lu %2lu ", 40850103Skarels rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - 40950103Skarels (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))), 41050103Skarels rate(sum.v_xsfrec + sum.v_xifrec - 41150103Skarels osum.v_xsfrec - osum.v_xifrec)); 41250006Skarels (void)printf("%3lu ", 41350103Skarels rate(pgtok(sum.v_pgpgin - osum.v_pgpgin))); 41450006Skarels (void)printf("%3lu %3lu ", 41550103Skarels rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)), 41650103Skarels rate(pgtok(sum.v_dfree - osum.v_dfree))); 41750006Skarels (void)printf("%3d ", pgtok(deficit)); 41850006Skarels #endif 41950103Skarels (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan)); 42048613Sbostic dkstats(); 42150006Skarels (void)printf("%4lu %4lu %3lu ", 42250103Skarels rate(sum.v_intr - osum.v_intr), 42350103Skarels rate(sum.v_syscall - osum.v_syscall), 42450103Skarels rate(sum.v_swtch - osum.v_swtch)); 42548613Sbostic cpustats(); 42648570Sbostic (void)printf("\n"); 42748570Sbostic (void)fflush(stdout); 42848613Sbostic if (reps >= 0 && --reps <= 0) 42948570Sbostic break; 43050006Skarels osum = sum; 43150103Skarels uptime = interval; 43250103Skarels /* 43350103Skarels * We round upward to avoid losing low-frequency events 43450103Skarels * (i.e., >= 1 per interval but < 1 per second). 43550103Skarels */ 43650103Skarels halfuptime = (uptime + 1) / 2; 43748613Sbostic (void)sleep(interval); 4381155Sbill } 4391155Sbill } 4401155Sbill 44117262Smckusick printhdr() 44217262Smckusick { 44348570Sbostic register int i; 44418761Ssam 44550006Skarels (void)printf(" procs memory page%*s", 20, ""); 44648570Sbostic if (ndrives > 1) 44750006Skarels (void)printf("disks %*s faults cpu\n", 44848570Sbostic ndrives * 3 - 6, ""); 44948570Sbostic else 45050006Skarels (void)printf("%*s faults cpu\n", ndrives * 3, ""); 45150006Skarels #ifndef NEWVM 45248570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr "); 45350006Skarels #else 45450006Skarels (void)printf(" r b w avm fre flt re pi po fr sr "); 45550006Skarels #endif 45618761Ssam for (i = 0; i < dk_ndrive; i++) 45718761Ssam if (dr_select[i]) 45848570Sbostic (void)printf("%c%c ", dr_name[i][0], 45945834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 46050006Skarels (void)printf(" in sy cs us sy id\n"); 46150004Skarels hdrcnt = winlines - 2; 46217262Smckusick } 46317262Smckusick 46450004Skarels /* 46550004Skarels * Force a header to be prepended to the next output. 46650004Skarels */ 46748570Sbostic void 46850004Skarels needhdr() 46950004Skarels { 47050004Skarels 47150004Skarels hdrcnt = 1; 47250004Skarels } 47350004Skarels 47450103Skarels #ifdef notdef 47550004Skarels void 4761155Sbill dotimes() 4771155Sbill { 47848570Sbostic u_int pgintime, rectime; 4791155Sbill 48048570Sbostic kread(X_REC, &rectime, sizeof(rectime)); 48148570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime)); 48248570Sbostic kread(X_SUM, &sum, sizeof(sum)); 48348570Sbostic (void)printf("%u reclaims, %u total time (usec)\n", 48448570Sbostic sum.v_pgrec, rectime); 48548570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 48648570Sbostic (void)printf("\n"); 48748570Sbostic (void)printf("%u page ins, %u total time (msec)\n", 48848570Sbostic sum.v_pgin, pgintime / 10); 48948570Sbostic (void)printf("average: %8.1f msec / page in\n", 49048570Sbostic pgintime / (sum.v_pgin * 10.0)); 4911155Sbill } 49250004Skarels #endif 4931155Sbill 49445834Sbostic pct(top, bot) 49545834Sbostic long top, bot; 49645834Sbostic { 49758251Smckusick long ans; 49858251Smckusick 49945834Sbostic if (bot == 0) 50048570Sbostic return(0); 50158251Smckusick ans = (quad_t)top * 100 / bot; 50258251Smckusick return (ans); 50345834Sbostic } 50445834Sbostic 50545834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 50645834Sbostic 50730069Ssam #if defined(tahoe) 50845834Sbostic #include <machine/cpu.h> 50930069Ssam #endif 51030069Ssam 51148570Sbostic void 5121155Sbill dosum() 5131155Sbill { 51418761Ssam struct nchstats nchstats; 51550004Skarels #ifndef NEWVM 51625960Ssam struct xstats xstats; 51750004Skarels #endif 51815807Smckusick long nchtotal; 51925960Ssam #if defined(tahoe) 52025960Ssam struct keystats keystats; 52125960Ssam #endif 5221155Sbill 52348570Sbostic kread(X_SUM, &sum, sizeof(sum)); 52451359Smckusick (void)printf("%9u cpu context switches\n", sum.v_swtch); 52551359Smckusick (void)printf("%9u device interrupts\n", sum.v_intr); 52651359Smckusick (void)printf("%9u software interrupts\n", sum.v_soft); 52751359Smckusick #ifdef vax 52851359Smckusick (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 52951359Smckusick #endif 53051359Smckusick (void)printf("%9u traps\n", sum.v_trap); 53151359Smckusick (void)printf("%9u system calls\n", sum.v_syscall); 53251359Smckusick (void)printf("%9u total faults taken\n", sum.v_faults); 53348570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin); 53448570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout); 53548570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 53648570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 53751359Smckusick (void)printf("%9u page ins\n", sum.v_pageins); 53851359Smckusick (void)printf("%9u page outs\n", sum.v_pageouts); 53948570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin); 54048570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout); 54151359Smckusick (void)printf("%9u pages reactivated\n", sum.v_reactivated); 54251359Smckusick (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 54351359Smckusick (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 54451359Smckusick (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 54551359Smckusick (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 54651359Smckusick (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 54751359Smckusick #ifdef NEWVM 54851359Smckusick (void)printf("%9u VM object cache lookups\n", sum.v_lookups); 54951359Smckusick (void)printf("%9u VM object hits\n", sum.v_hits); 55051359Smckusick (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 55151359Smckusick (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 55251359Smckusick (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 55351359Smckusick (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 55451359Smckusick (void)printf("%9u pages free\n", sum.v_free_count); 55551359Smckusick (void)printf("%9u pages wired down\n", sum.v_wire_count); 55651359Smckusick (void)printf("%9u pages active\n", sum.v_active_count); 55751359Smckusick (void)printf("%9u pages inactive\n", sum.v_inactive_count); 55851359Smckusick (void)printf("%9u bytes per page\n", sum.v_page_size); 55951359Smckusick #else 56048570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 56148570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 56245834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 56348570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 56448570Sbostic (void)printf("%9u executable fill pages created\n", 56545834Sbostic sum.v_nexfod / CLSIZE); 56648570Sbostic (void)printf("%9u executable fill page faults\n", 56745834Sbostic sum.v_exfod / CLSIZE); 56848570Sbostic (void)printf("%9u swap text pages found in free list\n", 56945834Sbostic sum.v_xsfrec); 57048570Sbostic (void)printf("%9u inode text pages found in free list\n", 57145834Sbostic sum.v_xifrec); 57248570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 57348570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 57448570Sbostic (void)printf("%9u pages freed by the clock daemon\n", 57545834Sbostic sum.v_dfree / CLSIZE); 57650006Skarels #endif 57748570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 57838773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 57938773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 58038773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 58148570Sbostic (void)printf("%9ld total name lookups\n", nchtotal); 58248570Sbostic (void)printf( 58345834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 58445834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 58545834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 58645834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 58748570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 58845834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 58945834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 59045834Sbostic PCT(nchstats.ncs_long, nchtotal)); 59150004Skarels #ifndef NEWVM 59248570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats)); 59348570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 59445834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 59548570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 59625512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 59748570Sbostic (void)printf("%9lu total calls to xfree", xstats.free); 59848570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 59925512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 60050004Skarels #endif 60125960Ssam #if defined(tahoe) 60248570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 60348570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 60425960Ssam keystats.ks_allocs, "code cache keys allocated", 60545834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 60645834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 60745834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 60845834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 60948570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 61048570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 61125960Ssam keystats.ks_allocs, "data cache keys allocated", 61245834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 61345834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 61445834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 61545834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 61625960Ssam #endif 6171155Sbill } 6181155Sbill 61950103Skarels #ifdef notdef 62048570Sbostic void 6211155Sbill doforkst() 6221155Sbill { 62348570Sbostic struct forkstat fks; 6241155Sbill 62548570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 62648570Sbostic (void)printf("%d forks, %d pages, average %.2f\n", 62748570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 62848570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n", 62948570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 6301155Sbill } 63150004Skarels #endif 6321155Sbill 63348570Sbostic void 63448613Sbostic dkstats() 6351155Sbill { 63648613Sbostic register int dn, state; 63748613Sbostic double etime; 63848613Sbostic long tmp; 63948613Sbostic 64048613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 64148613Sbostic tmp = cur.xfer[dn]; 64248613Sbostic cur.xfer[dn] -= last.xfer[dn]; 64348613Sbostic last.xfer[dn] = tmp; 64448613Sbostic } 64548613Sbostic etime = 0; 64648613Sbostic for (state = 0; state < CPUSTATES; ++state) { 64748613Sbostic tmp = cur.time[state]; 64848613Sbostic cur.time[state] -= last.time[state]; 64948613Sbostic last.time[state] = tmp; 65048613Sbostic etime += cur.time[state]; 65148613Sbostic } 65248613Sbostic if (etime == 0) 65348613Sbostic etime = 1; 65448613Sbostic etime /= hz; 65548613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 65648613Sbostic if (!dr_select[dn]) 65748613Sbostic continue; 65850006Skarels (void)printf("%2.0f ", cur.xfer[dn] / etime); 65948613Sbostic } 6601155Sbill } 6611155Sbill 66248613Sbostic void 66348613Sbostic cpustats() 6641155Sbill { 66548613Sbostic register int state; 66648613Sbostic double pct, total; 6671155Sbill 66848613Sbostic total = 0; 66948613Sbostic for (state = 0; state < CPUSTATES; ++state) 67048613Sbostic total += cur.time[state]; 67148613Sbostic if (total) 67248613Sbostic pct = 100 / total; 67348613Sbostic else 67448613Sbostic pct = 0; 67550006Skarels (void)printf("%2.0f ", /* user + nice */ 67648613Sbostic (cur.time[0] + cur.time[1]) * pct); 67750006Skarels (void)printf("%2.0f ", cur.time[2] * pct); /* system */ 67850006Skarels (void)printf("%2.0f", cur.time[3] * pct); /* idle */ 6791155Sbill } 6801155Sbill 68148570Sbostic void 68245834Sbostic dointr() 6831155Sbill { 68448570Sbostic register long *intrcnt, inttotal, uptime; 68545834Sbostic register int nintr, inamlen; 68645834Sbostic register char *intrname; 6871155Sbill 68848570Sbostic uptime = getuptime(); 68956572Sbostic nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value; 69056572Sbostic inamlen = 69156572Sbostic namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value; 69248570Sbostic intrcnt = malloc((size_t)nintr); 69345834Sbostic intrname = malloc((size_t)inamlen); 69417262Smckusick if (intrcnt == NULL || intrname == NULL) { 69548570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 69648570Sbostic exit(1); 69717262Smckusick } 69848570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr); 69945834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 70048570Sbostic (void)printf("interrupt total rate\n"); 70117262Smckusick inttotal = 0; 70245834Sbostic nintr /= sizeof(long); 70345834Sbostic while (--nintr >= 0) { 70417262Smckusick if (*intrcnt) 70548570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname, 70645834Sbostic *intrcnt, *intrcnt / uptime); 70717262Smckusick intrname += strlen(intrname) + 1; 70817262Smckusick inttotal += *intrcnt++; 70917262Smckusick } 71048570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 71117262Smckusick } 71217262Smckusick 71333610Smckusick /* 71445152Smckusick * These names are defined in <sys/malloc.h>. 71533610Smckusick */ 71645152Smckusick char *kmemnames[] = INITKMEMNAMES; 71733610Smckusick 71848570Sbostic void 71933610Smckusick domem() 72033610Smckusick { 72145834Sbostic register struct kmembuckets *kp; 72245834Sbostic register struct kmemstats *ks; 72356612Smckusick register int i, j; 72456612Smckusick int len, size, first; 72550004Skarels long totuse = 0, totfree = 0, totreq = 0; 72656612Smckusick char *name; 72733610Smckusick struct kmemstats kmemstats[M_LAST]; 72833610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 72933610Smckusick 73048570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 73148570Sbostic (void)printf("Memory statistics by bucket size\n"); 73248570Sbostic (void)printf( 73345834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 73433610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 73533610Smckusick if (kp->kb_calls == 0) 73633610Smckusick continue; 73750004Skarels size = 1 << i; 73850006Skarels (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, 73933610Smckusick kp->kb_total - kp->kb_totalfree, 74033610Smckusick kp->kb_totalfree, kp->kb_calls, 74133610Smckusick kp->kb_highwat, kp->kb_couldfree); 74250004Skarels totfree += size * kp->kb_totalfree; 74333610Smckusick } 74450004Skarels 74548570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 74656612Smckusick (void)printf("\nMemory usage type by bucket size\n"); 74756612Smckusick (void)printf(" Size Type(s)\n"); 74856612Smckusick kp = &buckets[MINBUCKET]; 74956612Smckusick for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) { 75056612Smckusick if (kp->kb_calls == 0) 75156612Smckusick continue; 75256612Smckusick first = 1; 75356612Smckusick len = 8; 75456612Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 75556612Smckusick if (ks->ks_calls == 0) 75656612Smckusick continue; 75756612Smckusick if ((ks->ks_size & j) == 0) 75856612Smckusick continue; 75956612Smckusick name = kmemnames[i] ? kmemnames[i] : "undefined"; 76056612Smckusick len += 2 + strlen(name); 76156612Smckusick if (first) 76256612Smckusick printf("%8d %s", j, name); 76356612Smckusick else 76456612Smckusick printf(","); 76556612Smckusick if (len >= 80) { 76656612Smckusick printf("\n\t "); 76756612Smckusick len = 10 + strlen(name); 76856612Smckusick } 76956612Smckusick if (!first) 77056612Smckusick printf(" %s", name); 77156612Smckusick first = 0; 77256612Smckusick } 77356612Smckusick printf("\n"); 77456612Smckusick } 77556612Smckusick 77648570Sbostic (void)printf( 77756612Smckusick "\nMemory statistics by type Type Kern\n"); 77856612Smckusick (void)printf( 77956612Smckusick " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n"); 78033610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 78133610Smckusick if (ks->ks_calls == 0) 78233610Smckusick continue; 78356612Smckusick (void)printf("%11s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u", 78448570Sbostic kmemnames[i] ? kmemnames[i] : "undefined", 78548570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 78648570Sbostic (ks->ks_maxused + 1023) / 1024, 78748570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls, 78848570Sbostic ks->ks_limblocks, ks->ks_mapblocks); 78956612Smckusick first = 1; 79056612Smckusick for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) { 79156612Smckusick if ((ks->ks_size & j) == 0) 79256612Smckusick continue; 79356612Smckusick if (first) 79456612Smckusick printf(" %d", j); 79556612Smckusick else 79656612Smckusick printf(",%d", j); 79756612Smckusick first = 0; 79856612Smckusick } 79956612Smckusick printf("\n"); 80050004Skarels totuse += ks->ks_memuse; 80150004Skarels totreq += ks->ks_calls; 80233610Smckusick } 80350004Skarels (void)printf("\nMemory Totals: In Use Free Requests\n"); 80450004Skarels (void)printf(" %7ldK %6ldK %8ld\n", 80550004Skarels (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 80633610Smckusick } 80733610Smckusick 80825708Ssam /* 80948570Sbostic * kread reads something from the kernel, given its nlist index. 81025708Ssam */ 81148570Sbostic void 81248570Sbostic kread(nlx, addr, size) 81348570Sbostic int nlx; 81448570Sbostic void *addr; 81548570Sbostic size_t size; 81625708Ssam { 81748570Sbostic char *sym; 81825708Ssam 81956572Sbostic if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { 82056572Sbostic sym = namelist[nlx].n_name; 82148570Sbostic if (*sym == '_') 82248570Sbostic ++sym; 82348570Sbostic (void)fprintf(stderr, 82452243Sbostic "vmstat: symbol %s not defined\n", sym); 82525708Ssam exit(1); 82625708Ssam } 82756572Sbostic if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) { 82856572Sbostic sym = namelist[nlx].n_name; 82948570Sbostic if (*sym == '_') 83048570Sbostic ++sym; 83154272Smccanne (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd)); 83248570Sbostic exit(1); 83325708Ssam } 83425708Ssam } 83542952Sbostic 83648570Sbostic void 83748570Sbostic usage() 83842952Sbostic { 83948570Sbostic (void)fprintf(stderr, 84050004Skarels #ifndef NEWVM 84148570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \ 84250103Skarels [-N system] [-w wait] [disks]\n"); 84350004Skarels #else 84450004Skarels "usage: vmstat [-ims] [-c count] [-M core] \ 84550103Skarels [-N system] [-w wait] [disks]\n"); 84650004Skarels #endif 84748570Sbostic exit(1); 84842952Sbostic } 849