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*50004Skarels static char sccsid[] = "@(#)vmstat.c 5.28 (Berkeley) 06/04/91"; 1636580Sbostic #endif /* not lint */ 1721585Sdist 181155Sbill #include <sys/param.h> 19*50004Skarels #include <sys/time.h> 20*50004Skarels #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> 26*50004Skarels #include <sys/signal.h> 27*50004Skarels #include <sys/fcntl.h> 28*50004Skarels #include <sys/ioctl.h> 2948570Sbostic #include <time.h> 3048570Sbostic #include <nlist.h> 3148570Sbostic #include <kvm.h> 3245834Sbostic #include <errno.h> 3348570Sbostic #include <unistd.h> 3445834Sbostic #include <stdio.h> 3548570Sbostic #include <ctype.h> 3645834Sbostic #include <stdlib.h> 3745834Sbostic #include <string.h> 3837912Sbostic #include <paths.h> 391155Sbill 40*50004Skarels #ifdef SPPWAIT 41*50004Skarels #define NEWVM 42*50004Skarels #endif 43*50004Skarels #ifndef NEWVM 44*50004Skarels #include <sys/vm.h> 45*50004Skarels #include <sys/text.h> 46*50004Skarels #else 47*50004Skarels #include <sys/vmmeter.h> 48*50004Skarels #endif 49*50004Skarels 501155Sbill struct nlist nl[] = { 511448Sbill #define X_CPTIME 0 521448Sbill { "_cp_time" }, 531448Sbill #define X_RATE 1 541155Sbill { "_rate" }, 551448Sbill #define X_TOTAL 2 561155Sbill { "_total" }, 57*50004Skarels #define X_SUM 3 58*50004Skarels { "_cnt" }, 59*50004Skarels #define X_BOOTTIME 4 609249Ssam { "_boottime" }, 61*50004Skarels #define X_DKXFER 5 621448Sbill { "_dk_xfer" }, 63*50004Skarels #define X_HZ 6 643162Stoy { "_hz" }, 65*50004Skarels #define X_PHZ 7 6615266Ssam { "_phz" }, 67*50004Skarels #define X_NCHSTATS 8 6815807Smckusick { "_nchstats" }, 69*50004Skarels #define X_INTRNAMES 9 7017262Smckusick { "_intrnames" }, 71*50004Skarels #define X_EINTRNAMES 10 7217262Smckusick { "_eintrnames" }, 73*50004Skarels #define X_INTRCNT 11 7417262Smckusick { "_intrcnt" }, 75*50004Skarels #define X_EINTRCNT 12 7617262Smckusick { "_eintrcnt" }, 77*50004Skarels #define X_DK_NDRIVE 13 7818761Ssam { "_dk_ndrive" }, 79*50004Skarels #define X_KMEMSTAT 14 8033610Smckusick { "_kmemstats" }, 81*50004Skarels #define X_KMEMBUCKETS 15 8233610Smckusick { "_bucket" }, 83*50004Skarels #ifdef NEWVM 84*50004Skarels #define X_END 15 85*50004Skarels #else 86*50004Skarels #define X_DEFICIT 16 87*50004Skarels { "_deficit" }, 88*50004Skarels #define X_FORKSTAT 17 89*50004Skarels { "_forkstat" }, 90*50004Skarels #define X_REC 18 91*50004Skarels { "_rectime" }, 92*50004Skarels #define X_PGIN 19 93*50004Skarels { "_pgintime" }, 94*50004Skarels #define X_XSTATS 20 95*50004Skarels { "_xstats" }, 9648570Sbostic #define X_END 20 97*50004Skarels #endif 9848570Sbostic #ifdef hp300 9948570Sbostic #define X_HPDINIT (X_END+1) 10048570Sbostic { "_hp_dinit" }, 10110826Ssam #endif 10225708Ssam #ifdef tahoe 10342952Sbostic #define X_VBDINIT (X_END+1) 10425708Ssam { "_vbdinit" }, 10542952Sbostic #define X_CKEYSTATS (X_END+2) 10625960Ssam { "_ckeystats" }, 10742952Sbostic #define X_DKEYSTATS (X_END+3) 10825960Ssam { "_dkeystats" }, 10925708Ssam #endif 11048570Sbostic #ifdef vax 11148570Sbostic #define X_MBDINIT (X_END+1) 11248570Sbostic { "_mbdinit" }, 11348570Sbostic #define X_UBDINIT (X_END+2) 11448570Sbostic { "_ubdinit" }, 11542952Sbostic #endif 11610826Ssam { "" }, 1171155Sbill }; 1181155Sbill 11948570Sbostic struct _disk { 12048570Sbostic long time[CPUSTATES]; 12148570Sbostic long *xfer; 12248570Sbostic } cur, last; 12318761Ssam 124*50004Skarels struct vmmeter sum; 125*50004Skarels char *vmunix = _PATH_UNIX; 126*50004Skarels char **dr_name; 127*50004Skarels int *dr_select, dk_ndrive, ndrives; 1281155Sbill 129*50004Skarels int winlines = 20; 130*50004Skarels 13145834Sbostic #define FORKSTAT 0x01 13245834Sbostic #define INTRSTAT 0x02 13345834Sbostic #define MEMSTAT 0x04 13445834Sbostic #define SUMSTAT 0x08 13545834Sbostic #define TIMESTAT 0x10 13645834Sbostic #define VMSTAT 0x20 13745834Sbostic #define ZEROOUT 0x40 13845834Sbostic 13948570Sbostic #include "names.c" /* disk names -- machine dependent */ 14048570Sbostic 141*50004Skarels void cpustats(), dkstats(), dointr(), domem(), dosum(); 142*50004Skarels void dovmstat(), kread(), usage(), zero(); 143*50004Skarels #ifndef NEWVM 144*50004Skarels void dotimes(), doforkst(); 145*50004Skarels #endif 14648570Sbostic 1471155Sbill main(argc, argv) 14845834Sbostic register int argc; 14945834Sbostic register char **argv; 1501155Sbill { 15145834Sbostic extern int optind; 15245834Sbostic extern char *optarg; 15348570Sbostic register int c, todo; 15448570Sbostic u_int interval; 15548570Sbostic int reps; 15648570Sbostic char *kmem; 1571155Sbill 15848570Sbostic kmem = NULL; 15948570Sbostic interval = reps = todo = 0; 16048570Sbostic while ((c = getopt(argc, argv, "c:fiM:mN:stw:z")) != EOF) { 16145834Sbostic switch (c) { 16248570Sbostic case 'c': 16348570Sbostic reps = atoi(optarg); 16448570Sbostic break; 165*50004Skarels #ifndef NEWVM 16645834Sbostic case 'f': 16745834Sbostic todo |= FORKSTAT; 16845834Sbostic break; 169*50004Skarels #endif 17045834Sbostic case 'i': 17145834Sbostic todo |= INTRSTAT; 17245834Sbostic break; 17348570Sbostic case 'M': 17445834Sbostic kmem = optarg; 17545834Sbostic break; 17645834Sbostic case 'm': 17745834Sbostic todo |= MEMSTAT; 17845834Sbostic break; 17948570Sbostic case 'N': 18048570Sbostic vmunix = optarg; 18148570Sbostic break; 18245834Sbostic case 's': 18345834Sbostic todo |= SUMSTAT; 18445834Sbostic break; 185*50004Skarels #ifndef NEWVM 18645834Sbostic case 't': 18745834Sbostic todo |= TIMESTAT; 18845834Sbostic break; 189*50004Skarels #endif 19048570Sbostic case 'w': 19148570Sbostic interval = atoi(optarg); 19245834Sbostic break; 19345834Sbostic case 'z': 19445834Sbostic todo |= ZEROOUT; 19545834Sbostic break; 19645834Sbostic case '?': 19748570Sbostic default: 19845834Sbostic usage(); 19945834Sbostic } 20045834Sbostic } 20148570Sbostic argc -= optind; 20248570Sbostic argv += optind; 20345834Sbostic 20445834Sbostic if (todo & ZEROOUT) { 20545834Sbostic if (todo & ~ZEROOUT || kmem) 20645834Sbostic usage(); 20748570Sbostic zero(); 20845834Sbostic exit(0); 20945834Sbostic } 21045834Sbostic 21145834Sbostic if (todo == 0) 21245834Sbostic todo = VMSTAT; 21345834Sbostic 21448570Sbostic if (kvm_openfiles(vmunix, kmem, NULL) < 0) { 21548570Sbostic (void)fprintf(stderr, 21648570Sbostic "vmstat: kvm_openfiles: %s\n", kvm_geterr()); 2171155Sbill exit(1); 2181155Sbill } 21945834Sbostic 220*50004Skarels if ((c = kvm_nlist(nl)) != 0) { 221*50004Skarels if (c > 0) { 222*50004Skarels (void)fprintf(stderr, 223*50004Skarels "vmstat: undefined symbols in %s:", vmunix); 224*50004Skarels for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++) 225*50004Skarels if (nl[c].n_type == 0) 226*50004Skarels printf(" %s", nl[c].n_name); 227*50004Skarels (void)fputc('\n', stderr); 228*50004Skarels } else 229*50004Skarels (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", 230*50004Skarels kvm_geterr()); 2311155Sbill exit(1); 2321155Sbill } 2331155Sbill 23448570Sbostic if (todo & VMSTAT) { 23548570Sbostic char **getdrivedata(); 236*50004Skarels struct winsize winsize; 23748570Sbostic 23848570Sbostic argv = getdrivedata(argv); 239*50004Skarels winsize.ws_row = 0; 240*50004Skarels (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 241*50004Skarels if (winsize.ws_row > 0) 242*50004Skarels winlines = winsize.ws_row; 243*50004Skarels 24448570Sbostic } 24548570Sbostic 24648570Sbostic #define BACKWARD_COMPATIBILITY 24748570Sbostic #ifdef BACKWARD_COMPATIBILITY 24848570Sbostic if (*argv) { 24948570Sbostic interval = atoi(*argv); 25048570Sbostic if (*++argv) 25148570Sbostic reps = atoi(*argv); 25248570Sbostic } 25348570Sbostic #endif 25448570Sbostic 25548613Sbostic if (interval) { 25648613Sbostic if (!reps) 25748613Sbostic reps = -1; 25848613Sbostic } else 25948613Sbostic if (reps) 26048613Sbostic interval = 1; 26148613Sbostic 262*50004Skarels #ifndef NEWVM 26345834Sbostic if (todo & FORKSTAT) 26445834Sbostic doforkst(); 265*50004Skarels #endif 26645834Sbostic if (todo & MEMSTAT) 26745834Sbostic domem(); 26845834Sbostic if (todo & SUMSTAT) 26945834Sbostic dosum(); 270*50004Skarels #ifndef NEWVM 27145834Sbostic if (todo & TIMESTAT) 27245834Sbostic dotimes(); 273*50004Skarels #endif 27445834Sbostic if (todo & INTRSTAT) 27545834Sbostic dointr(); 27648570Sbostic if (todo & VMSTAT) 27748570Sbostic dovmstat(interval, reps); 27845834Sbostic exit(0); 27945834Sbostic } 28010826Ssam 28148570Sbostic char ** 28248570Sbostic getdrivedata(argv) 28345834Sbostic char **argv; 28445834Sbostic { 28545834Sbostic register int i; 28645834Sbostic register char **cp; 28745834Sbostic char buf[30]; 28845834Sbostic 28948570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 29018761Ssam if (dk_ndrive <= 0) { 29148570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 29218761Ssam exit(1); 29318761Ssam } 29448570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 29548570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 29645834Sbostic for (i = 0; i < dk_ndrive; i++) 29745834Sbostic dr_name[i] = NULL; 29848570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 29948570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 3003162Stoy read_names(); 30148570Sbostic for (i = 0; i < dk_ndrive; i++) 30245834Sbostic if (dr_name[i] == NULL) { 30348570Sbostic (void)sprintf(buf, "??%d", i); 30445834Sbostic dr_name[i] = strdup(buf); 30545834Sbostic } 30645834Sbostic 30718761Ssam /* 30848570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives 30948570Sbostic * supplied as arguments, default drives. If everything isn't filled 31048570Sbostic * in and there are drives not taken care of, display the first few 31148570Sbostic * that fit. 31218761Ssam */ 31348570Sbostic #define BACKWARD_COMPATIBILITY 31448570Sbostic for (ndrives = 0; *argv; ++argv) { 31548570Sbostic #ifdef BACKWARD_COMPATIBILITY 31648570Sbostic if (isdigit(**argv)) 31748570Sbostic break; 31848570Sbostic #endif 31918761Ssam for (i = 0; i < dk_ndrive; i++) { 32048570Sbostic if (strcmp(dr_name[i], *argv)) 32118761Ssam continue; 32218761Ssam dr_select[i] = 1; 32348570Sbostic ++ndrives; 32445834Sbostic break; 32518761Ssam } 32618761Ssam } 32718761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 32818761Ssam if (dr_select[i]) 32918761Ssam continue; 33018761Ssam for (cp = defdrives; *cp; cp++) 33118761Ssam if (strcmp(dr_name[i], *cp) == 0) { 33218761Ssam dr_select[i] = 1; 33348570Sbostic ++ndrives; 33418761Ssam break; 33518761Ssam } 33618761Ssam } 33718761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 33818761Ssam if (dr_select[i]) 33918761Ssam continue; 34018761Ssam dr_select[i] = 1; 34148570Sbostic ++ndrives; 34218761Ssam } 34348570Sbostic return(argv); 34445834Sbostic } 34545834Sbostic 34645834Sbostic long 34745834Sbostic getuptime() 34845834Sbostic { 34948570Sbostic static time_t now, boottime; 35048570Sbostic time_t uptime; 35145834Sbostic 35245834Sbostic if (boottime == 0) 35348570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime)); 35448570Sbostic (void)time(&now); 35545834Sbostic uptime = now - boottime; 35645834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 35748570Sbostic (void)fprintf(stderr, 35845834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 35945834Sbostic exit(1); 36045834Sbostic } 36148570Sbostic return(uptime); 36245834Sbostic } 36345834Sbostic 364*50004Skarels int hz, hdrcnt; 36548613Sbostic 36648570Sbostic void 36748570Sbostic dovmstat(interval, reps) 36848570Sbostic u_int interval; 36948570Sbostic int reps; 37045834Sbostic { 37148570Sbostic struct vmmeter rate; 37248570Sbostic struct vmtotal total; 37348570Sbostic time_t uptime; 374*50004Skarels int deficit = 0; 375*50004Skarels void needhdr(); 37645834Sbostic 37748570Sbostic uptime = getuptime(); 378*50004Skarels (void)signal(SIGCONT, needhdr); 37948570Sbostic 38048570Sbostic if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 38148613Sbostic kread(X_PHZ, &hz, sizeof(hz)); 38248613Sbostic if (!hz) 38348613Sbostic kread(X_HZ, &hz, sizeof(hz)); 38448570Sbostic 38548570Sbostic for (hdrcnt = 1;;) { 386*50004Skarels if (!--hdrcnt) 38748570Sbostic printhdr(); 38848570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time)); 38948570Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 39048570Sbostic if (uptime != 1) 39148570Sbostic kread(X_SUM, &rate, sizeof(rate)); 39248570Sbostic else 39348570Sbostic kread(X_RATE, &rate, sizeof(rate)); 39448570Sbostic kread(X_TOTAL, &total, sizeof(total)); 39548570Sbostic kread(X_SUM, &sum, sizeof(sum)); 396*50004Skarels #ifndef NEWVM 39748570Sbostic kread(X_DEFICIT, &deficit, sizeof(deficit)); 398*50004Skarels #endif 39948570Sbostic (void)printf("%2d%2d%2d", 40048570Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 40145834Sbostic #define pgtok(a) ((a)*NBPG >> 10) 40248570Sbostic (void)printf("%6ld%6ld", 40348570Sbostic pgtok(total.t_avm), pgtok(total.t_free)); 40448570Sbostic (void)printf("%4lu%3lu", 40548570Sbostic (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec)) / uptime, 40648570Sbostic (rate.v_xsfrec+rate.v_xifrec) / uptime); 40748570Sbostic (void)printf("%4lu", pgtok(rate.v_pgpgin) / uptime); 40848570Sbostic (void)printf("%4lu%4lu%4d%4lu", pgtok(rate.v_pgpgout) / uptime, 40948570Sbostic pgtok(rate.v_dfree) / uptime, 41048570Sbostic pgtok(deficit), rate.v_scan / uptime); 41148613Sbostic dkstats(); 41248613Sbostic (void)printf("%4lu%4lu%4lu", rate.v_intr / uptime, 41348570Sbostic rate.v_syscall / uptime, rate.v_swtch / uptime); 41448613Sbostic cpustats(); 41548570Sbostic (void)printf("\n"); 41648570Sbostic (void)fflush(stdout); 41748570Sbostic uptime = 1; 41848613Sbostic if (reps >= 0 && --reps <= 0) 41948570Sbostic break; 42048613Sbostic (void)sleep(interval); 4211155Sbill } 4221155Sbill } 4231155Sbill 42417262Smckusick printhdr() 42517262Smckusick { 42648570Sbostic register int i; 42718761Ssam 42848570Sbostic (void)printf(" procs memory page%*s", 22, ""); 42948570Sbostic if (ndrives > 1) 43048570Sbostic (void)printf("disks %*s faults cpu\n", 43148570Sbostic ndrives * 3 - 6, ""); 43248570Sbostic else 43348570Sbostic (void)printf("%*s faults cpu\n", ndrives * 3, ""); 43448570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr "); 43518761Ssam for (i = 0; i < dk_ndrive; i++) 43618761Ssam if (dr_select[i]) 43748570Sbostic (void)printf("%c%c ", dr_name[i][0], 43845834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 43948570Sbostic (void)printf(" in sy cs us sy id\n"); 440*50004Skarels hdrcnt = winlines - 2; 44117262Smckusick } 44217262Smckusick 443*50004Skarels /* 444*50004Skarels * Force a header to be prepended to the next output. 445*50004Skarels */ 44648570Sbostic void 447*50004Skarels needhdr() 448*50004Skarels { 449*50004Skarels 450*50004Skarels hdrcnt = 1; 451*50004Skarels } 452*50004Skarels 453*50004Skarels #ifndef NEWVM 454*50004Skarels void 4551155Sbill dotimes() 4561155Sbill { 45748570Sbostic u_int pgintime, rectime; 4581155Sbill 45948570Sbostic kread(X_REC, &rectime, sizeof(rectime)); 46048570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime)); 46148570Sbostic kread(X_SUM, &sum, sizeof(sum)); 46248570Sbostic (void)printf("%u reclaims, %u total time (usec)\n", 46348570Sbostic sum.v_pgrec, rectime); 46448570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 46548570Sbostic (void)printf("\n"); 46648570Sbostic (void)printf("%u page ins, %u total time (msec)\n", 46748570Sbostic sum.v_pgin, pgintime / 10); 46848570Sbostic (void)printf("average: %8.1f msec / page in\n", 46948570Sbostic pgintime / (sum.v_pgin * 10.0)); 4701155Sbill } 471*50004Skarels #endif 4721155Sbill 47345834Sbostic pct(top, bot) 47445834Sbostic long top, bot; 47545834Sbostic { 47645834Sbostic if (bot == 0) 47748570Sbostic return(0); 47848570Sbostic return((top * 100) / bot); 47945834Sbostic } 48045834Sbostic 48145834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 48245834Sbostic 48330069Ssam #if defined(tahoe) 48445834Sbostic #include <machine/cpu.h> 48530069Ssam #endif 48630069Ssam 48748570Sbostic void 4881155Sbill dosum() 4891155Sbill { 49018761Ssam struct nchstats nchstats; 491*50004Skarels #ifndef NEWVM 49225960Ssam struct xstats xstats; 493*50004Skarels #endif 49415807Smckusick long nchtotal; 49525960Ssam #if defined(tahoe) 49625960Ssam struct keystats keystats; 49725960Ssam #endif 4981155Sbill 49948570Sbostic kread(X_SUM, &sum, sizeof(sum)); 50048570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin); 50148570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout); 50248570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 50348570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 50448570Sbostic (void)printf("%9u total address trans. faults taken\n", sum.v_faults); 50548570Sbostic (void)printf("%9u page ins\n", sum.v_pgin); 50648570Sbostic (void)printf("%9u page outs\n", sum.v_pgout); 50748570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin); 50848570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout); 50948570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 51048570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 51145834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 51248570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 51348570Sbostic (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 51448570Sbostic (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 51548570Sbostic (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 51648570Sbostic (void)printf("%9u executable fill pages created\n", 51745834Sbostic sum.v_nexfod / CLSIZE); 51848570Sbostic (void)printf("%9u executable fill page faults\n", 51945834Sbostic sum.v_exfod / CLSIZE); 52048570Sbostic (void)printf("%9u swap text pages found in free list\n", 52145834Sbostic sum.v_xsfrec); 52248570Sbostic (void)printf("%9u inode text pages found in free list\n", 52345834Sbostic sum.v_xifrec); 52448570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 52548570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 52648570Sbostic (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 52748570Sbostic (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 52848570Sbostic (void)printf("%9u pages freed by the clock daemon\n", 52945834Sbostic sum.v_dfree / CLSIZE); 53048570Sbostic (void)printf("%9u cpu context switches\n", sum.v_swtch); 53148570Sbostic (void)printf("%9u device interrupts\n", sum.v_intr); 53248570Sbostic (void)printf("%9u software interrupts\n", sum.v_soft); 53318761Ssam #ifdef vax 53448570Sbostic (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 53518761Ssam #endif 53648570Sbostic (void)printf("%9u traps\n", sum.v_trap); 53748570Sbostic (void)printf("%9u system calls\n", sum.v_syscall); 53848570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 53938773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 54038773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 54138773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 54248570Sbostic (void)printf("%9ld total name lookups\n", nchtotal); 54348570Sbostic (void)printf( 54445834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 54545834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 54645834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 54745834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 54848570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 54945834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 55045834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 55145834Sbostic PCT(nchstats.ncs_long, nchtotal)); 552*50004Skarels #ifndef NEWVM 55348570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats)); 55448570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 55545834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 55648570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 55725512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 55848570Sbostic (void)printf("%9lu total calls to xfree", xstats.free); 55948570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 56025512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 561*50004Skarels #endif 56225960Ssam #if defined(tahoe) 56348570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 56448570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 56525960Ssam keystats.ks_allocs, "code cache keys allocated", 56645834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 56745834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 56845834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 56945834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 57048570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 57148570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 57225960Ssam keystats.ks_allocs, "data cache keys allocated", 57345834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 57445834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 57545834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 57645834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 57725960Ssam #endif 5781155Sbill } 5791155Sbill 580*50004Skarels #ifndef NEWVM 58148570Sbostic void 5821155Sbill doforkst() 5831155Sbill { 58448570Sbostic struct forkstat fks; 5851155Sbill 58648570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 58748570Sbostic (void)printf("%d forks, %d pages, average %.2f\n", 58848570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 58948570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n", 59048570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 5911155Sbill } 592*50004Skarels #endif 5931155Sbill 59448570Sbostic void 59548613Sbostic dkstats() 5961155Sbill { 59748613Sbostic register int dn, state; 59848613Sbostic double etime; 59948613Sbostic long tmp; 60048613Sbostic 60148613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 60248613Sbostic tmp = cur.xfer[dn]; 60348613Sbostic cur.xfer[dn] -= last.xfer[dn]; 60448613Sbostic last.xfer[dn] = tmp; 60548613Sbostic } 60648613Sbostic etime = 0; 60748613Sbostic for (state = 0; state < CPUSTATES; ++state) { 60848613Sbostic tmp = cur.time[state]; 60948613Sbostic cur.time[state] -= last.time[state]; 61048613Sbostic last.time[state] = tmp; 61148613Sbostic etime += cur.time[state]; 61248613Sbostic } 61348613Sbostic if (etime == 0) 61448613Sbostic etime = 1; 61548613Sbostic etime /= hz; 61648613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 61748613Sbostic if (!dr_select[dn]) 61848613Sbostic continue; 61948570Sbostic (void)printf("%3.0f", cur.xfer[dn] / etime); 62048613Sbostic } 6211155Sbill } 6221155Sbill 62348613Sbostic void 62448613Sbostic cpustats() 6251155Sbill { 62648613Sbostic register int state; 62748613Sbostic double pct, total; 6281155Sbill 62948613Sbostic total = 0; 63048613Sbostic for (state = 0; state < CPUSTATES; ++state) 63148613Sbostic total += cur.time[state]; 63248613Sbostic if (total) 63348613Sbostic pct = 100 / total; 63448613Sbostic else 63548613Sbostic pct = 0; 63648613Sbostic (void)printf("%3.0f", /* user + nice */ 63748613Sbostic (cur.time[0] + cur.time[1]) * pct); 63848613Sbostic (void)printf("%3.0f", cur.time[2] * pct); /* system */ 63948613Sbostic (void)printf("%3.0f", cur.time[3] * pct); /* idle */ 6401155Sbill } 6411155Sbill 64248570Sbostic void 64345834Sbostic dointr() 6441155Sbill { 64548570Sbostic register long *intrcnt, inttotal, uptime; 64645834Sbostic register int nintr, inamlen; 64745834Sbostic register char *intrname; 6481155Sbill 64948570Sbostic uptime = getuptime(); 65045834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 65145834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 65248570Sbostic intrcnt = malloc((size_t)nintr); 65345834Sbostic intrname = malloc((size_t)inamlen); 65417262Smckusick if (intrcnt == NULL || intrname == NULL) { 65548570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 65648570Sbostic exit(1); 65717262Smckusick } 65848570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr); 65945834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 66048570Sbostic (void)printf("interrupt total rate\n"); 66117262Smckusick inttotal = 0; 66245834Sbostic nintr /= sizeof(long); 66345834Sbostic while (--nintr >= 0) { 66417262Smckusick if (*intrcnt) 66548570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname, 66645834Sbostic *intrcnt, *intrcnt / uptime); 66717262Smckusick intrname += strlen(intrname) + 1; 66817262Smckusick inttotal += *intrcnt++; 66917262Smckusick } 67048570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 67117262Smckusick } 67217262Smckusick 67333610Smckusick /* 67445152Smckusick * These names are defined in <sys/malloc.h>. 67533610Smckusick */ 67645152Smckusick char *kmemnames[] = INITKMEMNAMES; 67733610Smckusick 67848570Sbostic void 67933610Smckusick domem() 68033610Smckusick { 68145834Sbostic register struct kmembuckets *kp; 68245834Sbostic register struct kmemstats *ks; 68345834Sbostic register int i; 684*50004Skarels int size; 685*50004Skarels long totuse = 0, totfree = 0, totreq = 0; 68633610Smckusick struct kmemstats kmemstats[M_LAST]; 68733610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 68833610Smckusick 68948570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 69048570Sbostic (void)printf("Memory statistics by bucket size\n"); 69148570Sbostic (void)printf( 69245834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 69333610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 69433610Smckusick if (kp->kb_calls == 0) 69533610Smckusick continue; 696*50004Skarels size = 1 << i; 697*50004Skarels (void)printf("%8d%9ld%7ld%11ld%8ld%11ld\n", size, 69833610Smckusick kp->kb_total - kp->kb_totalfree, 69933610Smckusick kp->kb_totalfree, kp->kb_calls, 70033610Smckusick kp->kb_highwat, kp->kb_couldfree); 701*50004Skarels totfree += size * kp->kb_totalfree; 702*50004Skarels totuse += size * (kp->kb_total - kp->kb_totalfree); 70333610Smckusick } 704*50004Skarels printf("%d\n", totuse); 705*50004Skarels totuse = 0; 706*50004Skarels 70748570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 70848570Sbostic (void)printf("\nMemory statistics by type\n"); 70948570Sbostic (void)printf( 71048570Sbostic " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 71133610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 71233610Smckusick if (ks->ks_calls == 0) 71333610Smckusick continue; 71448570Sbostic (void)printf("%10s%7ld%8ldK%9ldK%6ldK%9ld%7u%10u\n", 71548570Sbostic kmemnames[i] ? kmemnames[i] : "undefined", 71648570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 71748570Sbostic (ks->ks_maxused + 1023) / 1024, 71848570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls, 71948570Sbostic ks->ks_limblocks, ks->ks_mapblocks); 720*50004Skarels totuse += ks->ks_memuse; 721*50004Skarels totreq += ks->ks_calls; 72233610Smckusick } 723*50004Skarels (void)printf("\nMemory Totals: In Use Free Requests\n"); 724*50004Skarels (void)printf(" %7ldK %6ldK %8ld\n", 725*50004Skarels (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 72633610Smckusick } 72733610Smckusick 72848570Sbostic void 72948570Sbostic zero() 7303162Stoy { 73149924Sbostic static struct nlist znl[] = { 73248570Sbostic #undef X_SUM 73348570Sbostic #define X_SUM 0 73448570Sbostic { "_sum" }, 73548570Sbostic { "" }, 73648570Sbostic }; 73748570Sbostic int fd; 73848570Sbostic char *kmem; 7393162Stoy 74048570Sbostic if (geteuid()) { 74148570Sbostic (void)fprintf(stderr, "vmstat: %s\n", strerror(EPERM)); 7423162Stoy exit(1); 7433162Stoy } 74448570Sbostic /* 74548570Sbostic * Zeroing the statistics is fundamentally different 74648570Sbostic * (and really belongs in a separate program). 74748570Sbostic */ 74848570Sbostic if (nlist(vmunix, znl) || nl[0].n_type == 0) { 74948570Sbostic (void)fprintf(stderr, "vmstat: %s: symbol %s not found\n", 75048570Sbostic vmunix, nl[0].n_name); 75148570Sbostic exit(1); 7523162Stoy } 75348570Sbostic 75448570Sbostic kmem = _PATH_KMEM; 75548570Sbostic if ((fd = open(kmem, O_RDWR)) < 0) { 75648570Sbostic (void)fprintf(stderr, 75748570Sbostic "vmstat: %s: %s\n", kmem, strerror(errno)); 75848570Sbostic exit(1); 7593162Stoy } 76048570Sbostic if (lseek(fd, (long)nl[0].n_value, L_SET) == -1 || 76148570Sbostic write(fd, &sum, sizeof(sum)) != sizeof(sum)) { 76248570Sbostic (void)fprintf(stderr, 76348570Sbostic "vmstat: %s: %s\n", kmem, strerror(errno)); 76448570Sbostic exit(1); 76548570Sbostic } 7663162Stoy } 76725708Ssam 76825708Ssam /* 76948570Sbostic * kread reads something from the kernel, given its nlist index. 77025708Ssam */ 77148570Sbostic void 77248570Sbostic kread(nlx, addr, size) 77348570Sbostic int nlx; 77448570Sbostic void *addr; 77548570Sbostic size_t size; 77625708Ssam { 77748570Sbostic char *sym; 77825708Ssam 77948570Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 78048570Sbostic sym = nl[nlx].n_name; 78148570Sbostic if (*sym == '_') 78248570Sbostic ++sym; 78348570Sbostic (void)fprintf(stderr, 78448570Sbostic "vmstat: %s: symbol %s not defined\n", vmunix, sym); 78525708Ssam exit(1); 78625708Ssam } 78748570Sbostic if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { 78848570Sbostic sym = nl[nlx].n_name; 78948570Sbostic if (*sym == '_') 79048570Sbostic ++sym; 79148570Sbostic (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); 79248570Sbostic exit(1); 79325708Ssam } 79425708Ssam } 79542952Sbostic 79648570Sbostic void 79748570Sbostic usage() 79842952Sbostic { 79948570Sbostic (void)fprintf(stderr, 800*50004Skarels #ifndef NEWVM 80148570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \ 80248570Sbostic [-N system] [-w wait] [disks]\n vmstat -z\n"); 803*50004Skarels #else 804*50004Skarels "usage: vmstat [-ims] [-c count] [-M core] \ 805*50004Skarels [-N system] [-w wait] [disks]\n vmstat -z\n"); 806*50004Skarels #endif 80748570Sbostic exit(1); 80842952Sbostic } 809