121585Sdist /* 236580Sbostic * Copyright (c) 1980 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[] = 1036580Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 1121585Sdist All rights reserved.\n"; 1236580Sbostic #endif /* not lint */ 1310826Ssam 1421585Sdist #ifndef lint 15*46892Sbostic static char sccsid[] = "@(#)vmstat.c 5.24 (Berkeley) 03/02/91"; 1636580Sbostic #endif /* not lint */ 1721585Sdist 181155Sbill #include <sys/param.h> 1918761Ssam #include <sys/file.h> 201155Sbill #include <sys/vm.h> 21*46892Sbostic #include <sys/user.h> 2229664Ssam #include <sys/dkstat.h> 233162Stoy #include <sys/buf.h> 2417262Smckusick #include <sys/namei.h> 2525708Ssam #include <sys/text.h> 2633610Smckusick #include <sys/malloc.h> 2737912Sbostic #include <ctype.h> 2845834Sbostic #include <errno.h> 2945834Sbostic #include <kvm.h> 3037912Sbostic #include <nlist.h> 3145834Sbostic #include <stdio.h> 3245834Sbostic #include <stdlib.h> 3345834Sbostic #include <string.h> 3437912Sbostic #include <paths.h> 351155Sbill 361155Sbill struct nlist nl[] = { 371448Sbill #define X_CPTIME 0 381448Sbill { "_cp_time" }, 391448Sbill #define X_RATE 1 401155Sbill { "_rate" }, 411448Sbill #define X_TOTAL 2 421155Sbill { "_total" }, 431448Sbill #define X_DEFICIT 3 441155Sbill { "_deficit" }, 451448Sbill #define X_FORKSTAT 4 461155Sbill { "_forkstat" }, 471448Sbill #define X_SUM 5 481155Sbill { "_sum" }, 491448Sbill #define X_FIRSTFREE 6 501155Sbill { "_firstfree" }, 511448Sbill #define X_MAXFREE 7 521155Sbill { "_maxfree" }, 539249Ssam #define X_BOOTTIME 8 549249Ssam { "_boottime" }, 551448Sbill #define X_DKXFER 9 561448Sbill { "_dk_xfer" }, 5710826Ssam #define X_REC 10 581155Sbill { "_rectime" }, 5910826Ssam #define X_PGIN 11 601155Sbill { "_pgintime" }, 6110826Ssam #define X_HZ 12 623162Stoy { "_hz" }, 6318761Ssam #define X_PHZ 13 6415266Ssam { "_phz" }, 6515807Smckusick #define X_NCHSTATS 14 6615807Smckusick { "_nchstats" }, 6717262Smckusick #define X_INTRNAMES 15 6817262Smckusick { "_intrnames" }, 6917262Smckusick #define X_EINTRNAMES 16 7017262Smckusick { "_eintrnames" }, 7117262Smckusick #define X_INTRCNT 17 7217262Smckusick { "_intrcnt" }, 7317262Smckusick #define X_EINTRCNT 18 7417262Smckusick { "_eintrcnt" }, 7518761Ssam #define X_DK_NDRIVE 19 7618761Ssam { "_dk_ndrive" }, 7725512Ssam #define X_XSTATS 20 7825512Ssam { "_xstats" }, 7933610Smckusick #define X_KMEMSTAT 21 8033610Smckusick { "_kmemstats" }, 8133610Smckusick #define X_KMEMBUCKETS 22 8233610Smckusick { "_bucket" }, 8342952Sbostic #define X_END 22 8410826Ssam #ifdef vax 8542952Sbostic #define X_MBDINIT (X_END+1) 8610826Ssam { "_mbdinit" }, 8742952Sbostic #define X_UBDINIT (X_END+2) 8810826Ssam { "_ubdinit" }, 8910826Ssam #endif 9025708Ssam #ifdef tahoe 9142952Sbostic #define X_VBDINIT (X_END+1) 9225708Ssam { "_vbdinit" }, 9342952Sbostic #define X_CKEYSTATS (X_END+2) 9425960Ssam { "_ckeystats" }, 9542952Sbostic #define X_DKEYSTATS (X_END+3) 9625960Ssam { "_dkeystats" }, 9725708Ssam #endif 9842952Sbostic #ifdef hp300 9942952Sbostic #define X_HPDINIT (X_END+1) 10042952Sbostic { "_hp_dinit" }, 10142952Sbostic #endif 10210826Ssam { "" }, 1031155Sbill }; 1041155Sbill 10545834Sbostic char *vmunix = _PATH_UNIX; 10645834Sbostic char *kmem = NULL; 10718761Ssam char **dr_name; 10818761Ssam int *dr_select; 10918761Ssam int dk_ndrive; 11018761Ssam int ndrives = 0; 11118761Ssam #ifdef vax 11218761Ssam char *defdrives[] = { "hp0", "hp1", "hp2", 0 }; 11318761Ssam #else 11442952Sbostic #ifdef hp300 11542952Sbostic char *defdrives[] = { "rd0", "rd1", "rd2", 0 }; 11642952Sbostic #else 11718761Ssam char *defdrives[] = { 0 }; 11818761Ssam #endif 11942952Sbostic #endif 1201155Sbill double stat1(); 1211155Sbill int firstfree, maxfree; 1223162Stoy int hz; 12315266Ssam int phz; 12415266Ssam int HZ; 12518761Ssam 12618761Ssam struct { 1271155Sbill int busy; 1281448Sbill long time[CPUSTATES]; 12918761Ssam long *xfer; 1301155Sbill struct vmmeter Rate; 1311155Sbill struct vmtotal Total; 1321155Sbill struct vmmeter Sum; 1331155Sbill struct forkstat Forkstat; 1341155Sbill unsigned rectime; 1351155Sbill unsigned pgintime; 13645834Sbostic } s, s1; 1371155Sbill #define rate s.Rate 1381155Sbill #define total s.Total 1391155Sbill #define sum s.Sum 1401155Sbill #define forkstat s.Forkstat 1411155Sbill 14210826Ssam struct vmmeter osum; 1431155Sbill int deficit; 1441155Sbill double etime; 14517262Smckusick time_t now, boottime; 14618768Ssam int lines = 1; 14745834Sbostic void printhdr(); 14845834Sbostic long lseek(); 1491155Sbill 15029664Ssam #define INTS(x) ((x) - (hz + phz)) 15129664Ssam 15245834Sbostic #define FORKSTAT 0x01 15345834Sbostic #define INTRSTAT 0x02 15445834Sbostic #define MEMSTAT 0x04 15545834Sbostic #define SUMSTAT 0x08 15645834Sbostic #define TIMESTAT 0x10 15745834Sbostic #define VMSTAT 0x20 15845834Sbostic #define ZEROOUT 0x40 15945834Sbostic 1601155Sbill main(argc, argv) 16145834Sbostic register int argc; 16245834Sbostic register char **argv; 1631155Sbill { 16445834Sbostic register int c, i, todo = 0; 16545834Sbostic extern int optind; 16645834Sbostic extern char *optarg; 1671155Sbill 16845834Sbostic while ((c = getopt(argc, argv, "fik:mstu:z")) != EOF) { 16945834Sbostic switch (c) { 17045834Sbostic case 'f': 17145834Sbostic todo |= FORKSTAT; 17245834Sbostic break; 17345834Sbostic case 'i': 17445834Sbostic todo |= INTRSTAT; 17545834Sbostic break; 17645834Sbostic case 'k': 17745834Sbostic kmem = optarg; 17845834Sbostic break; 17945834Sbostic case 'm': 18045834Sbostic todo |= MEMSTAT; 18145834Sbostic break; 18245834Sbostic case 's': 18345834Sbostic todo |= SUMSTAT; 18445834Sbostic break; 18545834Sbostic case 't': 18645834Sbostic todo |= TIMESTAT; 18745834Sbostic break; 18845834Sbostic case 'u': 18945834Sbostic vmunix = optarg; 19045834Sbostic break; 19145834Sbostic case 'z': 19245834Sbostic todo |= ZEROOUT; 19345834Sbostic break; 19445834Sbostic case '?': 19545834Sbostic usage(); 19645834Sbostic /* NOTREACHED */ 19745834Sbostic default: 19845834Sbostic (void) fprintf(stderr, 19945834Sbostic "vmstat: internal error in options\n"); 20045834Sbostic exit(1); 20145834Sbostic /* NOTREACHED */ 20245834Sbostic } 20345834Sbostic } 20445834Sbostic 20545834Sbostic /* 20645834Sbostic * Zeroing the statistics is fundamentally different 20745834Sbostic * (and really belongs in a separate program). 20845834Sbostic */ 20945834Sbostic if (todo & ZEROOUT) { 21045834Sbostic if (todo & ~ZEROOUT || kmem) 21145834Sbostic usage(); 21245834Sbostic nl[0].n_name = nl[X_SUM].n_name; 21345834Sbostic nl[1].n_name = 0; 21445834Sbostic if (nlist(vmunix, nl) || nl[0].n_type == 0) { 21545834Sbostic (void) fprintf(stderr, 21645834Sbostic "vmstat: cannot get symbol %s from %s\n", 21745834Sbostic nl[0].n_name, vmunix); 21845834Sbostic exit(1); 21945834Sbostic } 22045834Sbostic if ((i = open(kmem = _PATH_KMEM, 2)) < 0) { 22145834Sbostic (void) fprintf(stderr, "vmstat: cannot write %s: %s\n", 22245834Sbostic kmem, strerror(errno)); 22345834Sbostic exit(1); 22445834Sbostic } 22545834Sbostic (void) lseek(i, (long)nl[0].n_value, L_SET); 22645834Sbostic if (write(i, (char *)&s.Sum, sizeof s.Sum) != sizeof s.Sum) { 22745834Sbostic (void) fprintf(stderr, "vmstat: write(%s): %s\n", 22845834Sbostic kmem, strerror(errno)); 22945834Sbostic exit(1); 23045834Sbostic } 23145834Sbostic exit(0); 23245834Sbostic } 23345834Sbostic 23445834Sbostic if (todo == 0) 23545834Sbostic todo = VMSTAT; 23645834Sbostic 23745834Sbostic if (kvm_openfiles(vmunix, kmem, (char *)NULL) < 0) { 23845834Sbostic (void) fprintf(stderr, 23945834Sbostic "vmstat: kvm_openfiles(%s, %s, NULL): %s\n", 24045834Sbostic vmunix, kmem ? kmem : "NULL", kvm_geterr()); 2411155Sbill exit(1); 2421155Sbill } 24345834Sbostic 24445834Sbostic (void) kvm_nlist(nl); 24545834Sbostic if (nl[0].n_type == 0) { 24645834Sbostic (void) fprintf(stderr, "vmstat: %s: no namelist\n", 24745834Sbostic vmunix); 2481155Sbill exit(1); 2491155Sbill } 2501155Sbill 25145834Sbostic /* 25245834Sbostic * Fork, memory, sum, and time statistics do not need everything. 25345834Sbostic */ 25445834Sbostic if (todo & FORKSTAT) 25545834Sbostic doforkst(); 25645834Sbostic if (todo & MEMSTAT) 25745834Sbostic domem(); 25845834Sbostic if (todo & SUMSTAT) 25945834Sbostic dosum(); 26045834Sbostic if (todo & TIMESTAT) 26145834Sbostic dotimes(); 26245834Sbostic if (todo & INTRSTAT) 26345834Sbostic dointr(); 26445834Sbostic if (todo & VMSTAT) { 26545834Sbostic /* 26645834Sbostic * Read drive names, decide which drives to report, etc. 26745834Sbostic */ 26845834Sbostic argc -= optind; 26945834Sbostic argv += optind; 27045834Sbostic i = getdrivedata(argc, argv); 27145834Sbostic argc -= i; 27245834Sbostic argv += i; 27345834Sbostic dovmstat(argc > 0 ? atoi(argv[0]) : 0, 27445834Sbostic argc > 1 ? atoi(argv[1]) : 0); 27545834Sbostic } 27645834Sbostic exit(0); 27745834Sbostic } 27810826Ssam 27945834Sbostic usage() 28045834Sbostic { 2811155Sbill 28245834Sbostic (void) fprintf(stderr, 28345834Sbostic "usage: vmstat [-fimst]\n\tvmstat [drive-list] [interval [count]]\n\tvmstat -z\n"); 28445834Sbostic exit(1); 28545834Sbostic } 28633610Smckusick 28745834Sbostic /* 28845834Sbostic * kread reads something from the kernel, given its nlist index. 28945834Sbostic */ 29045834Sbostic void 29145834Sbostic kread(nlx, addr, size) 29245834Sbostic int nlx; 29345834Sbostic char *addr; 29445834Sbostic size_t size; 29545834Sbostic { 29645834Sbostic char *sym; 2971155Sbill 29845834Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 29945834Sbostic sym = nl[nlx].n_name; 30045834Sbostic if (*sym == '_') 30145834Sbostic sym++; 30245834Sbostic (void) fprintf(stderr, 30345834Sbostic "vmstat: symbol `%s' not defined in %s\n", sym, vmunix); 30445834Sbostic exit(1); 3051155Sbill } 30645834Sbostic if (kvm_read(nl[nlx].n_value, addr, size) != size) { 30745834Sbostic sym = nl[nlx].n_name; 30845834Sbostic if (*sym == '_') 30945834Sbostic sym++; 31045834Sbostic (void) fprintf(stderr, 31145834Sbostic "vmstat: error reading `%s': %s\n", sym, kvm_geterr()); 31245834Sbostic exit(1); 31318761Ssam } 31445834Sbostic } 31545834Sbostic 31645834Sbostic getdrivedata(argc, argv) 31745834Sbostic int argc; 31845834Sbostic char **argv; 31945834Sbostic { 32045834Sbostic register int i; 32145834Sbostic register char **cp; 32245834Sbostic int ret; 32345834Sbostic char buf[30]; 32445834Sbostic 32545834Sbostic kread(X_FIRSTFREE, (char *)&firstfree, sizeof firstfree); 32645834Sbostic kread(X_MAXFREE, (char *)&maxfree, sizeof maxfree); 32745834Sbostic kread(X_HZ, (char *)&hz, sizeof hz); 32845834Sbostic if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 32945834Sbostic kread(X_PHZ, (char *)&phz, sizeof phz); 33015266Ssam HZ = phz ? phz : hz; 33145834Sbostic kread(X_DK_NDRIVE, (char *)&dk_ndrive, sizeof dk_ndrive); 33218761Ssam if (dk_ndrive <= 0) { 33345834Sbostic (void) fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 33418761Ssam exit(1); 33518761Ssam } 33645834Sbostic dr_select = (int *)calloc((size_t)dk_ndrive, sizeof (int)); 33745834Sbostic dr_name = (char **)malloc((size_t)dk_ndrive * sizeof (char *)); 33845834Sbostic for (i = 0; i < dk_ndrive; i++) 33945834Sbostic dr_name[i] = NULL; 34045834Sbostic s.xfer = (long *)calloc((size_t)dk_ndrive, sizeof (long)); 34145834Sbostic s1.xfer = (long *)calloc((size_t)dk_ndrive, sizeof (long)); 3423162Stoy read_names(); 34345834Sbostic for (i = 0; i < dk_ndrive; i++) { 34445834Sbostic if (dr_name[i] == NULL) { 34545834Sbostic (void) sprintf(buf, "??%d", i); 34645834Sbostic dr_name[i] = strdup(buf); 34745834Sbostic } 3481155Sbill } 34945834Sbostic 35018761Ssam /* 35118761Ssam * Choose drives to be displayed. Priority 35218761Ssam * goes to (in order) drives supplied as arguments, 35318761Ssam * default drives. If everything isn't filled 35418761Ssam * in and there are drives not taken care of, 35518761Ssam * display the first few that fit. 35618761Ssam */ 35745834Sbostic ret = 0; 35818761Ssam ndrives = 0; 35918761Ssam while (argc > 0 && !isdigit(argv[0][0])) { 36018761Ssam for (i = 0; i < dk_ndrive; i++) { 36118761Ssam if (strcmp(dr_name[i], argv[0])) 36218761Ssam continue; 36318761Ssam dr_select[i] = 1; 36418761Ssam ndrives++; 36545834Sbostic break; 36618761Ssam } 36745834Sbostic ret++; 36818761Ssam argc--, argv++; 36918761Ssam } 37018761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 37118761Ssam if (dr_select[i]) 37218761Ssam continue; 37318761Ssam for (cp = defdrives; *cp; cp++) 37418761Ssam if (strcmp(dr_name[i], *cp) == 0) { 37518761Ssam dr_select[i] = 1; 37618761Ssam ndrives++; 37718761Ssam break; 37818761Ssam } 37918761Ssam } 38018761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 38118761Ssam if (dr_select[i]) 38218761Ssam continue; 38318761Ssam dr_select[i] = 1; 38418761Ssam ndrives++; 38518761Ssam } 38645834Sbostic return (ret); 38745834Sbostic } 38845834Sbostic 38945834Sbostic long 39045834Sbostic getuptime() 39145834Sbostic { 39245834Sbostic time_t time(); 39345834Sbostic long uptime; 39445834Sbostic 39545834Sbostic if (boottime == 0) 39645834Sbostic kread(X_BOOTTIME, (char *)&boottime, sizeof boottime); 39745834Sbostic (void) time(&now); 39845834Sbostic uptime = now - boottime; 39945834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 40045834Sbostic (void) fprintf(stderr, 40145834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 40245834Sbostic exit(1); 40345834Sbostic } 40445834Sbostic return (uptime); 40545834Sbostic } 40645834Sbostic 40745834Sbostic dovmstat(sleeptime, iter) 40845834Sbostic int sleeptime, iter; 40945834Sbostic { 41045834Sbostic register int i; 41145834Sbostic long interval, t; 41245834Sbostic 41345834Sbostic interval = getuptime(); 41445834Sbostic (void) signal(SIGCONT, printhdr); 4151155Sbill loop: 41618768Ssam if (--lines == 0) 41718768Ssam printhdr(); 41845834Sbostic kread(X_CPTIME, (char *)s.time, sizeof s.time); 41945834Sbostic kread(X_DKXFER, (char *)s.xfer, sizeof *s.xfer * dk_ndrive); 42045834Sbostic if (interval != 1) 42145834Sbostic kread(X_SUM, (char *)&rate, sizeof rate); 42218761Ssam else 42345834Sbostic kread(X_RATE, (char *)&rate, sizeof rate); 42445834Sbostic kread(X_TOTAL, (char *)&total, sizeof total); 42510826Ssam osum = sum; 42645834Sbostic kread(X_SUM, (char *)&sum, sizeof sum); 42745834Sbostic kread(X_DEFICIT, (char *)&deficit, sizeof deficit); 4281448Sbill etime = 0; 42945834Sbostic for (i = 0; i < dk_ndrive; i++) { 4301448Sbill t = s.xfer[i]; 4311448Sbill s.xfer[i] -= s1.xfer[i]; 4321448Sbill s1.xfer[i] = t; 4331155Sbill } 43445834Sbostic for (i = 0; i < CPUSTATES; i++) { 4351448Sbill t = s.time[i]; 4361448Sbill s.time[i] -= s1.time[i]; 4371448Sbill s1.time[i] = t; 4381448Sbill etime += s.time[i]; 4391155Sbill } 44045834Sbostic if (etime == 0.) 4411155Sbill etime = 1.; 44245834Sbostic (void) printf("%2d%2d%2d", 44345834Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 44445834Sbostic #define pgtok(a) ((a)*NBPG >> 10) 44545834Sbostic (void) printf("%6ld%6ld", pgtok(total.t_avm), pgtok(total.t_free)); 44645834Sbostic (void) printf("%4lu%3lu", 44745834Sbostic (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec)) / interval, 44845834Sbostic (rate.v_xsfrec+rate.v_xifrec) / interval); 44945834Sbostic (void) printf("%4lu", pgtok(rate.v_pgpgin) / interval); 45045834Sbostic (void) printf("%4lu%4lu%4d%4lu", pgtok(rate.v_pgpgout) / interval, 45145834Sbostic pgtok(rate.v_dfree) / interval, 45245834Sbostic pgtok(deficit), rate.v_scan / interval); 45318761Ssam etime /= (float)HZ; 45418761Ssam for (i = 0; i < dk_ndrive; i++) 45518761Ssam if (dr_select[i]) 45618761Ssam stats(i); 45745834Sbostic (void) printf("%4lu%4lu%4lu", INTS(rate.v_intr / interval), 45845834Sbostic rate.v_syscall / interval, rate.v_swtch / interval); 45945834Sbostic for(i = 0; i < CPUSTATES; i++) { 4601155Sbill float f = stat1(i); 4611155Sbill if (i == 0) { /* US+NI */ 4621155Sbill i++; 4631155Sbill f += stat1(i); 4641155Sbill } 46545834Sbostic (void) printf("%3.0f", f); 4661155Sbill } 46745834Sbostic (void) printf("\n"); 46845834Sbostic (void) fflush(stdout); 46945834Sbostic interval = 1; 47045834Sbostic if (iter && --iter == 0) 47145834Sbostic return; 47245834Sbostic if (sleeptime) { 47345834Sbostic sleep((unsigned)sleeptime); 4741155Sbill goto loop; 4751155Sbill } 4761155Sbill } 4771155Sbill 47845834Sbostic void 47917262Smckusick printhdr() 48017262Smckusick { 48118761Ssam register int i, j; 48218761Ssam 48345834Sbostic (void) printf(" procs memory page "); 48418761Ssam i = (ndrives * 3 - 6) / 2; 48518761Ssam if (i < 0) 48618761Ssam i = 0; 48718761Ssam for (j = 0; j < i; j++) 48845834Sbostic (void) putchar(' '); 48945834Sbostic (void) printf("faults"); 49018761Ssam i = ndrives * 3 - 6 - i; 49118761Ssam for (j = 0; j < i; j++) 49245834Sbostic (void) putchar(' '); 49345834Sbostic (void) printf(" cpu\n"); 49445834Sbostic (void) printf(" r b w avm fre re at pi po fr de sr "); 49518761Ssam for (i = 0; i < dk_ndrive; i++) 49618761Ssam if (dr_select[i]) 49745834Sbostic (void) printf("%c%c ", dr_name[i][0], 49845834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 49945834Sbostic (void) printf(" in sy cs us sy id\n"); 50018768Ssam lines = 19; 50117262Smckusick } 50217262Smckusick 5031155Sbill dotimes() 5041155Sbill { 5051155Sbill 50645834Sbostic kread(X_REC, (char *)&s.rectime, sizeof s.rectime); 50745834Sbostic kread(X_PGIN, (char *)&s.pgintime, sizeof s.pgintime); 50845834Sbostic kread(X_SUM, (char *)&sum, sizeof sum); 50945834Sbostic (void) printf("%u reclaims, %u total time (usec)\n", 51045834Sbostic sum.v_pgrec, s.rectime); 51145834Sbostic (void) printf("average: %u usec / reclaim\n", s.rectime / sum.v_pgrec); 51245834Sbostic (void) printf("\n"); 51345834Sbostic (void) printf("%u page ins, %u total time (msec)\n", 51445834Sbostic sum.v_pgin, s.pgintime / 10); 51545834Sbostic (void) printf("average: %8.1f msec / page in\n", 51645834Sbostic s.pgintime / (sum.v_pgin * 10.0)); 5171155Sbill } 5181155Sbill 51945834Sbostic pct(top, bot) 52045834Sbostic long top, bot; 52145834Sbostic { 52245834Sbostic 52345834Sbostic if (bot == 0) 52445834Sbostic return (0); 52545834Sbostic return ((top * 100) / bot); 52645834Sbostic } 52745834Sbostic 52845834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 52945834Sbostic 53030069Ssam #if defined(tahoe) 53145834Sbostic #include <machine/cpu.h> 53230069Ssam #endif 53330069Ssam 5341155Sbill dosum() 5351155Sbill { 53618761Ssam struct nchstats nchstats; 53725960Ssam struct xstats xstats; 53815807Smckusick long nchtotal; 53925960Ssam #if defined(tahoe) 54025960Ssam struct keystats keystats; 54125960Ssam #endif 5421155Sbill 54345834Sbostic kread(X_SUM, (char *)&sum, sizeof sum); 54445834Sbostic (void) printf("%9u swap ins\n", sum.v_swpin); 54545834Sbostic (void) printf("%9u swap outs\n", sum.v_swpout); 54645834Sbostic (void) printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 54745834Sbostic (void) printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 54845834Sbostic (void) printf("%9u total address trans. faults taken\n", sum.v_faults); 54945834Sbostic (void) printf("%9u page ins\n", sum.v_pgin); 55045834Sbostic (void) printf("%9u page outs\n", sum.v_pgout); 55145834Sbostic (void) printf("%9u pages paged in\n", sum.v_pgpgin); 55245834Sbostic (void) printf("%9u pages paged out\n", sum.v_pgpgout); 55345834Sbostic (void) printf("%9u sequential process pages freed\n", sum.v_seqfree); 55445834Sbostic (void) printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 55545834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 55645834Sbostic (void) printf("%9u reclaims from free list\n", sum.v_pgfrec); 55745834Sbostic (void) printf("%9u intransit blocking page faults\n", sum.v_intrans); 55845834Sbostic (void) printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 55945834Sbostic (void) printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 56045834Sbostic (void) printf("%9u executable fill pages created\n", 56145834Sbostic sum.v_nexfod / CLSIZE); 56245834Sbostic (void) printf("%9u executable fill page faults\n", 56345834Sbostic sum.v_exfod / CLSIZE); 56445834Sbostic (void) printf("%9u swap text pages found in free list\n", 56545834Sbostic sum.v_xsfrec); 56645834Sbostic (void) printf("%9u inode text pages found in free list\n", 56745834Sbostic sum.v_xifrec); 56845834Sbostic (void) printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 56945834Sbostic (void) printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 57045834Sbostic (void) printf("%9u pages examined by the clock daemon\n", sum.v_scan); 57145834Sbostic (void) printf("%9u revolutions of the clock hand\n", sum.v_rev); 57245834Sbostic (void) printf("%9u pages freed by the clock daemon\n", 57345834Sbostic sum.v_dfree / CLSIZE); 57445834Sbostic (void) printf("%9u cpu context switches\n", sum.v_swtch); 57545834Sbostic (void) printf("%9u device interrupts\n", sum.v_intr); 57645834Sbostic (void) printf("%9u software interrupts\n", sum.v_soft); 57718761Ssam #ifdef vax 57845834Sbostic (void) printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 57918761Ssam #endif 58045834Sbostic (void) printf("%9u traps\n", sum.v_trap); 58145834Sbostic (void) printf("%9u system calls\n", sum.v_syscall); 58245834Sbostic kread(X_NCHSTATS, (char *)&nchstats, sizeof nchstats); 58338773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 58438773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 58538773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 58645834Sbostic (void) printf("%9ld total name lookups\n", nchtotal); 58745834Sbostic (void) printf( 58845834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 58945834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 59045834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 59145834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 59245834Sbostic (void) printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 59345834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 59445834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 59545834Sbostic PCT(nchstats.ncs_long, nchtotal)); 59645834Sbostic kread(X_XSTATS, (char *)&xstats, sizeof xstats); 59745834Sbostic (void) printf("%9lu total calls to xalloc (cache hits %d%%)\n", 59845834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 59945834Sbostic (void) printf("%9s sticky %lu flushed %lu unused %lu\n", "", 60025512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 60145834Sbostic (void) printf("%9lu total calls to xfree", xstats.free); 60245834Sbostic (void) printf(" (sticky %lu cached %lu swapped %lu)\n", 60325512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 60425960Ssam #if defined(tahoe) 60545834Sbostic kread(X_CKEYSTATS, (char *)&keystats, sizeof keystats); 60645834Sbostic (void) printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 60725960Ssam keystats.ks_allocs, "code cache keys allocated", 60845834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 60945834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 61045834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 61145834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 61245834Sbostic kread(X_DKEYSTATS, (char *)&keystats, sizeof keystats); 61345834Sbostic (void) printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 61425960Ssam keystats.ks_allocs, "data 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)); 61925960Ssam #endif 6201155Sbill } 6211155Sbill 6221155Sbill doforkst() 6231155Sbill { 6241155Sbill 62545834Sbostic kread(X_FORKSTAT, (char *)&forkstat, sizeof forkstat); 62645834Sbostic (void) printf("%d forks, %d pages, average=%.2f\n", 6271155Sbill forkstat.cntfork, forkstat.sizfork, 6281155Sbill (float) forkstat.sizfork / forkstat.cntfork); 62945834Sbostic (void) printf("%d vforks, %d pages, average=%.2f\n", 6301155Sbill forkstat.cntvfork, forkstat.sizvfork, 6311155Sbill (float)forkstat.sizvfork / forkstat.cntvfork); 6321155Sbill } 6331155Sbill 6341155Sbill stats(dn) 6351155Sbill { 6361155Sbill 63718761Ssam if (dn >= dk_ndrive) { 63845834Sbostic (void) printf(" 0"); 6391155Sbill return; 6401155Sbill } 64145834Sbostic (void) printf("%3.0f", s.xfer[dn]/etime); 6421155Sbill } 6431155Sbill 6441155Sbill double 6451155Sbill stat1(row) 6461155Sbill { 6471448Sbill double t; 6481448Sbill register i; 6491155Sbill 6501155Sbill t = 0; 6511155Sbill for(i=0; i<CPUSTATES; i++) 6521448Sbill t += s.time[i]; 6531448Sbill if(t == 0.) 6541448Sbill t = 1.; 6551448Sbill return(s.time[row]*100./t); 6561155Sbill } 6571155Sbill 65845834Sbostic dointr() 6591155Sbill { 66045834Sbostic register int nintr, inamlen; 66145834Sbostic register long *intrcnt, inttotal, uptime = getuptime(); 66245834Sbostic register char *intrname; 6631155Sbill 66445834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 66545834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 66645834Sbostic intrcnt = (long *)malloc((size_t)nintr); 66745834Sbostic intrname = malloc((size_t)inamlen); 66817262Smckusick if (intrcnt == NULL || intrname == NULL) { 66945834Sbostic (void) fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 67017262Smckusick exit(9); 67117262Smckusick } 67245834Sbostic kread(X_INTRCNT, (char *)intrcnt, (size_t)nintr); 67345834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 67445834Sbostic (void) printf("interrupt total rate\n"); 67517262Smckusick inttotal = 0; 67645834Sbostic nintr /= sizeof(long); 67745834Sbostic while (--nintr >= 0) { 67817262Smckusick if (*intrcnt) 67945834Sbostic (void) printf("%-12s %8ld %8ld\n", intrname, 68045834Sbostic *intrcnt, *intrcnt / uptime); 68117262Smckusick intrname += strlen(intrname) + 1; 68217262Smckusick inttotal += *intrcnt++; 68317262Smckusick } 68445834Sbostic (void) printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 68517262Smckusick } 68617262Smckusick 68733610Smckusick /* 68845152Smckusick * These names are defined in <sys/malloc.h>. 68933610Smckusick */ 69045152Smckusick char *kmemnames[] = INITKMEMNAMES; 69133610Smckusick 69233610Smckusick domem() 69333610Smckusick { 69445834Sbostic register struct kmembuckets *kp; 69545834Sbostic register struct kmemstats *ks; 69645834Sbostic register int i; 69733610Smckusick struct kmemstats kmemstats[M_LAST]; 69833610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 69933610Smckusick 70045834Sbostic kread(X_KMEMBUCKETS, (char *)buckets, sizeof buckets); 70145834Sbostic (void) printf("Memory statistics by bucket size\n"); 70245834Sbostic (void) printf( 70345834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 70433610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 70533610Smckusick if (kp->kb_calls == 0) 70633610Smckusick continue; 70745834Sbostic (void) printf("%8d%9ld%7ld%11ld%8ld%11ld\n", 1 << i, 70833610Smckusick kp->kb_total - kp->kb_totalfree, 70933610Smckusick kp->kb_totalfree, kp->kb_calls, 71033610Smckusick kp->kb_highwat, kp->kb_couldfree); 71133610Smckusick 71233610Smckusick } 71345834Sbostic kread(X_KMEMSTAT, (char *)kmemstats, sizeof kmemstats); 71445834Sbostic (void) printf("Memory statistics by type\n"); 71545834Sbostic (void) printf("\ 71645834Sbostic Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 71733610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 71833610Smckusick if (ks->ks_calls == 0) 71933610Smckusick continue; 72045834Sbostic (void) printf("%10s%7ld%8ldK%9ldK%6ldK%9ld%7u%10u\n", 72133610Smckusick kmemnames[i] ? kmemnames[i] : "undefined", 72233610Smckusick ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 72333610Smckusick (ks->ks_maxused + 1023) / 1024, 72433610Smckusick (ks->ks_limit + 1023) / 1024, ks->ks_calls, 72533610Smckusick ks->ks_limblocks, ks->ks_mapblocks); 72633610Smckusick } 72733610Smckusick } 72833610Smckusick 7293162Stoy /* 7303162Stoy * Read the drive names out of kmem. 7313162Stoy */ 73210826Ssam #ifdef vax 73345834Sbostic #include <uba/ubavar.h> 73445834Sbostic #include <mba/mbavar.h> 73518761Ssam 7363162Stoy read_names() 7373162Stoy { 73845834Sbostic register char *p; 73945834Sbostic unsigned long mp, up; 7403162Stoy struct mba_device mdev; 7413162Stoy struct mba_driver mdrv; 74245834Sbostic struct uba_device udev; 7433162Stoy struct uba_driver udrv; 74445834Sbostic char name[10]; 74545834Sbostic static char buf[BUFSIZ]; 7463162Stoy 74745834Sbostic mp = nl[X_MBDINIT].n_value; 74845834Sbostic up = nl[X_UBDINIT].n_value; 74945834Sbostic if (mp == 0 && up == 0) { 75045834Sbostic (void) fprintf(stderr, 75145834Sbostic "vmstat: disk init info not in namelist\n"); 7523162Stoy exit(1); 7533162Stoy } 75445834Sbostic p = buf; 75545834Sbostic if (mp) for (;; mp += sizeof mdev) { 75645834Sbostic (void) kvm_read((u_long)mp, (char *)&mdev, sizeof mdev); 7573162Stoy if (mdev.mi_driver == 0) 7583162Stoy break; 7593162Stoy if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 7603162Stoy continue; 76145834Sbostic (void) kvm_read((u_long)mdev.mi_driver, 76245834Sbostic (char *)&mdrv, sizeof mdrv); 76345834Sbostic (void) kvm_read((u_long)mdrv.md_dname, name, sizeof name); 76445834Sbostic dr_name[mdev.mi_dk] = p; 76545834Sbostic p += sprintf(p, "%s%d", name, mdev.mi_unit); 7663162Stoy } 76745834Sbostic if (up) for (;; up += sizeof udev) { 76845834Sbostic (void) kvm_read(up, (char *)&udev, sizeof udev); 7693162Stoy if (udev.ui_driver == 0) 7703162Stoy break; 7713162Stoy if (udev.ui_dk < 0 || udev.ui_alive == 0) 7723162Stoy continue; 77345834Sbostic (void) kvm_read((u_long)udev.ui_driver, 77445834Sbostic (char *)&udrv, sizeof udrv); 77545834Sbostic (void) kvm_read((u_long)udrv.ud_dname, name, sizeof name); 77645834Sbostic dr_name[udev.ui_dk] = p; 77745834Sbostic p += sprintf(p, "%s%d", name, udev.ui_unit); 7783162Stoy } 7793162Stoy } 78010826Ssam #endif 78125708Ssam 78225708Ssam #ifdef tahoe 783*46892Sbostic #include <tahoe/vba/vbavar.h> 78425708Ssam 78525708Ssam /* 78625708Ssam * Read the drive names out of kmem. 78725708Ssam */ 78825708Ssam read_names() 78925708Ssam { 79045834Sbostic register char *p; 79125708Ssam struct vba_device udev, *up; 79225708Ssam struct vba_driver udrv; 79345834Sbostic char name[10]; 79445834Sbostic static char buf[BUFSIZ]; 79525708Ssam 79625708Ssam up = (struct vba_device *) nl[X_VBDINIT].n_value; 79725708Ssam if (up == 0) { 79845834Sbostic (void) fprintf(stderr, 79945834Sbostic "vmstat: disk init info not in namelist\n"); 80025708Ssam exit(1); 80125708Ssam } 80245834Sbostic p = buf; 80345834Sbostic for (;; up += sizeof udev) { 80445834Sbostic (void) kvm_read(up, (char *)&udev, sizeof udev); 80525708Ssam if (udev.ui_driver == 0) 80625708Ssam break; 80725708Ssam if (udev.ui_dk < 0 || udev.ui_alive == 0) 80825708Ssam continue; 80945834Sbostic (void) kvm_read((u_long)udev.ui_driver, 81045834Sbostic (char *)&udrv, sizeof udrv); 81145834Sbostic (void) kvm_read((u_long)udrv.ud_dname, name, sizeof name); 81245834Sbostic dr_name[udev.ui_dk] = p; 81345834Sbostic p += sprintf(p, "%s%d", name, udev.ui_unit); 81425708Ssam } 81525708Ssam } 81625708Ssam #endif 81742952Sbostic 81842952Sbostic #ifdef hp300 819*46892Sbostic #include <hp300/dev/device.h> 82042952Sbostic 82142952Sbostic read_names() 82242952Sbostic { 82345834Sbostic register char *p; 82445834Sbostic register u_long hp; 825*46892Sbostic static char buf[BUFSIZ]; 82642952Sbostic struct hp_device hdev; 82742952Sbostic struct driver hdrv; 828*46892Sbostic char name[10]; 82942952Sbostic 83045834Sbostic hp = nl[X_HPDINIT].n_value; 83142952Sbostic if (hp == 0) { 83245834Sbostic (void) fprintf(stderr, 83345834Sbostic "vmstat: disk init info not in namelist\n"); 83442952Sbostic exit(1); 83542952Sbostic } 83645834Sbostic p = buf; 83745834Sbostic for (;; hp += sizeof hdev) { 83845834Sbostic (void) kvm_read(hp, (char *)&hdev, sizeof hdev); 83942952Sbostic if (hdev.hp_driver == 0) 84042952Sbostic break; 84145834Sbostic if (hdev.hp_dk < 0 || hdev.hp_alive == 0) 84242952Sbostic continue; 84345834Sbostic (void) kvm_read((u_long)hdev.hp_driver, 84445834Sbostic (char *)&hdrv, sizeof hdrv); 84545834Sbostic (void) kvm_read((u_long)hdrv.d_name, name, sizeof name); 84645834Sbostic dr_name[hdev.hp_dk] = p; 84745834Sbostic p += sprintf(p, "%s%d", name, hdev.hp_unit); 84842952Sbostic } 84942952Sbostic } 85042952Sbostic #endif 851