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*50103Skarels static char sccsid[] = "@(#)vmstat.c 5.30 (Berkeley) 06/20/91"; 1636580Sbostic #endif /* not lint */ 1721585Sdist 181155Sbill #include <sys/param.h> 1950004Skarels #include <sys/time.h> 2050004Skarels #include <sys/proc.h> 2146892Sbostic #include <sys/user.h> 2229664Ssam #include <sys/dkstat.h> 233162Stoy #include <sys/buf.h> 2417262Smckusick #include <sys/namei.h> 2533610Smckusick #include <sys/malloc.h> 2650004Skarels #include <sys/signal.h> 2750004Skarels #include <sys/fcntl.h> 2850004Skarels #include <sys/ioctl.h> 29*50103Skarels #include <sys/vmmeter.h> 30*50103Skarels #include <vm/vm.h> 31*50103Skarels #include <vm/vm_statistics.h> 3248570Sbostic #include <time.h> 3348570Sbostic #include <nlist.h> 3448570Sbostic #include <kvm.h> 3545834Sbostic #include <errno.h> 3648570Sbostic #include <unistd.h> 3745834Sbostic #include <stdio.h> 3848570Sbostic #include <ctype.h> 3945834Sbostic #include <stdlib.h> 4045834Sbostic #include <string.h> 4137912Sbostic #include <paths.h> 421155Sbill 43*50103Skarels #define NEWVM /* XXX till old has been updated or purged */ 441155Sbill struct nlist nl[] = { 451448Sbill #define X_CPTIME 0 461448Sbill { "_cp_time" }, 4750006Skarels #define X_TOTAL 1 481155Sbill { "_total" }, 4950006Skarels #define X_SUM 2 50*50103Skarels { "_cnt" }, /* XXX for now that's where it is */ 5150006Skarels #define X_BOOTTIME 3 529249Ssam { "_boottime" }, 5350006Skarels #define X_DKXFER 4 541448Sbill { "_dk_xfer" }, 5550006Skarels #define X_HZ 5 563162Stoy { "_hz" }, 5750006Skarels #define X_PHZ 6 5815266Ssam { "_phz" }, 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" }, 6950006Skarels #define X_DK_NDRIVE 12 7018761Ssam { "_dk_ndrive" }, 7150006Skarels #define X_KMEMSTAT 13 7233610Smckusick { "_kmemstats" }, 7350006Skarels #define X_KMEMBUCKETS 14 7433610Smckusick { "_bucket" }, 7550006Skarels #define X_VMSTAT 15 7650006Skarels { "_vm_stat" }, 77*50103Skarels #ifdef notdef 7850006Skarels #define X_DEFICIT 15 7950004Skarels { "_deficit" }, 8050006Skarels #define X_FORKSTAT 16 8150004Skarels { "_forkstat" }, 8250006Skarels #define X_REC 17 8350004Skarels { "_rectime" }, 8450006Skarels #define X_PGIN 18 8550004Skarels { "_pgintime" }, 8650006Skarels #define X_XSTATS 19 8750004Skarels { "_xstats" }, 8850006Skarels #define X_END 19 89*50103Skarels #else 90*50103Skarels #define X_END 15 9150004Skarels #endif 9248570Sbostic #ifdef hp300 9348570Sbostic #define X_HPDINIT (X_END+1) 9448570Sbostic { "_hp_dinit" }, 9510826Ssam #endif 9625708Ssam #ifdef tahoe 9742952Sbostic #define X_VBDINIT (X_END+1) 9825708Ssam { "_vbdinit" }, 9942952Sbostic #define X_CKEYSTATS (X_END+2) 10025960Ssam { "_ckeystats" }, 10142952Sbostic #define X_DKEYSTATS (X_END+3) 10225960Ssam { "_dkeystats" }, 10325708Ssam #endif 10448570Sbostic #ifdef vax 10548570Sbostic #define X_MBDINIT (X_END+1) 10648570Sbostic { "_mbdinit" }, 10748570Sbostic #define X_UBDINIT (X_END+2) 10848570Sbostic { "_ubdinit" }, 10942952Sbostic #endif 11010826Ssam { "" }, 1111155Sbill }; 1121155Sbill 11348570Sbostic struct _disk { 11448570Sbostic long time[CPUSTATES]; 11548570Sbostic long *xfer; 11648570Sbostic } cur, last; 11718761Ssam 11850006Skarels struct vm_statistics vm_stat, ostat; 11950006Skarels struct vmmeter sum, osum; 12050004Skarels char *vmunix = _PATH_UNIX; 12150004Skarels char **dr_name; 12250004Skarels int *dr_select, dk_ndrive, ndrives; 1231155Sbill 12450004Skarels int winlines = 20; 12550004Skarels 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(); 136*50103Skarels void dovmstat(), kread(), usage(); 137*50103Skarels #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; 15048570Sbostic char *kmem; 1511155Sbill 15248570Sbostic kmem = NULL; 15348570Sbostic interval = reps = todo = 0; 154*50103Skarels while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) { 15545834Sbostic switch (c) { 15648570Sbostic case 'c': 15748570Sbostic reps = atoi(optarg); 15848570Sbostic break; 159*50103Skarels #ifndef notdef 16045834Sbostic case 'f': 16145834Sbostic todo |= FORKSTAT; 16245834Sbostic break; 16350004Skarels #endif 16445834Sbostic case 'i': 16545834Sbostic todo |= INTRSTAT; 16645834Sbostic break; 16748570Sbostic case 'M': 16845834Sbostic kmem = optarg; 16945834Sbostic break; 17045834Sbostic case 'm': 17145834Sbostic todo |= MEMSTAT; 17245834Sbostic break; 17348570Sbostic case 'N': 17448570Sbostic vmunix = optarg; 17548570Sbostic break; 17645834Sbostic case 's': 17745834Sbostic todo |= SUMSTAT; 17845834Sbostic break; 179*50103Skarels #ifndef notdef 18045834Sbostic case 't': 18145834Sbostic todo |= TIMESTAT; 18245834Sbostic break; 18350004Skarels #endif 18448570Sbostic case 'w': 18548570Sbostic interval = atoi(optarg); 18645834Sbostic break; 18745834Sbostic case '?': 18848570Sbostic default: 18945834Sbostic usage(); 19045834Sbostic } 19145834Sbostic } 19248570Sbostic argc -= optind; 19348570Sbostic argv += optind; 19445834Sbostic 19545834Sbostic if (todo == 0) 19645834Sbostic todo = VMSTAT; 19745834Sbostic 19848570Sbostic if (kvm_openfiles(vmunix, kmem, NULL) < 0) { 19948570Sbostic (void)fprintf(stderr, 20048570Sbostic "vmstat: kvm_openfiles: %s\n", kvm_geterr()); 2011155Sbill exit(1); 2021155Sbill } 20345834Sbostic 20450004Skarels if ((c = kvm_nlist(nl)) != 0) { 20550004Skarels if (c > 0) { 20650004Skarels (void)fprintf(stderr, 20750004Skarels "vmstat: undefined symbols in %s:", vmunix); 20850004Skarels for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++) 20950004Skarels if (nl[c].n_type == 0) 21050004Skarels printf(" %s", nl[c].n_name); 21150004Skarels (void)fputc('\n', stderr); 21250004Skarels } else 21350004Skarels (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", 21450004Skarels kvm_geterr()); 2151155Sbill exit(1); 2161155Sbill } 2171155Sbill 21848570Sbostic if (todo & VMSTAT) { 21948570Sbostic char **getdrivedata(); 22050004Skarels struct winsize winsize; 22148570Sbostic 22248570Sbostic argv = getdrivedata(argv); 22350004Skarels winsize.ws_row = 0; 22450004Skarels (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 22550004Skarels if (winsize.ws_row > 0) 22650004Skarels winlines = winsize.ws_row; 22750004Skarels 22848570Sbostic } 22948570Sbostic 23048570Sbostic #define BACKWARD_COMPATIBILITY 23148570Sbostic #ifdef BACKWARD_COMPATIBILITY 23248570Sbostic if (*argv) { 23348570Sbostic interval = atoi(*argv); 23448570Sbostic if (*++argv) 23548570Sbostic reps = atoi(*argv); 23648570Sbostic } 23748570Sbostic #endif 23848570Sbostic 23948613Sbostic if (interval) { 24048613Sbostic if (!reps) 24148613Sbostic reps = -1; 242*50103Skarels } else if (reps) 243*50103Skarels interval = 1; 24448613Sbostic 245*50103Skarels #ifdef notdef 24645834Sbostic if (todo & FORKSTAT) 24745834Sbostic doforkst(); 24850004Skarels #endif 24945834Sbostic if (todo & MEMSTAT) 25045834Sbostic domem(); 25145834Sbostic if (todo & SUMSTAT) 25245834Sbostic dosum(); 253*50103Skarels #ifdef notdef 25445834Sbostic if (todo & TIMESTAT) 25545834Sbostic dotimes(); 25650004Skarels #endif 25745834Sbostic if (todo & INTRSTAT) 25845834Sbostic dointr(); 25948570Sbostic if (todo & VMSTAT) 26048570Sbostic dovmstat(interval, reps); 26145834Sbostic exit(0); 26245834Sbostic } 26310826Ssam 26448570Sbostic char ** 26548570Sbostic getdrivedata(argv) 26645834Sbostic char **argv; 26745834Sbostic { 26845834Sbostic register int i; 26945834Sbostic register char **cp; 27045834Sbostic char buf[30]; 27145834Sbostic 27248570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 27318761Ssam if (dk_ndrive <= 0) { 27448570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 27518761Ssam exit(1); 27618761Ssam } 27748570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 27848570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 27945834Sbostic for (i = 0; i < dk_ndrive; i++) 28045834Sbostic dr_name[i] = NULL; 28148570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 28248570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 2833162Stoy read_names(); 28448570Sbostic for (i = 0; i < dk_ndrive; i++) 28545834Sbostic if (dr_name[i] == NULL) { 28648570Sbostic (void)sprintf(buf, "??%d", i); 28745834Sbostic dr_name[i] = strdup(buf); 28845834Sbostic } 28945834Sbostic 29018761Ssam /* 29148570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives 29248570Sbostic * supplied as arguments, default drives. If everything isn't filled 29348570Sbostic * in and there are drives not taken care of, display the first few 29448570Sbostic * that fit. 29518761Ssam */ 29648570Sbostic #define BACKWARD_COMPATIBILITY 29748570Sbostic for (ndrives = 0; *argv; ++argv) { 29848570Sbostic #ifdef BACKWARD_COMPATIBILITY 29948570Sbostic if (isdigit(**argv)) 30048570Sbostic break; 30148570Sbostic #endif 30218761Ssam for (i = 0; i < dk_ndrive; i++) { 30348570Sbostic if (strcmp(dr_name[i], *argv)) 30418761Ssam continue; 30518761Ssam dr_select[i] = 1; 30648570Sbostic ++ndrives; 30745834Sbostic break; 30818761Ssam } 30918761Ssam } 31018761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 31118761Ssam if (dr_select[i]) 31218761Ssam continue; 31318761Ssam for (cp = defdrives; *cp; cp++) 31418761Ssam if (strcmp(dr_name[i], *cp) == 0) { 31518761Ssam dr_select[i] = 1; 31648570Sbostic ++ndrives; 31718761Ssam break; 31818761Ssam } 31918761Ssam } 32018761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 32118761Ssam if (dr_select[i]) 32218761Ssam continue; 32318761Ssam dr_select[i] = 1; 32448570Sbostic ++ndrives; 32518761Ssam } 32648570Sbostic return(argv); 32745834Sbostic } 32845834Sbostic 32945834Sbostic long 33045834Sbostic getuptime() 33145834Sbostic { 33248570Sbostic static time_t now, boottime; 33348570Sbostic time_t uptime; 33445834Sbostic 33545834Sbostic if (boottime == 0) 33648570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime)); 33748570Sbostic (void)time(&now); 33845834Sbostic uptime = now - boottime; 33945834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 34048570Sbostic (void)fprintf(stderr, 34145834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 34245834Sbostic exit(1); 34345834Sbostic } 34448570Sbostic return(uptime); 34545834Sbostic } 34645834Sbostic 34750006Skarels int hz, hdrcnt; 34848613Sbostic 34948570Sbostic void 35048570Sbostic dovmstat(interval, reps) 35148570Sbostic u_int interval; 35248570Sbostic int reps; 35345834Sbostic { 35448570Sbostic struct vmtotal total; 355*50103Skarels time_t uptime, halfuptime; 35650004Skarels void needhdr(); 357*50103Skarels #ifndef notdef 35850006Skarels int deficit; 35950006Skarels #endif 36045834Sbostic 36148570Sbostic uptime = getuptime(); 362*50103Skarels halfuptime = uptime / 2; 36350004Skarels (void)signal(SIGCONT, needhdr); 36448570Sbostic 36548570Sbostic if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 36648613Sbostic kread(X_PHZ, &hz, sizeof(hz)); 36748613Sbostic if (!hz) 36848613Sbostic kread(X_HZ, &hz, sizeof(hz)); 36948570Sbostic 37048570Sbostic for (hdrcnt = 1;;) { 37150004Skarels if (!--hdrcnt) 37248570Sbostic printhdr(); 37348570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time)); 37448570Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 37550006Skarels kread(X_SUM, &sum, sizeof(sum)); 37648570Sbostic kread(X_TOTAL, &total, sizeof(total)); 37750006Skarels kread(X_VMSTAT, &vm_stat, sizeof(vm_stat)); 378*50103Skarels #ifdef notdef 37948570Sbostic kread(X_DEFICIT, &deficit, sizeof(deficit)); 38050004Skarels #endif 38150006Skarels (void)printf("%2d %1d %1d ", 38248570Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 38345834Sbostic #define pgtok(a) ((a)*NBPG >> 10) 384*50103Skarels #define rate(x) (((x) + halfuptime) / uptime) /* round */ 38550006Skarels (void)printf("%5ld %5ld ", 38648570Sbostic pgtok(total.t_avm), pgtok(total.t_free)); 38750006Skarels #ifdef NEWVM 388*50103Skarels (void)printf("%4lu ", rate(vm_stat.faults - ostat.faults)); 38950006Skarels (void)printf("%3lu ", 390*50103Skarels rate(vm_stat.reactivations - ostat.reactivations)); 391*50103Skarels (void)printf("%3lu ", rate(vm_stat.pageins - ostat.pageins)); 39250006Skarels (void)printf("%3lu %3lu ", 393*50103Skarels rate(vm_stat.pageouts - ostat.pageouts), 0); 39450006Skarels #else 39550006Skarels (void)printf("%3lu %2lu ", 396*50103Skarels rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - 397*50103Skarels (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))), 398*50103Skarels rate(sum.v_xsfrec + sum.v_xifrec - 399*50103Skarels osum.v_xsfrec - osum.v_xifrec)); 40050006Skarels (void)printf("%3lu ", 401*50103Skarels rate(pgtok(sum.v_pgpgin - osum.v_pgpgin))); 40250006Skarels (void)printf("%3lu %3lu ", 403*50103Skarels rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)), 404*50103Skarels rate(pgtok(sum.v_dfree - osum.v_dfree))); 40550006Skarels (void)printf("%3d ", pgtok(deficit)); 40650006Skarels #endif 407*50103Skarels (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan)); 40848613Sbostic dkstats(); 40950006Skarels (void)printf("%4lu %4lu %3lu ", 410*50103Skarels rate(sum.v_intr - osum.v_intr), 411*50103Skarels rate(sum.v_syscall - osum.v_syscall), 412*50103Skarels rate(sum.v_swtch - osum.v_swtch)); 41348613Sbostic cpustats(); 41448570Sbostic (void)printf("\n"); 41548570Sbostic (void)fflush(stdout); 41648613Sbostic if (reps >= 0 && --reps <= 0) 41748570Sbostic break; 41850006Skarels osum = sum; 41950006Skarels ostat = vm_stat; 420*50103Skarels uptime = interval; 421*50103Skarels /* 422*50103Skarels * We round upward to avoid losing low-frequency events 423*50103Skarels * (i.e., >= 1 per interval but < 1 per second). 424*50103Skarels */ 425*50103Skarels halfuptime = (uptime + 1) / 2; 42648613Sbostic (void)sleep(interval); 4271155Sbill } 4281155Sbill } 4291155Sbill 43017262Smckusick printhdr() 43117262Smckusick { 43248570Sbostic register int i; 43318761Ssam 43450006Skarels (void)printf(" procs memory page%*s", 20, ""); 43548570Sbostic if (ndrives > 1) 43650006Skarels (void)printf("disks %*s faults cpu\n", 43748570Sbostic ndrives * 3 - 6, ""); 43848570Sbostic else 43950006Skarels (void)printf("%*s faults cpu\n", ndrives * 3, ""); 44050006Skarels #ifndef NEWVM 44148570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr "); 44250006Skarels #else 44350006Skarels (void)printf(" r b w avm fre flt re pi po fr sr "); 44450006Skarels #endif 44518761Ssam for (i = 0; i < dk_ndrive; i++) 44618761Ssam if (dr_select[i]) 44748570Sbostic (void)printf("%c%c ", dr_name[i][0], 44845834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 44950006Skarels (void)printf(" in sy cs us sy id\n"); 45050004Skarels hdrcnt = winlines - 2; 45117262Smckusick } 45217262Smckusick 45350004Skarels /* 45450004Skarels * Force a header to be prepended to the next output. 45550004Skarels */ 45648570Sbostic void 45750004Skarels needhdr() 45850004Skarels { 45950004Skarels 46050004Skarels hdrcnt = 1; 46150004Skarels } 46250004Skarels 463*50103Skarels #ifdef notdef 46450004Skarels void 4651155Sbill dotimes() 4661155Sbill { 46748570Sbostic u_int pgintime, rectime; 4681155Sbill 46948570Sbostic kread(X_REC, &rectime, sizeof(rectime)); 47048570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime)); 47148570Sbostic kread(X_SUM, &sum, sizeof(sum)); 47248570Sbostic (void)printf("%u reclaims, %u total time (usec)\n", 47348570Sbostic sum.v_pgrec, rectime); 47448570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 47548570Sbostic (void)printf("\n"); 47648570Sbostic (void)printf("%u page ins, %u total time (msec)\n", 47748570Sbostic sum.v_pgin, pgintime / 10); 47848570Sbostic (void)printf("average: %8.1f msec / page in\n", 47948570Sbostic pgintime / (sum.v_pgin * 10.0)); 4801155Sbill } 48150004Skarels #endif 4821155Sbill 48345834Sbostic pct(top, bot) 48445834Sbostic long top, bot; 48545834Sbostic { 48645834Sbostic if (bot == 0) 48748570Sbostic return(0); 48848570Sbostic return((top * 100) / bot); 48945834Sbostic } 49045834Sbostic 49145834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 49245834Sbostic 49330069Ssam #if defined(tahoe) 49445834Sbostic #include <machine/cpu.h> 49530069Ssam #endif 49630069Ssam 49748570Sbostic void 4981155Sbill dosum() 4991155Sbill { 50018761Ssam struct nchstats nchstats; 50150004Skarels #ifndef NEWVM 50225960Ssam struct xstats xstats; 50350004Skarels #endif 50415807Smckusick long nchtotal; 50525960Ssam #if defined(tahoe) 50625960Ssam struct keystats keystats; 50725960Ssam #endif 5081155Sbill 50948570Sbostic kread(X_SUM, &sum, sizeof(sum)); 51050006Skarels #ifdef NEWVM 51150006Skarels kread(X_VMSTAT, &vm_stat, sizeof(vm_stat)); 51250006Skarels #else 51348570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin); 51448570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout); 51548570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 51648570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 51748570Sbostic (void)printf("%9u total address trans. faults taken\n", sum.v_faults); 51848570Sbostic (void)printf("%9u page ins\n", sum.v_pgin); 51948570Sbostic (void)printf("%9u page outs\n", sum.v_pgout); 52048570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin); 52148570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout); 52248570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 52348570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 52445834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 52548570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 52648570Sbostic (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 52748570Sbostic (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 52848570Sbostic (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 52948570Sbostic (void)printf("%9u executable fill pages created\n", 53045834Sbostic sum.v_nexfod / CLSIZE); 53148570Sbostic (void)printf("%9u executable fill page faults\n", 53245834Sbostic sum.v_exfod / CLSIZE); 53348570Sbostic (void)printf("%9u swap text pages found in free list\n", 53445834Sbostic sum.v_xsfrec); 53548570Sbostic (void)printf("%9u inode text pages found in free list\n", 53645834Sbostic sum.v_xifrec); 53748570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 53848570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 53948570Sbostic (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 54048570Sbostic (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 54148570Sbostic (void)printf("%9u pages freed by the clock daemon\n", 54245834Sbostic sum.v_dfree / CLSIZE); 54350006Skarels #endif 54448570Sbostic (void)printf("%9u cpu context switches\n", sum.v_swtch); 54548570Sbostic (void)printf("%9u device interrupts\n", sum.v_intr); 54648570Sbostic (void)printf("%9u software interrupts\n", sum.v_soft); 54718761Ssam #ifdef vax 54848570Sbostic (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 54918761Ssam #endif 55048570Sbostic (void)printf("%9u traps\n", sum.v_trap); 55148570Sbostic (void)printf("%9u system calls\n", sum.v_syscall); 55250006Skarels #ifdef NEWVM 55350006Skarels (void)printf("%9u bytes per page\n", vm_stat.pagesize); 55450006Skarels (void)printf("%9u pages free\n", vm_stat.free_count); 55550006Skarels (void)printf("%9u pages active\n", vm_stat.active_count); 55650006Skarels (void)printf("%9u pages inactive\n", vm_stat.inactive_count); 55750006Skarels (void)printf("%9u pages wired down\n", vm_stat.wire_count); 55850006Skarels (void)printf("%9u zero-fill pages\n", vm_stat.zero_fill_count); 55950006Skarels (void)printf("%9u pages reactivated\n", vm_stat.reactivations); 56050006Skarels (void)printf("%9u pageins\n", vm_stat.pageins); 56150006Skarels (void)printf("%9u pageouts\n", vm_stat.pageouts); 56250006Skarels (void)printf("%9u VM faults\n", vm_stat.faults); 56350006Skarels (void)printf("%9u copy-on-write faults\n", vm_stat.cow_faults); 56450006Skarels (void)printf("%9u VM object cache lookups\n", vm_stat.lookups); 56550006Skarels (void)printf("%9u VM object hits\n", vm_stat.hits); 56650006Skarels #endif 56750006Skarels 56848570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 56938773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 57038773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 57138773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 57248570Sbostic (void)printf("%9ld total name lookups\n", nchtotal); 57348570Sbostic (void)printf( 57445834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 57545834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 57645834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 57745834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 57848570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 57945834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 58045834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 58145834Sbostic PCT(nchstats.ncs_long, nchtotal)); 58250004Skarels #ifndef NEWVM 58348570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats)); 58448570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 58545834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 58648570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 58725512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 58848570Sbostic (void)printf("%9lu total calls to xfree", xstats.free); 58948570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 59025512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 59150004Skarels #endif 59225960Ssam #if defined(tahoe) 59348570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 59448570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 59525960Ssam keystats.ks_allocs, "code cache keys allocated", 59645834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 59745834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 59845834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 59945834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 60048570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 60148570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 60225960Ssam keystats.ks_allocs, "data cache keys allocated", 60345834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 60445834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 60545834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 60645834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 60725960Ssam #endif 6081155Sbill } 6091155Sbill 610*50103Skarels #ifdef notdef 61148570Sbostic void 6121155Sbill doforkst() 6131155Sbill { 61448570Sbostic struct forkstat fks; 6151155Sbill 61648570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 61748570Sbostic (void)printf("%d forks, %d pages, average %.2f\n", 61848570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 61948570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n", 62048570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 6211155Sbill } 62250004Skarels #endif 6231155Sbill 62448570Sbostic void 62548613Sbostic dkstats() 6261155Sbill { 62748613Sbostic register int dn, state; 62848613Sbostic double etime; 62948613Sbostic long tmp; 63048613Sbostic 63148613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 63248613Sbostic tmp = cur.xfer[dn]; 63348613Sbostic cur.xfer[dn] -= last.xfer[dn]; 63448613Sbostic last.xfer[dn] = tmp; 63548613Sbostic } 63648613Sbostic etime = 0; 63748613Sbostic for (state = 0; state < CPUSTATES; ++state) { 63848613Sbostic tmp = cur.time[state]; 63948613Sbostic cur.time[state] -= last.time[state]; 64048613Sbostic last.time[state] = tmp; 64148613Sbostic etime += cur.time[state]; 64248613Sbostic } 64348613Sbostic if (etime == 0) 64448613Sbostic etime = 1; 64548613Sbostic etime /= hz; 64648613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 64748613Sbostic if (!dr_select[dn]) 64848613Sbostic continue; 64950006Skarels (void)printf("%2.0f ", cur.xfer[dn] / etime); 65048613Sbostic } 6511155Sbill } 6521155Sbill 65348613Sbostic void 65448613Sbostic cpustats() 6551155Sbill { 65648613Sbostic register int state; 65748613Sbostic double pct, total; 6581155Sbill 65948613Sbostic total = 0; 66048613Sbostic for (state = 0; state < CPUSTATES; ++state) 66148613Sbostic total += cur.time[state]; 66248613Sbostic if (total) 66348613Sbostic pct = 100 / total; 66448613Sbostic else 66548613Sbostic pct = 0; 66650006Skarels (void)printf("%2.0f ", /* user + nice */ 66748613Sbostic (cur.time[0] + cur.time[1]) * pct); 66850006Skarels (void)printf("%2.0f ", cur.time[2] * pct); /* system */ 66950006Skarels (void)printf("%2.0f", cur.time[3] * pct); /* idle */ 6701155Sbill } 6711155Sbill 67248570Sbostic void 67345834Sbostic dointr() 6741155Sbill { 67548570Sbostic register long *intrcnt, inttotal, uptime; 67645834Sbostic register int nintr, inamlen; 67745834Sbostic register char *intrname; 6781155Sbill 67948570Sbostic uptime = getuptime(); 68045834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 68145834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 68248570Sbostic intrcnt = malloc((size_t)nintr); 68345834Sbostic intrname = malloc((size_t)inamlen); 68417262Smckusick if (intrcnt == NULL || intrname == NULL) { 68548570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 68648570Sbostic exit(1); 68717262Smckusick } 68848570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr); 68945834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 69048570Sbostic (void)printf("interrupt total rate\n"); 69117262Smckusick inttotal = 0; 69245834Sbostic nintr /= sizeof(long); 69345834Sbostic while (--nintr >= 0) { 69417262Smckusick if (*intrcnt) 69548570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname, 69645834Sbostic *intrcnt, *intrcnt / uptime); 69717262Smckusick intrname += strlen(intrname) + 1; 69817262Smckusick inttotal += *intrcnt++; 69917262Smckusick } 70048570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 70117262Smckusick } 70217262Smckusick 70333610Smckusick /* 70445152Smckusick * These names are defined in <sys/malloc.h>. 70533610Smckusick */ 70645152Smckusick char *kmemnames[] = INITKMEMNAMES; 70733610Smckusick 70848570Sbostic void 70933610Smckusick domem() 71033610Smckusick { 71145834Sbostic register struct kmembuckets *kp; 71245834Sbostic register struct kmemstats *ks; 71345834Sbostic register int i; 71450004Skarels int size; 71550004Skarels long totuse = 0, totfree = 0, totreq = 0; 71633610Smckusick struct kmemstats kmemstats[M_LAST]; 71733610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 71833610Smckusick 71948570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 72048570Sbostic (void)printf("Memory statistics by bucket size\n"); 72148570Sbostic (void)printf( 72245834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 72333610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 72433610Smckusick if (kp->kb_calls == 0) 72533610Smckusick continue; 72650004Skarels size = 1 << i; 72750006Skarels (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, 72833610Smckusick kp->kb_total - kp->kb_totalfree, 72933610Smckusick kp->kb_totalfree, kp->kb_calls, 73033610Smckusick kp->kb_highwat, kp->kb_couldfree); 73150004Skarels totfree += size * kp->kb_totalfree; 73250004Skarels totuse += size * (kp->kb_total - kp->kb_totalfree); 73333610Smckusick } 73450004Skarels 73548570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 73648570Sbostic (void)printf("\nMemory statistics by type\n"); 73748570Sbostic (void)printf( 73848570Sbostic " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 73933610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 74033610Smckusick if (ks->ks_calls == 0) 74133610Smckusick continue; 74250006Skarels (void)printf("%10s %6ld %7ldK %8ldK %5ldK %8ld %6u %9u\n", 74348570Sbostic kmemnames[i] ? kmemnames[i] : "undefined", 74448570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 74548570Sbostic (ks->ks_maxused + 1023) / 1024, 74648570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls, 74748570Sbostic ks->ks_limblocks, ks->ks_mapblocks); 74850004Skarels totuse += ks->ks_memuse; 74950004Skarels totreq += ks->ks_calls; 75033610Smckusick } 75150004Skarels (void)printf("\nMemory Totals: In Use Free Requests\n"); 75250004Skarels (void)printf(" %7ldK %6ldK %8ld\n", 75350004Skarels (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 75433610Smckusick } 75533610Smckusick 75625708Ssam /* 75748570Sbostic * kread reads something from the kernel, given its nlist index. 75825708Ssam */ 75948570Sbostic void 76048570Sbostic kread(nlx, addr, size) 76148570Sbostic int nlx; 76248570Sbostic void *addr; 76348570Sbostic size_t size; 76425708Ssam { 76548570Sbostic char *sym; 76625708Ssam 76748570Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 76848570Sbostic sym = nl[nlx].n_name; 76948570Sbostic if (*sym == '_') 77048570Sbostic ++sym; 77148570Sbostic (void)fprintf(stderr, 77248570Sbostic "vmstat: %s: symbol %s not defined\n", vmunix, sym); 77325708Ssam exit(1); 77425708Ssam } 77548570Sbostic if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { 77648570Sbostic sym = nl[nlx].n_name; 77748570Sbostic if (*sym == '_') 77848570Sbostic ++sym; 77948570Sbostic (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); 78048570Sbostic exit(1); 78125708Ssam } 78225708Ssam } 78342952Sbostic 78448570Sbostic void 78548570Sbostic usage() 78642952Sbostic { 78748570Sbostic (void)fprintf(stderr, 78850004Skarels #ifndef NEWVM 78948570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \ 790*50103Skarels [-N system] [-w wait] [disks]\n"); 79150004Skarels #else 79250004Skarels "usage: vmstat [-ims] [-c count] [-M core] \ 793*50103Skarels [-N system] [-w wait] [disks]\n"); 79450004Skarels #endif 79548570Sbostic exit(1); 79642952Sbostic } 797