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*50006Skarels static char sccsid[] = "@(#)vmstat.c 5.29 (Berkeley) 06/04/91"; 1636580Sbostic #endif /* not lint */ 1721585Sdist 181155Sbill #include <sys/param.h> 1950004Skarels #include <sys/time.h> 2050004Skarels #include <sys/proc.h> 2146892Sbostic #include <sys/user.h> 2229664Ssam #include <sys/dkstat.h> 233162Stoy #include <sys/buf.h> 2417262Smckusick #include <sys/namei.h> 2533610Smckusick #include <sys/malloc.h> 2650004Skarels #include <sys/signal.h> 2750004Skarels #include <sys/fcntl.h> 2850004Skarels #include <sys/ioctl.h> 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 4050004Skarels #ifdef SPPWAIT 4150004Skarels #define NEWVM 4250004Skarels #endif 43*50006Skarels #ifdef NEWVM 44*50006Skarels #include <sys/vmmeter.h> 45*50006Skarels #include <vm/vm.h> 46*50006Skarels #include <vm/vm_statistics.h> 47*50006Skarels #else 4850004Skarels #include <sys/vm.h> 4950004Skarels #include <sys/text.h> 5050004Skarels #endif 5150004Skarels 521155Sbill struct nlist nl[] = { 531448Sbill #define X_CPTIME 0 541448Sbill { "_cp_time" }, 55*50006Skarels #define X_TOTAL 1 561155Sbill { "_total" }, 57*50006Skarels #define X_SUM 2 58*50006Skarels #define SUM "_cnt" /* XXX for now that's where it is */ 59*50006Skarels { SUM }, 60*50006Skarels #define X_BOOTTIME 3 619249Ssam { "_boottime" }, 62*50006Skarels #define X_DKXFER 4 631448Sbill { "_dk_xfer" }, 64*50006Skarels #define X_HZ 5 653162Stoy { "_hz" }, 66*50006Skarels #define X_PHZ 6 6715266Ssam { "_phz" }, 68*50006Skarels #define X_NCHSTATS 7 6915807Smckusick { "_nchstats" }, 70*50006Skarels #define X_INTRNAMES 8 7117262Smckusick { "_intrnames" }, 72*50006Skarels #define X_EINTRNAMES 9 7317262Smckusick { "_eintrnames" }, 74*50006Skarels #define X_INTRCNT 10 7517262Smckusick { "_intrcnt" }, 76*50006Skarels #define X_EINTRCNT 11 7717262Smckusick { "_eintrcnt" }, 78*50006Skarels #define X_DK_NDRIVE 12 7918761Ssam { "_dk_ndrive" }, 80*50006Skarels #define X_KMEMSTAT 13 8133610Smckusick { "_kmemstats" }, 82*50006Skarels #define X_KMEMBUCKETS 14 8333610Smckusick { "_bucket" }, 8450004Skarels #ifdef NEWVM 85*50006Skarels #define X_VMSTAT 15 86*50006Skarels { "_vm_stat" }, 8750004Skarels #define X_END 15 8850004Skarels #else 89*50006Skarels #define X_DEFICIT 15 9050004Skarels { "_deficit" }, 91*50006Skarels #define X_FORKSTAT 16 9250004Skarels { "_forkstat" }, 93*50006Skarels #define X_REC 17 9450004Skarels { "_rectime" }, 95*50006Skarels #define X_PGIN 18 9650004Skarels { "_pgintime" }, 97*50006Skarels #define X_XSTATS 19 9850004Skarels { "_xstats" }, 99*50006Skarels #define X_END 19 10050004Skarels #endif 10148570Sbostic #ifdef hp300 10248570Sbostic #define X_HPDINIT (X_END+1) 10348570Sbostic { "_hp_dinit" }, 10410826Ssam #endif 10525708Ssam #ifdef tahoe 10642952Sbostic #define X_VBDINIT (X_END+1) 10725708Ssam { "_vbdinit" }, 10842952Sbostic #define X_CKEYSTATS (X_END+2) 10925960Ssam { "_ckeystats" }, 11042952Sbostic #define X_DKEYSTATS (X_END+3) 11125960Ssam { "_dkeystats" }, 11225708Ssam #endif 11348570Sbostic #ifdef vax 11448570Sbostic #define X_MBDINIT (X_END+1) 11548570Sbostic { "_mbdinit" }, 11648570Sbostic #define X_UBDINIT (X_END+2) 11748570Sbostic { "_ubdinit" }, 11842952Sbostic #endif 11910826Ssam { "" }, 1201155Sbill }; 1211155Sbill 12248570Sbostic struct _disk { 12348570Sbostic long time[CPUSTATES]; 12448570Sbostic long *xfer; 12548570Sbostic } cur, last; 12618761Ssam 127*50006Skarels #ifdef NEWVM 128*50006Skarels struct vm_statistics vm_stat, ostat; 129*50006Skarels #endif 130*50006Skarels struct vmmeter sum, osum; 13150004Skarels char *vmunix = _PATH_UNIX; 13250004Skarels char **dr_name; 13350004Skarels int *dr_select, dk_ndrive, ndrives; 1341155Sbill 13550004Skarels int winlines = 20; 13650004Skarels 13745834Sbostic #define FORKSTAT 0x01 13845834Sbostic #define INTRSTAT 0x02 13945834Sbostic #define MEMSTAT 0x04 14045834Sbostic #define SUMSTAT 0x08 14145834Sbostic #define TIMESTAT 0x10 14245834Sbostic #define VMSTAT 0x20 14345834Sbostic #define ZEROOUT 0x40 14445834Sbostic 14548570Sbostic #include "names.c" /* disk names -- machine dependent */ 14648570Sbostic 14750004Skarels void cpustats(), dkstats(), dointr(), domem(), dosum(); 14850004Skarels void dovmstat(), kread(), usage(), zero(); 14950004Skarels #ifndef NEWVM 15050004Skarels void dotimes(), doforkst(); 15150004Skarels #endif 15248570Sbostic 1531155Sbill main(argc, argv) 15445834Sbostic register int argc; 15545834Sbostic register char **argv; 1561155Sbill { 15745834Sbostic extern int optind; 15845834Sbostic extern char *optarg; 15948570Sbostic register int c, todo; 16048570Sbostic u_int interval; 16148570Sbostic int reps; 16248570Sbostic char *kmem; 1631155Sbill 16448570Sbostic kmem = NULL; 16548570Sbostic interval = reps = todo = 0; 16648570Sbostic while ((c = getopt(argc, argv, "c:fiM:mN:stw:z")) != EOF) { 16745834Sbostic switch (c) { 16848570Sbostic case 'c': 16948570Sbostic reps = atoi(optarg); 17048570Sbostic break; 17150004Skarels #ifndef NEWVM 17245834Sbostic case 'f': 17345834Sbostic todo |= FORKSTAT; 17445834Sbostic break; 17550004Skarels #endif 17645834Sbostic case 'i': 17745834Sbostic todo |= INTRSTAT; 17845834Sbostic break; 17948570Sbostic case 'M': 18045834Sbostic kmem = optarg; 18145834Sbostic break; 18245834Sbostic case 'm': 18345834Sbostic todo |= MEMSTAT; 18445834Sbostic break; 18548570Sbostic case 'N': 18648570Sbostic vmunix = optarg; 18748570Sbostic break; 18845834Sbostic case 's': 18945834Sbostic todo |= SUMSTAT; 19045834Sbostic break; 19150004Skarels #ifndef NEWVM 19245834Sbostic case 't': 19345834Sbostic todo |= TIMESTAT; 19445834Sbostic break; 19550004Skarels #endif 19648570Sbostic case 'w': 19748570Sbostic interval = atoi(optarg); 19845834Sbostic break; 19945834Sbostic case 'z': 20045834Sbostic todo |= ZEROOUT; 20145834Sbostic break; 20245834Sbostic case '?': 20348570Sbostic default: 20445834Sbostic usage(); 20545834Sbostic } 20645834Sbostic } 20748570Sbostic argc -= optind; 20848570Sbostic argv += optind; 20945834Sbostic 21045834Sbostic if (todo & ZEROOUT) { 21145834Sbostic if (todo & ~ZEROOUT || kmem) 21245834Sbostic usage(); 21348570Sbostic zero(); 21445834Sbostic exit(0); 21545834Sbostic } 21645834Sbostic 21745834Sbostic if (todo == 0) 21845834Sbostic todo = VMSTAT; 21945834Sbostic 22048570Sbostic if (kvm_openfiles(vmunix, kmem, NULL) < 0) { 22148570Sbostic (void)fprintf(stderr, 22248570Sbostic "vmstat: kvm_openfiles: %s\n", kvm_geterr()); 2231155Sbill exit(1); 2241155Sbill } 22545834Sbostic 22650004Skarels if ((c = kvm_nlist(nl)) != 0) { 22750004Skarels if (c > 0) { 22850004Skarels (void)fprintf(stderr, 22950004Skarels "vmstat: undefined symbols in %s:", vmunix); 23050004Skarels for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++) 23150004Skarels if (nl[c].n_type == 0) 23250004Skarels printf(" %s", nl[c].n_name); 23350004Skarels (void)fputc('\n', stderr); 23450004Skarels } else 23550004Skarels (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", 23650004Skarels kvm_geterr()); 2371155Sbill exit(1); 2381155Sbill } 2391155Sbill 24048570Sbostic if (todo & VMSTAT) { 24148570Sbostic char **getdrivedata(); 24250004Skarels struct winsize winsize; 24348570Sbostic 24448570Sbostic argv = getdrivedata(argv); 24550004Skarels winsize.ws_row = 0; 24650004Skarels (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 24750004Skarels if (winsize.ws_row > 0) 24850004Skarels winlines = winsize.ws_row; 24950004Skarels 25048570Sbostic } 25148570Sbostic 25248570Sbostic #define BACKWARD_COMPATIBILITY 25348570Sbostic #ifdef BACKWARD_COMPATIBILITY 25448570Sbostic if (*argv) { 25548570Sbostic interval = atoi(*argv); 25648570Sbostic if (*++argv) 25748570Sbostic reps = atoi(*argv); 25848570Sbostic } 25948570Sbostic #endif 26048570Sbostic 26148613Sbostic if (interval) { 26248613Sbostic if (!reps) 26348613Sbostic reps = -1; 26448613Sbostic } else 26548613Sbostic if (reps) 26648613Sbostic interval = 1; 26748613Sbostic 26850004Skarels #ifndef NEWVM 26945834Sbostic if (todo & FORKSTAT) 27045834Sbostic doforkst(); 27150004Skarels #endif 27245834Sbostic if (todo & MEMSTAT) 27345834Sbostic domem(); 27445834Sbostic if (todo & SUMSTAT) 27545834Sbostic dosum(); 27650004Skarels #ifndef NEWVM 27745834Sbostic if (todo & TIMESTAT) 27845834Sbostic dotimes(); 27950004Skarels #endif 28045834Sbostic if (todo & INTRSTAT) 28145834Sbostic dointr(); 28248570Sbostic if (todo & VMSTAT) 28348570Sbostic dovmstat(interval, reps); 28445834Sbostic exit(0); 28545834Sbostic } 28610826Ssam 28748570Sbostic char ** 28848570Sbostic getdrivedata(argv) 28945834Sbostic char **argv; 29045834Sbostic { 29145834Sbostic register int i; 29245834Sbostic register char **cp; 29345834Sbostic char buf[30]; 29445834Sbostic 29548570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 29618761Ssam if (dk_ndrive <= 0) { 29748570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 29818761Ssam exit(1); 29918761Ssam } 30048570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 30148570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 30245834Sbostic for (i = 0; i < dk_ndrive; i++) 30345834Sbostic dr_name[i] = NULL; 30448570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 30548570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 3063162Stoy read_names(); 30748570Sbostic for (i = 0; i < dk_ndrive; i++) 30845834Sbostic if (dr_name[i] == NULL) { 30948570Sbostic (void)sprintf(buf, "??%d", i); 31045834Sbostic dr_name[i] = strdup(buf); 31145834Sbostic } 31245834Sbostic 31318761Ssam /* 31448570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives 31548570Sbostic * supplied as arguments, default drives. If everything isn't filled 31648570Sbostic * in and there are drives not taken care of, display the first few 31748570Sbostic * that fit. 31818761Ssam */ 31948570Sbostic #define BACKWARD_COMPATIBILITY 32048570Sbostic for (ndrives = 0; *argv; ++argv) { 32148570Sbostic #ifdef BACKWARD_COMPATIBILITY 32248570Sbostic if (isdigit(**argv)) 32348570Sbostic break; 32448570Sbostic #endif 32518761Ssam for (i = 0; i < dk_ndrive; i++) { 32648570Sbostic if (strcmp(dr_name[i], *argv)) 32718761Ssam continue; 32818761Ssam dr_select[i] = 1; 32948570Sbostic ++ndrives; 33045834Sbostic break; 33118761Ssam } 33218761Ssam } 33318761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 33418761Ssam if (dr_select[i]) 33518761Ssam continue; 33618761Ssam for (cp = defdrives; *cp; cp++) 33718761Ssam if (strcmp(dr_name[i], *cp) == 0) { 33818761Ssam dr_select[i] = 1; 33948570Sbostic ++ndrives; 34018761Ssam break; 34118761Ssam } 34218761Ssam } 34318761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 34418761Ssam if (dr_select[i]) 34518761Ssam continue; 34618761Ssam dr_select[i] = 1; 34748570Sbostic ++ndrives; 34818761Ssam } 34948570Sbostic return(argv); 35045834Sbostic } 35145834Sbostic 35245834Sbostic long 35345834Sbostic getuptime() 35445834Sbostic { 35548570Sbostic static time_t now, boottime; 35648570Sbostic time_t uptime; 35745834Sbostic 35845834Sbostic if (boottime == 0) 35948570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime)); 36048570Sbostic (void)time(&now); 36145834Sbostic uptime = now - boottime; 36245834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 36348570Sbostic (void)fprintf(stderr, 36445834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 36545834Sbostic exit(1); 36645834Sbostic } 36748570Sbostic return(uptime); 36845834Sbostic } 36945834Sbostic 370*50006Skarels int hz, hdrcnt; 37148613Sbostic 37248570Sbostic void 37348570Sbostic dovmstat(interval, reps) 37448570Sbostic u_int interval; 37548570Sbostic int reps; 37645834Sbostic { 37748570Sbostic struct vmtotal total; 37848570Sbostic time_t uptime; 37950004Skarels void needhdr(); 380*50006Skarels #ifndef NEWVM 381*50006Skarels int deficit; 382*50006Skarels #endif 38345834Sbostic 38448570Sbostic uptime = getuptime(); 38550004Skarels (void)signal(SIGCONT, needhdr); 38648570Sbostic 38748570Sbostic if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 38848613Sbostic kread(X_PHZ, &hz, sizeof(hz)); 38948613Sbostic if (!hz) 39048613Sbostic kread(X_HZ, &hz, sizeof(hz)); 39148570Sbostic 39248570Sbostic for (hdrcnt = 1;;) { 39350004Skarels if (!--hdrcnt) 39448570Sbostic printhdr(); 39548570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time)); 39648570Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 397*50006Skarels kread(X_SUM, &sum, sizeof(sum)); 39848570Sbostic kread(X_TOTAL, &total, sizeof(total)); 399*50006Skarels #ifdef NEWVM 400*50006Skarels kread(X_VMSTAT, &vm_stat, sizeof(vm_stat)); 401*50006Skarels #else 40248570Sbostic kread(X_DEFICIT, &deficit, sizeof(deficit)); 40350004Skarels #endif 404*50006Skarels (void)printf("%2d %1d %1d ", 40548570Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 40645834Sbostic #define pgtok(a) ((a)*NBPG >> 10) 407*50006Skarels (void)printf("%5ld %5ld ", 40848570Sbostic pgtok(total.t_avm), pgtok(total.t_free)); 409*50006Skarels #ifdef NEWVM 410*50006Skarels (void)printf("%4lu ", 411*50006Skarels (vm_stat.faults - ostat.faults) / uptime); 412*50006Skarels (void)printf("%3lu ", 413*50006Skarels (vm_stat.reactivations - ostat.reactivations) / uptime); 414*50006Skarels (void)printf("%3lu ", 415*50006Skarels (vm_stat.pageins - ostat.pageins) / uptime); 416*50006Skarels (void)printf("%3lu %3lu ", 417*50006Skarels (vm_stat.pageouts - ostat.pageouts) / uptime, 0); 418*50006Skarels #else 419*50006Skarels (void)printf("%3lu %2lu ", 420*50006Skarels (sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - 421*50006Skarels (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))) / uptime, 422*50006Skarels (sum.v_xsfrec + sum.v_xifrec - 423*50006Skarels osum.v_xsfrec - osum.v_xifrec) / uptime); 424*50006Skarels (void)printf("%3lu ", 425*50006Skarels pgtok(sum.v_pgpgin - osum.v_pgpgin) / uptime); 426*50006Skarels (void)printf("%3lu %3lu ", 427*50006Skarels pgtok(sum.v_pgpgout - osum.v_pgpgout) / uptime, 428*50006Skarels pgtok(sum.v_dfree - osum.v_dfree) / uptime); 429*50006Skarels (void)printf("%3d ", pgtok(deficit)); 430*50006Skarels #endif 431*50006Skarels (void)printf("%3lu ", (sum.v_scan - osum.v_scan) / uptime); 43248613Sbostic dkstats(); 433*50006Skarels (void)printf("%4lu %4lu %3lu ", 434*50006Skarels (sum.v_intr - osum.v_intr) / uptime, 435*50006Skarels (sum.v_syscall - osum.v_syscall) / uptime, 436*50006Skarels (sum.v_swtch - osum.v_swtch ) / uptime); 43748613Sbostic cpustats(); 43848570Sbostic (void)printf("\n"); 43948570Sbostic (void)fflush(stdout); 44048570Sbostic uptime = 1; 44148613Sbostic if (reps >= 0 && --reps <= 0) 44248570Sbostic break; 443*50006Skarels osum = sum; 444*50006Skarels ostat = vm_stat; 44548613Sbostic (void)sleep(interval); 4461155Sbill } 4471155Sbill } 4481155Sbill 44917262Smckusick printhdr() 45017262Smckusick { 45148570Sbostic register int i; 45218761Ssam 453*50006Skarels (void)printf(" procs memory page%*s", 20, ""); 45448570Sbostic if (ndrives > 1) 455*50006Skarels (void)printf("disks %*s faults cpu\n", 45648570Sbostic ndrives * 3 - 6, ""); 45748570Sbostic else 458*50006Skarels (void)printf("%*s faults cpu\n", ndrives * 3, ""); 459*50006Skarels #ifndef NEWVM 46048570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr "); 461*50006Skarels #else 462*50006Skarels (void)printf(" r b w avm fre flt re pi po fr sr "); 463*50006Skarels #endif 46418761Ssam for (i = 0; i < dk_ndrive; i++) 46518761Ssam if (dr_select[i]) 46648570Sbostic (void)printf("%c%c ", dr_name[i][0], 46745834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 468*50006Skarels (void)printf(" in sy cs us sy id\n"); 46950004Skarels hdrcnt = winlines - 2; 47017262Smckusick } 47117262Smckusick 47250004Skarels /* 47350004Skarels * Force a header to be prepended to the next output. 47450004Skarels */ 47548570Sbostic void 47650004Skarels needhdr() 47750004Skarels { 47850004Skarels 47950004Skarels hdrcnt = 1; 48050004Skarels } 48150004Skarels 48250004Skarels #ifndef NEWVM 48350004Skarels void 4841155Sbill dotimes() 4851155Sbill { 48648570Sbostic u_int pgintime, rectime; 4871155Sbill 48848570Sbostic kread(X_REC, &rectime, sizeof(rectime)); 48948570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime)); 49048570Sbostic kread(X_SUM, &sum, sizeof(sum)); 49148570Sbostic (void)printf("%u reclaims, %u total time (usec)\n", 49248570Sbostic sum.v_pgrec, rectime); 49348570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 49448570Sbostic (void)printf("\n"); 49548570Sbostic (void)printf("%u page ins, %u total time (msec)\n", 49648570Sbostic sum.v_pgin, pgintime / 10); 49748570Sbostic (void)printf("average: %8.1f msec / page in\n", 49848570Sbostic pgintime / (sum.v_pgin * 10.0)); 4991155Sbill } 50050004Skarels #endif 5011155Sbill 50245834Sbostic pct(top, bot) 50345834Sbostic long top, bot; 50445834Sbostic { 50545834Sbostic if (bot == 0) 50648570Sbostic return(0); 50748570Sbostic return((top * 100) / bot); 50845834Sbostic } 50945834Sbostic 51045834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 51145834Sbostic 51230069Ssam #if defined(tahoe) 51345834Sbostic #include <machine/cpu.h> 51430069Ssam #endif 51530069Ssam 51648570Sbostic void 5171155Sbill dosum() 5181155Sbill { 51918761Ssam struct nchstats nchstats; 52050004Skarels #ifndef NEWVM 52125960Ssam struct xstats xstats; 52250004Skarels #endif 52315807Smckusick long nchtotal; 52425960Ssam #if defined(tahoe) 52525960Ssam struct keystats keystats; 52625960Ssam #endif 5271155Sbill 52848570Sbostic kread(X_SUM, &sum, sizeof(sum)); 529*50006Skarels #ifdef NEWVM 530*50006Skarels kread(X_VMSTAT, &vm_stat, sizeof(vm_stat)); 531*50006Skarels #else 53248570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin); 53348570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout); 53448570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 53548570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 53648570Sbostic (void)printf("%9u total address trans. faults taken\n", sum.v_faults); 53748570Sbostic (void)printf("%9u page ins\n", sum.v_pgin); 53848570Sbostic (void)printf("%9u page outs\n", sum.v_pgout); 53948570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin); 54048570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout); 54148570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 54248570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 54345834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 54448570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 54548570Sbostic (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 54648570Sbostic (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 54748570Sbostic (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 54848570Sbostic (void)printf("%9u executable fill pages created\n", 54945834Sbostic sum.v_nexfod / CLSIZE); 55048570Sbostic (void)printf("%9u executable fill page faults\n", 55145834Sbostic sum.v_exfod / CLSIZE); 55248570Sbostic (void)printf("%9u swap text pages found in free list\n", 55345834Sbostic sum.v_xsfrec); 55448570Sbostic (void)printf("%9u inode text pages found in free list\n", 55545834Sbostic sum.v_xifrec); 55648570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 55748570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 55848570Sbostic (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 55948570Sbostic (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 56048570Sbostic (void)printf("%9u pages freed by the clock daemon\n", 56145834Sbostic sum.v_dfree / CLSIZE); 562*50006Skarels #endif 56348570Sbostic (void)printf("%9u cpu context switches\n", sum.v_swtch); 56448570Sbostic (void)printf("%9u device interrupts\n", sum.v_intr); 56548570Sbostic (void)printf("%9u software interrupts\n", sum.v_soft); 56618761Ssam #ifdef vax 56748570Sbostic (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 56818761Ssam #endif 56948570Sbostic (void)printf("%9u traps\n", sum.v_trap); 57048570Sbostic (void)printf("%9u system calls\n", sum.v_syscall); 571*50006Skarels #ifdef NEWVM 572*50006Skarels (void)printf("%9u bytes per page\n", vm_stat.pagesize); 573*50006Skarels (void)printf("%9u pages free\n", vm_stat.free_count); 574*50006Skarels (void)printf("%9u pages active\n", vm_stat.active_count); 575*50006Skarels (void)printf("%9u pages inactive\n", vm_stat.inactive_count); 576*50006Skarels (void)printf("%9u pages wired down\n", vm_stat.wire_count); 577*50006Skarels (void)printf("%9u zero-fill pages\n", vm_stat.zero_fill_count); 578*50006Skarels (void)printf("%9u pages reactivated\n", vm_stat.reactivations); 579*50006Skarels (void)printf("%9u pageins\n", vm_stat.pageins); 580*50006Skarels (void)printf("%9u pageouts\n", vm_stat.pageouts); 581*50006Skarels (void)printf("%9u VM faults\n", vm_stat.faults); 582*50006Skarels (void)printf("%9u copy-on-write faults\n", vm_stat.cow_faults); 583*50006Skarels (void)printf("%9u VM object cache lookups\n", vm_stat.lookups); 584*50006Skarels (void)printf("%9u VM object hits\n", vm_stat.hits); 585*50006Skarels #endif 586*50006Skarels 58748570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 58838773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 58938773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 59038773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 59148570Sbostic (void)printf("%9ld total name lookups\n", nchtotal); 59248570Sbostic (void)printf( 59345834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 59445834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 59545834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 59645834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 59748570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 59845834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 59945834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 60045834Sbostic PCT(nchstats.ncs_long, nchtotal)); 60150004Skarels #ifndef NEWVM 60248570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats)); 60348570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 60445834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 60548570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 60625512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 60748570Sbostic (void)printf("%9lu total calls to xfree", xstats.free); 60848570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 60925512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 61050004Skarels #endif 61125960Ssam #if defined(tahoe) 61248570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 61348570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 61425960Ssam keystats.ks_allocs, "code cache keys allocated", 61545834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 61645834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 61745834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 61845834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 61948570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 62048570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 62125960Ssam keystats.ks_allocs, "data cache keys allocated", 62245834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 62345834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 62445834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 62545834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 62625960Ssam #endif 6271155Sbill } 6281155Sbill 62950004Skarels #ifndef NEWVM 63048570Sbostic void 6311155Sbill doforkst() 6321155Sbill { 63348570Sbostic struct forkstat fks; 6341155Sbill 63548570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 63648570Sbostic (void)printf("%d forks, %d pages, average %.2f\n", 63748570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 63848570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n", 63948570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 6401155Sbill } 64150004Skarels #endif 6421155Sbill 64348570Sbostic void 64448613Sbostic dkstats() 6451155Sbill { 64648613Sbostic register int dn, state; 64748613Sbostic double etime; 64848613Sbostic long tmp; 64948613Sbostic 65048613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 65148613Sbostic tmp = cur.xfer[dn]; 65248613Sbostic cur.xfer[dn] -= last.xfer[dn]; 65348613Sbostic last.xfer[dn] = tmp; 65448613Sbostic } 65548613Sbostic etime = 0; 65648613Sbostic for (state = 0; state < CPUSTATES; ++state) { 65748613Sbostic tmp = cur.time[state]; 65848613Sbostic cur.time[state] -= last.time[state]; 65948613Sbostic last.time[state] = tmp; 66048613Sbostic etime += cur.time[state]; 66148613Sbostic } 66248613Sbostic if (etime == 0) 66348613Sbostic etime = 1; 66448613Sbostic etime /= hz; 66548613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 66648613Sbostic if (!dr_select[dn]) 66748613Sbostic continue; 668*50006Skarels (void)printf("%2.0f ", cur.xfer[dn] / etime); 66948613Sbostic } 6701155Sbill } 6711155Sbill 67248613Sbostic void 67348613Sbostic cpustats() 6741155Sbill { 67548613Sbostic register int state; 67648613Sbostic double pct, total; 6771155Sbill 67848613Sbostic total = 0; 67948613Sbostic for (state = 0; state < CPUSTATES; ++state) 68048613Sbostic total += cur.time[state]; 68148613Sbostic if (total) 68248613Sbostic pct = 100 / total; 68348613Sbostic else 68448613Sbostic pct = 0; 685*50006Skarels (void)printf("%2.0f ", /* user + nice */ 68648613Sbostic (cur.time[0] + cur.time[1]) * pct); 687*50006Skarels (void)printf("%2.0f ", cur.time[2] * pct); /* system */ 688*50006Skarels (void)printf("%2.0f", cur.time[3] * pct); /* idle */ 6891155Sbill } 6901155Sbill 69148570Sbostic void 69245834Sbostic dointr() 6931155Sbill { 69448570Sbostic register long *intrcnt, inttotal, uptime; 69545834Sbostic register int nintr, inamlen; 69645834Sbostic register char *intrname; 6971155Sbill 69848570Sbostic uptime = getuptime(); 69945834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 70045834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 70148570Sbostic intrcnt = malloc((size_t)nintr); 70245834Sbostic intrname = malloc((size_t)inamlen); 70317262Smckusick if (intrcnt == NULL || intrname == NULL) { 70448570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 70548570Sbostic exit(1); 70617262Smckusick } 70748570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr); 70845834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 70948570Sbostic (void)printf("interrupt total rate\n"); 71017262Smckusick inttotal = 0; 71145834Sbostic nintr /= sizeof(long); 71245834Sbostic while (--nintr >= 0) { 71317262Smckusick if (*intrcnt) 71448570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname, 71545834Sbostic *intrcnt, *intrcnt / uptime); 71617262Smckusick intrname += strlen(intrname) + 1; 71717262Smckusick inttotal += *intrcnt++; 71817262Smckusick } 71948570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 72017262Smckusick } 72117262Smckusick 72233610Smckusick /* 72345152Smckusick * These names are defined in <sys/malloc.h>. 72433610Smckusick */ 72545152Smckusick char *kmemnames[] = INITKMEMNAMES; 72633610Smckusick 72748570Sbostic void 72833610Smckusick domem() 72933610Smckusick { 73045834Sbostic register struct kmembuckets *kp; 73145834Sbostic register struct kmemstats *ks; 73245834Sbostic register int i; 73350004Skarels int size; 73450004Skarels long totuse = 0, totfree = 0, totreq = 0; 73533610Smckusick struct kmemstats kmemstats[M_LAST]; 73633610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 73733610Smckusick 73848570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 73948570Sbostic (void)printf("Memory statistics by bucket size\n"); 74048570Sbostic (void)printf( 74145834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 74233610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 74333610Smckusick if (kp->kb_calls == 0) 74433610Smckusick continue; 74550004Skarels size = 1 << i; 746*50006Skarels (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, 74733610Smckusick kp->kb_total - kp->kb_totalfree, 74833610Smckusick kp->kb_totalfree, kp->kb_calls, 74933610Smckusick kp->kb_highwat, kp->kb_couldfree); 75050004Skarels totfree += size * kp->kb_totalfree; 75150004Skarels totuse += size * (kp->kb_total - kp->kb_totalfree); 75233610Smckusick } 75350004Skarels 75448570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 75548570Sbostic (void)printf("\nMemory statistics by type\n"); 75648570Sbostic (void)printf( 75748570Sbostic " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 75833610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 75933610Smckusick if (ks->ks_calls == 0) 76033610Smckusick continue; 761*50006Skarels (void)printf("%10s %6ld %7ldK %8ldK %5ldK %8ld %6u %9u\n", 76248570Sbostic kmemnames[i] ? kmemnames[i] : "undefined", 76348570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 76448570Sbostic (ks->ks_maxused + 1023) / 1024, 76548570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls, 76648570Sbostic ks->ks_limblocks, ks->ks_mapblocks); 76750004Skarels totuse += ks->ks_memuse; 76850004Skarels totreq += ks->ks_calls; 76933610Smckusick } 77050004Skarels (void)printf("\nMemory Totals: In Use Free Requests\n"); 77150004Skarels (void)printf(" %7ldK %6ldK %8ld\n", 77250004Skarels (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 77333610Smckusick } 77433610Smckusick 77548570Sbostic void 77648570Sbostic zero() 7773162Stoy { 77849924Sbostic static struct nlist znl[] = { 77948570Sbostic #undef X_SUM 78048570Sbostic #define X_SUM 0 781*50006Skarels { SUM }, 78248570Sbostic { "" }, 78348570Sbostic }; 78448570Sbostic int fd; 78548570Sbostic char *kmem; 7863162Stoy 78748570Sbostic if (geteuid()) { 78848570Sbostic (void)fprintf(stderr, "vmstat: %s\n", strerror(EPERM)); 7893162Stoy exit(1); 7903162Stoy } 79148570Sbostic /* 79248570Sbostic * Zeroing the statistics is fundamentally different 79348570Sbostic * (and really belongs in a separate program). 79448570Sbostic */ 79548570Sbostic if (nlist(vmunix, znl) || nl[0].n_type == 0) { 79648570Sbostic (void)fprintf(stderr, "vmstat: %s: symbol %s not found\n", 79748570Sbostic vmunix, nl[0].n_name); 79848570Sbostic exit(1); 7993162Stoy } 80048570Sbostic 80148570Sbostic kmem = _PATH_KMEM; 80248570Sbostic if ((fd = open(kmem, O_RDWR)) < 0) { 80348570Sbostic (void)fprintf(stderr, 80448570Sbostic "vmstat: %s: %s\n", kmem, strerror(errno)); 80548570Sbostic exit(1); 8063162Stoy } 80748570Sbostic if (lseek(fd, (long)nl[0].n_value, L_SET) == -1 || 80848570Sbostic write(fd, &sum, sizeof(sum)) != sizeof(sum)) { 80948570Sbostic (void)fprintf(stderr, 81048570Sbostic "vmstat: %s: %s\n", kmem, strerror(errno)); 81148570Sbostic exit(1); 81248570Sbostic } 8133162Stoy } 81425708Ssam 81525708Ssam /* 81648570Sbostic * kread reads something from the kernel, given its nlist index. 81725708Ssam */ 81848570Sbostic void 81948570Sbostic kread(nlx, addr, size) 82048570Sbostic int nlx; 82148570Sbostic void *addr; 82248570Sbostic size_t size; 82325708Ssam { 82448570Sbostic char *sym; 82525708Ssam 82648570Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 82748570Sbostic sym = nl[nlx].n_name; 82848570Sbostic if (*sym == '_') 82948570Sbostic ++sym; 83048570Sbostic (void)fprintf(stderr, 83148570Sbostic "vmstat: %s: symbol %s not defined\n", vmunix, sym); 83225708Ssam exit(1); 83325708Ssam } 83448570Sbostic if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { 83548570Sbostic sym = nl[nlx].n_name; 83648570Sbostic if (*sym == '_') 83748570Sbostic ++sym; 83848570Sbostic (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); 83948570Sbostic exit(1); 84025708Ssam } 84125708Ssam } 84242952Sbostic 84348570Sbostic void 84448570Sbostic usage() 84542952Sbostic { 84648570Sbostic (void)fprintf(stderr, 84750004Skarels #ifndef NEWVM 84848570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \ 84948570Sbostic [-N system] [-w wait] [disks]\n vmstat -z\n"); 85050004Skarels #else 85150004Skarels "usage: vmstat [-ims] [-c count] [-M core] \ 85250004Skarels [-N system] [-w wait] [disks]\n vmstat -z\n"); 85350004Skarels #endif 85448570Sbostic exit(1); 85542952Sbostic } 856