vmstat.c revision 34214
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1986, 1991, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3528693Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1980, 1986, 1991, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4128693Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93"; 4328693Scharnier#endif 4428693Scharnierstatic const char rcsid[] = 4534214Sdyson "$Id: vmstat.c,v 1.22 1997/12/05 19:28:28 bde Exp $"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 481590Srgrimes#include <sys/param.h> 491590Srgrimes#include <sys/time.h> 501590Srgrimes#include <sys/proc.h> 511590Srgrimes#include <sys/dkstat.h> 521590Srgrimes#include <sys/buf.h> 5312811Sbde#include <sys/uio.h> 541590Srgrimes#include <sys/namei.h> 551590Srgrimes#include <sys/malloc.h> 561590Srgrimes#include <sys/signal.h> 571590Srgrimes#include <sys/fcntl.h> 581590Srgrimes#include <sys/ioctl.h> 591590Srgrimes#include <sys/sysctl.h> 6012804Speter#include <sys/vmmeter.h> 6112811Sbde 6212811Sbde#include <vm/vm_param.h> 6312811Sbde 6428693Scharnier#include <ctype.h> 6528693Scharnier#include <err.h> 6628693Scharnier#include <errno.h> 6728693Scharnier#include <kvm.h> 6828693Scharnier#include <limits.h> 691590Srgrimes#include <nlist.h> 7028693Scharnier#include <paths.h> 711590Srgrimes#include <stdio.h> 721590Srgrimes#include <stdlib.h> 731590Srgrimes#include <string.h> 7430180Sdima#include <sysexits.h> 7528693Scharnier#include <time.h> 7628693Scharnier#include <unistd.h> 771590Srgrimes 781590Srgrimesstruct nlist namelist[] = { 791590Srgrimes#define X_CPTIME 0 801590Srgrimes { "_cp_time" }, 811590Srgrimes#define X_DK_NDRIVE 1 821590Srgrimes { "_dk_ndrive" }, 831590Srgrimes#define X_SUM 2 841590Srgrimes { "_cnt" }, 851590Srgrimes#define X_BOOTTIME 3 861590Srgrimes { "_boottime" }, 871590Srgrimes#define X_DKXFER 4 881590Srgrimes { "_dk_xfer" }, 891590Srgrimes#define X_HZ 5 901590Srgrimes { "_hz" }, 911590Srgrimes#define X_STATHZ 6 921590Srgrimes { "_stathz" }, 931590Srgrimes#define X_NCHSTATS 7 941590Srgrimes { "_nchstats" }, 951590Srgrimes#define X_INTRNAMES 8 961590Srgrimes { "_intrnames" }, 971590Srgrimes#define X_EINTRNAMES 9 981590Srgrimes { "_eintrnames" }, 991590Srgrimes#define X_INTRCNT 10 1001590Srgrimes { "_intrcnt" }, 1011590Srgrimes#define X_EINTRCNT 11 1021590Srgrimes { "_eintrcnt" }, 10330279Sphk#define X_KMEMSTATISTICS 12 10430279Sphk { "_kmemstatistics" }, 1051590Srgrimes#define X_KMEMBUCKETS 13 1061590Srgrimes { "_bucket" }, 10730180Sdima#ifdef notyet 1081590Srgrimes#define X_DEFICIT 14 1091590Srgrimes { "_deficit" }, 1101590Srgrimes#define X_FORKSTAT 15 1111590Srgrimes { "_forkstat" }, 1121590Srgrimes#define X_REC 16 1131590Srgrimes { "_rectime" }, 1141590Srgrimes#define X_PGIN 17 1151590Srgrimes { "_pgintime" }, 1161590Srgrimes#define X_XSTATS 18 1171590Srgrimes { "_xstats" }, 1181620Srgrimes#define X_END 19 1191590Srgrimes#else 1201590Srgrimes#define X_END 14 1211590Srgrimes#endif 1221590Srgrimes#if defined(hp300) || defined(luna68k) 1231590Srgrimes#define X_HPDINIT (X_END) 1241590Srgrimes { "_hp_dinit" }, 1251590Srgrimes#endif 1261620Srgrimes#if defined(i386) 1273642Swollman#define X_DK_NAMES (X_END) 1283642Swollman { "_dk_names" }, 1291620Srgrimes#endif 1301590Srgrimes#ifdef mips 1311590Srgrimes#define X_SCSI_DINIT (X_END) 1321590Srgrimes { "_scsi_dinit" }, 1331590Srgrimes#endif 1341590Srgrimes#ifdef tahoe 1351590Srgrimes#define X_VBDINIT (X_END) 1361590Srgrimes { "_vbdinit" }, 1371590Srgrimes#define X_CKEYSTATS (X_END+1) 1381590Srgrimes { "_ckeystats" }, 1391590Srgrimes#define X_DKEYSTATS (X_END+2) 1401590Srgrimes { "_dkeystats" }, 1411590Srgrimes#endif 1421590Srgrimes#ifdef vax 1431590Srgrimes#define X_MBDINIT (X_END) 1441590Srgrimes { "_mbdinit" }, 1451590Srgrimes#define X_UBDINIT (X_END+1) 1461590Srgrimes { "_ubdinit" }, 1471590Srgrimes#endif 1481590Srgrimes { "" }, 1491590Srgrimes}; 1501590Srgrimes 1511590Srgrimesstruct _disk { 1521590Srgrimes long time[CPUSTATES]; 1531590Srgrimes long *xfer; 1541590Srgrimes} cur, last; 1551590Srgrimes 1561590Srgrimesstruct vmmeter sum, osum; 1571590Srgrimeschar **dr_name; 1581590Srgrimesint *dr_select, dk_ndrive, ndrives; 1591590Srgrimes 1601590Srgrimesint winlines = 20; 1611590Srgrimes 1621590Srgrimeskvm_t *kd; 1631590Srgrimes 1641590Srgrimes#define FORKSTAT 0x01 1651590Srgrimes#define INTRSTAT 0x02 1661590Srgrimes#define MEMSTAT 0x04 1671590Srgrimes#define SUMSTAT 0x08 1681590Srgrimes#define TIMESTAT 0x10 1691590Srgrimes#define VMSTAT 0x20 1701590Srgrimes 1711590Srgrimes#include "names.c" /* disk names -- machine dependent */ 1721590Srgrimes 1731590Srgrimesvoid cpustats(), dkstats(), dointr(), domem(), dosum(); 1741590Srgrimesvoid dovmstat(), kread(), usage(); 17530180Sdima#ifdef notyet 1761590Srgrimesvoid dotimes(), doforkst(); 1771590Srgrimes#endif 17828693Scharniervoid printhdr __P((void)); 1791590Srgrimes 18028693Scharnierint 1811590Srgrimesmain(argc, argv) 1821590Srgrimes register int argc; 1831590Srgrimes register char **argv; 1841590Srgrimes{ 1851590Srgrimes register int c, todo; 1861590Srgrimes u_int interval; 1871590Srgrimes int reps; 1881590Srgrimes char *memf, *nlistf; 1891590Srgrimes char errbuf[_POSIX2_LINE_MAX]; 1901590Srgrimes 1911590Srgrimes memf = nlistf = NULL; 1921590Srgrimes interval = reps = todo = 0; 19324360Simp while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != -1) { 1941590Srgrimes switch (c) { 1951590Srgrimes case 'c': 1961590Srgrimes reps = atoi(optarg); 1971590Srgrimes break; 1981590Srgrimes case 'f': 19930180Sdima#ifdef notyet 2001590Srgrimes todo |= FORKSTAT; 20130180Sdima#else 20230180Sdima errx(EX_USAGE, "sorry, -f is not (re)implemented yet"); 20330180Sdima#endif 2041590Srgrimes break; 2051590Srgrimes case 'i': 2061590Srgrimes todo |= INTRSTAT; 2071590Srgrimes break; 2081590Srgrimes case 'M': 2091590Srgrimes memf = optarg; 2101590Srgrimes break; 2111590Srgrimes case 'm': 2121590Srgrimes todo |= MEMSTAT; 2131590Srgrimes break; 2141590Srgrimes case 'N': 2151590Srgrimes nlistf = optarg; 2161590Srgrimes break; 2171590Srgrimes case 's': 2181590Srgrimes todo |= SUMSTAT; 2191590Srgrimes break; 2201590Srgrimes case 't': 22130180Sdima#ifdef notyet 2221590Srgrimes todo |= TIMESTAT; 22330180Sdima#else 22430180Sdima errx(EX_USAGE, "sorry, -t is not (re)implemented yet"); 22530180Sdima#endif 2261590Srgrimes break; 2271590Srgrimes case 'w': 2281590Srgrimes interval = atoi(optarg); 2291590Srgrimes break; 2301590Srgrimes case '?': 2311590Srgrimes default: 2321590Srgrimes usage(); 2331590Srgrimes } 2341590Srgrimes } 2351590Srgrimes argc -= optind; 2361590Srgrimes argv += optind; 2371590Srgrimes 2381590Srgrimes if (todo == 0) 2391590Srgrimes todo = VMSTAT; 2401590Srgrimes 2411590Srgrimes /* 2421590Srgrimes * Discard setgid privileges if not the running kernel so that bad 2431590Srgrimes * guys can't print interesting stuff from kernel memory. 2441590Srgrimes */ 2451590Srgrimes if (nlistf != NULL || memf != NULL) 2461590Srgrimes setgid(getgid()); 2471590Srgrimes 24828693Scharnier kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 24928693Scharnier if (kd == 0) 25028693Scharnier errx(1, "kvm_openfiles: %s", errbuf); 2511590Srgrimes 2521590Srgrimes if ((c = kvm_nlist(kd, namelist)) != 0) { 2531590Srgrimes if (c > 0) { 25428693Scharnier warnx("undefined symbols:"); 2551590Srgrimes for (c = 0; 2561590Srgrimes c < sizeof(namelist)/sizeof(namelist[0]); c++) 2571590Srgrimes if (namelist[c].n_type == 0) 2581590Srgrimes fprintf(stderr, " %s", 2591590Srgrimes namelist[c].n_name); 2601590Srgrimes (void)fputc('\n', stderr); 2611590Srgrimes } else 26228693Scharnier warnx("kvm_nlist: %s", kvm_geterr(kd)); 2631590Srgrimes exit(1); 2641590Srgrimes } 2651590Srgrimes 2661590Srgrimes if (todo & VMSTAT) { 2671590Srgrimes char **getdrivedata(); 2681590Srgrimes struct winsize winsize; 2691590Srgrimes 2701590Srgrimes argv = getdrivedata(argv); 2711590Srgrimes winsize.ws_row = 0; 2721590Srgrimes (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 2731590Srgrimes if (winsize.ws_row > 0) 2741590Srgrimes winlines = winsize.ws_row; 2751590Srgrimes 2761590Srgrimes } 2771590Srgrimes 2781590Srgrimes#define BACKWARD_COMPATIBILITY 2791590Srgrimes#ifdef BACKWARD_COMPATIBILITY 2801590Srgrimes if (*argv) { 2811590Srgrimes interval = atoi(*argv); 2821590Srgrimes if (*++argv) 2831590Srgrimes reps = atoi(*argv); 2841590Srgrimes } 2851590Srgrimes#endif 2861590Srgrimes 2871590Srgrimes if (interval) { 2881590Srgrimes if (!reps) 2891590Srgrimes reps = -1; 2901590Srgrimes } else if (reps) 2911590Srgrimes interval = 1; 2921590Srgrimes 29330180Sdima#ifdef notyet 2941590Srgrimes if (todo & FORKSTAT) 2951590Srgrimes doforkst(); 2961590Srgrimes#endif 2971590Srgrimes if (todo & MEMSTAT) 2981590Srgrimes domem(); 2991590Srgrimes if (todo & SUMSTAT) 3001590Srgrimes dosum(); 30130180Sdima#ifdef notyet 3021590Srgrimes if (todo & TIMESTAT) 3031590Srgrimes dotimes(); 3041590Srgrimes#endif 3051590Srgrimes if (todo & INTRSTAT) 3061590Srgrimes dointr(); 3071590Srgrimes if (todo & VMSTAT) 3081590Srgrimes dovmstat(interval, reps); 3091590Srgrimes exit(0); 3101590Srgrimes} 3111590Srgrimes 3121590Srgrimeschar ** 3131590Srgrimesgetdrivedata(argv) 3141590Srgrimes char **argv; 3151590Srgrimes{ 3161590Srgrimes register int i; 3171590Srgrimes register char **cp; 3181590Srgrimes char buf[30]; 3191590Srgrimes 3201590Srgrimes kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 32128693Scharnier if (dk_ndrive < 0) 32228693Scharnier errx(1, "dk_ndrive %d", dk_ndrive); 3231590Srgrimes dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 3241590Srgrimes dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 3251590Srgrimes for (i = 0; i < dk_ndrive; i++) 3261590Srgrimes dr_name[i] = NULL; 3271590Srgrimes cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 3281590Srgrimes last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 3291590Srgrimes if (!read_names()) 3301590Srgrimes exit (1); 3311590Srgrimes for (i = 0; i < dk_ndrive; i++) 3321590Srgrimes if (dr_name[i] == NULL) { 3331590Srgrimes (void)sprintf(buf, "??%d", i); 3341590Srgrimes dr_name[i] = strdup(buf); 3351590Srgrimes } 3361590Srgrimes 3371590Srgrimes /* 3381590Srgrimes * Choose drives to be displayed. Priority goes to (in order) drives 3391590Srgrimes * supplied as arguments, default drives. If everything isn't filled 3401590Srgrimes * in and there are drives not taken care of, display the first few 3411590Srgrimes * that fit. 3421590Srgrimes */ 3431590Srgrimes#define BACKWARD_COMPATIBILITY 3441590Srgrimes for (ndrives = 0; *argv; ++argv) { 3451590Srgrimes#ifdef BACKWARD_COMPATIBILITY 3461590Srgrimes if (isdigit(**argv)) 3471590Srgrimes break; 3481590Srgrimes#endif 3491590Srgrimes for (i = 0; i < dk_ndrive; i++) { 3501590Srgrimes if (strcmp(dr_name[i], *argv)) 3511590Srgrimes continue; 3521590Srgrimes dr_select[i] = 1; 3531590Srgrimes ++ndrives; 3541590Srgrimes break; 3551590Srgrimes } 3561590Srgrimes } 3571590Srgrimes for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 3581590Srgrimes if (dr_select[i]) 3591590Srgrimes continue; 3601590Srgrimes for (cp = defdrives; *cp; cp++) 3611590Srgrimes if (strcmp(dr_name[i], *cp) == 0) { 3621590Srgrimes dr_select[i] = 1; 3631590Srgrimes ++ndrives; 3641590Srgrimes break; 3651590Srgrimes } 3661590Srgrimes } 3671590Srgrimes for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 3681590Srgrimes if (dr_select[i]) 3691590Srgrimes continue; 3701590Srgrimes dr_select[i] = 1; 3711590Srgrimes ++ndrives; 3721590Srgrimes } 3731590Srgrimes return(argv); 3741590Srgrimes} 3751590Srgrimes 3761590Srgrimeslong 3771590Srgrimesgetuptime() 3781590Srgrimes{ 3791590Srgrimes static time_t now, boottime; 3801590Srgrimes time_t uptime; 3811590Srgrimes 3821590Srgrimes if (boottime == 0) 3831590Srgrimes kread(X_BOOTTIME, &boottime, sizeof(boottime)); 3841590Srgrimes (void)time(&now); 3851590Srgrimes uptime = now - boottime; 38628693Scharnier if (uptime <= 0 || uptime > 60*60*24*365*10) 38728693Scharnier errx(1, "time makes no sense; namelist must be wrong"); 3881590Srgrimes return(uptime); 3891590Srgrimes} 3901590Srgrimes 3911590Srgrimesint hz, hdrcnt; 3921590Srgrimes 3931590Srgrimesvoid 3941590Srgrimesdovmstat(interval, reps) 3951590Srgrimes u_int interval; 3961590Srgrimes int reps; 3971590Srgrimes{ 3981590Srgrimes struct vmtotal total; 3991590Srgrimes time_t uptime, halfuptime; 4001590Srgrimes void needhdr(); 4011590Srgrimes int mib[2], size; 4021590Srgrimes 4031590Srgrimes uptime = getuptime(); 4041590Srgrimes halfuptime = uptime / 2; 4051590Srgrimes (void)signal(SIGCONT, needhdr); 4061590Srgrimes 4071590Srgrimes if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0) 4081590Srgrimes kread(X_STATHZ, &hz, sizeof(hz)); 4091590Srgrimes if (!hz) 4101590Srgrimes kread(X_HZ, &hz, sizeof(hz)); 4111590Srgrimes 4121590Srgrimes for (hdrcnt = 1;;) { 4131590Srgrimes if (!--hdrcnt) 4141590Srgrimes printhdr(); 4151590Srgrimes kread(X_CPTIME, cur.time, sizeof(cur.time)); 4161590Srgrimes kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive); 4171590Srgrimes kread(X_SUM, &sum, sizeof(sum)); 4181590Srgrimes size = sizeof(total); 4191590Srgrimes mib[0] = CTL_VM; 4201590Srgrimes mib[1] = VM_METER; 4211590Srgrimes if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) { 4221590Srgrimes printf("Can't get kerninfo: %s\n", strerror(errno)); 4231590Srgrimes bzero(&total, sizeof(total)); 4241590Srgrimes } 4251590Srgrimes (void)printf("%2d%2d%2d", 4261590Srgrimes total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); 4271590Srgrimes#define pgtok(a) ((a) * sum.v_page_size >> 10) 4281590Srgrimes#define rate(x) (((x) + halfuptime) / uptime) /* round */ 42923952Sscrappy (void)printf("%8ld%6ld ", 43028693Scharnier (long)pgtok(total.t_avm), (long)pgtok(total.t_free)); 4313659Sdg (void)printf("%4lu ", rate(sum.v_vm_faults - osum.v_vm_faults)); 4321590Srgrimes (void)printf("%3lu ", 4331590Srgrimes rate(sum.v_reactivated - osum.v_reactivated)); 4343659Sdg (void)printf("%3lu ", rate(sum.v_swapin + sum.v_vnodein - 4353659Sdg (osum.v_swapin + osum.v_vnodein))); 4363693Sdg (void)printf("%3lu ", rate(sum.v_swapout + sum.v_vnodeout - 4373693Sdg (osum.v_swapout + osum.v_vnodeout))); 4383693Sdg (void)printf("%3lu ", rate(sum.v_tfree - osum.v_tfree)); 4393693Sdg (void)printf("%3lu ", rate(sum.v_pdpages - osum.v_pdpages)); 4401590Srgrimes dkstats(); 4411590Srgrimes (void)printf("%4lu %4lu %3lu ", 4421590Srgrimes rate(sum.v_intr - osum.v_intr), 4431590Srgrimes rate(sum.v_syscall - osum.v_syscall), 4441590Srgrimes rate(sum.v_swtch - osum.v_swtch)); 4451590Srgrimes cpustats(); 4461590Srgrimes (void)printf("\n"); 4471590Srgrimes (void)fflush(stdout); 4481590Srgrimes if (reps >= 0 && --reps <= 0) 4491590Srgrimes break; 4501590Srgrimes osum = sum; 4511590Srgrimes uptime = interval; 4521590Srgrimes /* 4531590Srgrimes * We round upward to avoid losing low-frequency events 4541590Srgrimes * (i.e., >= 1 per interval but < 1 per second). 4551590Srgrimes */ 4563659Sdg if (interval != 1) 4573659Sdg halfuptime = (uptime + 1) / 2; 4583659Sdg else 4593659Sdg halfuptime = 0; 4601590Srgrimes (void)sleep(interval); 4611590Srgrimes } 4621590Srgrimes} 4631590Srgrimes 46428693Scharniervoid 4651590Srgrimesprinthdr() 4661590Srgrimes{ 4671590Srgrimes register int i; 4681590Srgrimes 46923952Sscrappy (void)printf(" procs memory page%*s", 20, ""); 4701590Srgrimes if (ndrives > 1) 4711590Srgrimes (void)printf("disks %*s faults cpu\n", 4721590Srgrimes ndrives * 3 - 6, ""); 4731590Srgrimes else 4741590Srgrimes (void)printf("%*s faults cpu\n", ndrives * 3, ""); 47523952Sscrappy (void)printf(" r b w avm fre flt re pi po fr sr "); 4761590Srgrimes for (i = 0; i < dk_ndrive; i++) 4771590Srgrimes if (dr_select[i]) 4781590Srgrimes (void)printf("%c%c ", dr_name[i][0], 4791590Srgrimes dr_name[i][strlen(dr_name[i]) - 1]); 4801590Srgrimes (void)printf(" in sy cs us sy id\n"); 4811590Srgrimes hdrcnt = winlines - 2; 4821590Srgrimes} 4831590Srgrimes 4841590Srgrimes/* 4851590Srgrimes * Force a header to be prepended to the next output. 4861590Srgrimes */ 4871590Srgrimesvoid 4881590Srgrimesneedhdr() 4891590Srgrimes{ 4901590Srgrimes 4911590Srgrimes hdrcnt = 1; 4921590Srgrimes} 4931590Srgrimes 49430180Sdima#ifdef notyet 4951590Srgrimesvoid 4961590Srgrimesdotimes() 4971590Srgrimes{ 4981590Srgrimes u_int pgintime, rectime; 4991590Srgrimes 5001590Srgrimes kread(X_REC, &rectime, sizeof(rectime)); 5011590Srgrimes kread(X_PGIN, &pgintime, sizeof(pgintime)); 5021590Srgrimes kread(X_SUM, &sum, sizeof(sum)); 5031590Srgrimes (void)printf("%u reclaims, %u total time (usec)\n", 5041590Srgrimes sum.v_pgrec, rectime); 5051590Srgrimes (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 5061590Srgrimes (void)printf("\n"); 5071590Srgrimes (void)printf("%u page ins, %u total time (msec)\n", 5081590Srgrimes sum.v_pgin, pgintime / 10); 5091590Srgrimes (void)printf("average: %8.1f msec / page in\n", 5101590Srgrimes pgintime / (sum.v_pgin * 10.0)); 5111590Srgrimes} 5121590Srgrimes#endif 5131590Srgrimes 51428693Scharnierlong 5151590Srgrimespct(top, bot) 5161590Srgrimes long top, bot; 5171590Srgrimes{ 5181590Srgrimes long ans; 5191590Srgrimes 5201590Srgrimes if (bot == 0) 5211590Srgrimes return(0); 5221590Srgrimes ans = (quad_t)top * 100 / bot; 5231590Srgrimes return (ans); 5241590Srgrimes} 5251590Srgrimes 5261590Srgrimes#define PCT(top, bot) pct((long)(top), (long)(bot)) 5271590Srgrimes 5281590Srgrimes#if defined(tahoe) 5291590Srgrimes#include <machine/cpu.h> 5301590Srgrimes#endif 5311590Srgrimes 5321590Srgrimesvoid 5331590Srgrimesdosum() 5341590Srgrimes{ 5351590Srgrimes struct nchstats nchstats; 5361590Srgrimes long nchtotal; 5371590Srgrimes#if defined(tahoe) 5381590Srgrimes struct keystats keystats; 5391590Srgrimes#endif 5401590Srgrimes 5411590Srgrimes kread(X_SUM, &sum, sizeof(sum)); 5421590Srgrimes (void)printf("%9u cpu context switches\n", sum.v_swtch); 5431590Srgrimes (void)printf("%9u device interrupts\n", sum.v_intr); 5441590Srgrimes (void)printf("%9u software interrupts\n", sum.v_soft); 5451590Srgrimes#ifdef vax 5461590Srgrimes (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 5471590Srgrimes#endif 5481590Srgrimes (void)printf("%9u traps\n", sum.v_trap); 5491590Srgrimes (void)printf("%9u system calls\n", sum.v_syscall); 5503659Sdg (void)printf("%9u swap pager pageins\n", sum.v_swapin); 5513693Sdg (void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin); 5523659Sdg (void)printf("%9u swap pager pageouts\n", sum.v_swapout); 5533659Sdg (void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout); 5543659Sdg (void)printf("%9u vnode pager pageins\n", sum.v_vnodein); 5553693Sdg (void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin); 5563659Sdg (void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout); 5573659Sdg (void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout); 5583693Sdg (void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups); 5593693Sdg (void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages); 5601590Srgrimes (void)printf("%9u pages reactivated\n", sum.v_reactivated); 5617351Sdg (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 56234214Sdyson (void)printf("%9u copy-on-write optimized faults\n", sum.v_cow_optim); 5637351Sdg (void)printf("%9u zero fill pages zeroed\n", sum.v_zfod); 56434214Sdyson (void)printf("%9u zero fill pages prezeroed\n", sum.v_ozfod); 5651590Srgrimes (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 5661590Srgrimes (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 5673693Sdg (void)printf("%9u pages freed\n", sum.v_tfree); 5681590Srgrimes (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 5691590Srgrimes (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 5701590Srgrimes (void)printf("%9u pages active\n", sum.v_active_count); 5711590Srgrimes (void)printf("%9u pages inactive\n", sum.v_inactive_count); 5725463Sdg (void)printf("%9u pages in VM cache\n", sum.v_cache_count); 5733693Sdg (void)printf("%9u pages wired down\n", sum.v_wire_count); 5743693Sdg (void)printf("%9u pages free\n", sum.v_free_count); 5751590Srgrimes (void)printf("%9u bytes per page\n", sum.v_page_size); 5761590Srgrimes kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 5771590Srgrimes nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 5781590Srgrimes nchstats.ncs_badhits + nchstats.ncs_falsehits + 5791590Srgrimes nchstats.ncs_miss + nchstats.ncs_long; 5801590Srgrimes (void)printf("%9ld total name lookups\n", nchtotal); 5811590Srgrimes (void)printf( 58228693Scharnier "%9s cache hits (%ld%% pos + %ld%% neg) system %ld%% per-directory\n", 5831590Srgrimes "", PCT(nchstats.ncs_goodhits, nchtotal), 5841590Srgrimes PCT(nchstats.ncs_neghits, nchtotal), 5851590Srgrimes PCT(nchstats.ncs_pass2, nchtotal)); 58628693Scharnier (void)printf("%9s deletions %ld%%, falsehits %ld%%, toolong %ld%%\n", "", 5871590Srgrimes PCT(nchstats.ncs_badhits, nchtotal), 5881590Srgrimes PCT(nchstats.ncs_falsehits, nchtotal), 5891590Srgrimes PCT(nchstats.ncs_long, nchtotal)); 5901590Srgrimes#if defined(tahoe) 5911590Srgrimes kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 5921590Srgrimes (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 5931590Srgrimes keystats.ks_allocs, "code cache keys allocated", 5941590Srgrimes PCT(keystats.ks_allocfree, keystats.ks_allocs), 5951590Srgrimes PCT(keystats.ks_norefs, keystats.ks_allocs), 5961590Srgrimes PCT(keystats.ks_taken, keystats.ks_allocs), 5971590Srgrimes PCT(keystats.ks_shared, keystats.ks_allocs)); 5981590Srgrimes kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 5991590Srgrimes (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 6001590Srgrimes keystats.ks_allocs, "data cache keys allocated", 6011590Srgrimes PCT(keystats.ks_allocfree, keystats.ks_allocs), 6021590Srgrimes PCT(keystats.ks_norefs, keystats.ks_allocs), 6031590Srgrimes PCT(keystats.ks_taken, keystats.ks_allocs), 6041590Srgrimes PCT(keystats.ks_shared, keystats.ks_allocs)); 6051590Srgrimes#endif 6061590Srgrimes} 6071590Srgrimes 60830180Sdima#ifdef notyet 6091590Srgrimesvoid 6101590Srgrimesdoforkst() 6111590Srgrimes{ 6121590Srgrimes struct forkstat fks; 6131590Srgrimes 6141590Srgrimes kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 6151590Srgrimes (void)printf("%d forks, %d pages, average %.2f\n", 6161590Srgrimes fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 6171590Srgrimes (void)printf("%d vforks, %d pages, average %.2f\n", 6181590Srgrimes fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 6191590Srgrimes} 6201590Srgrimes#endif 6211590Srgrimes 6221590Srgrimesvoid 6231590Srgrimesdkstats() 6241590Srgrimes{ 6251590Srgrimes register int dn, state; 6261590Srgrimes double etime; 6271590Srgrimes long tmp; 6281590Srgrimes 6291590Srgrimes for (dn = 0; dn < dk_ndrive; ++dn) { 6301590Srgrimes tmp = cur.xfer[dn]; 6311590Srgrimes cur.xfer[dn] -= last.xfer[dn]; 6321590Srgrimes last.xfer[dn] = tmp; 6331590Srgrimes } 6341590Srgrimes etime = 0; 6351590Srgrimes for (state = 0; state < CPUSTATES; ++state) { 6361590Srgrimes tmp = cur.time[state]; 6371590Srgrimes cur.time[state] -= last.time[state]; 6381590Srgrimes last.time[state] = tmp; 6391590Srgrimes etime += cur.time[state]; 6401590Srgrimes } 6411590Srgrimes if (etime == 0) 6421590Srgrimes etime = 1; 6431590Srgrimes etime /= hz; 6441590Srgrimes for (dn = 0; dn < dk_ndrive; ++dn) { 6451590Srgrimes if (!dr_select[dn]) 6461590Srgrimes continue; 6471590Srgrimes (void)printf("%2.0f ", cur.xfer[dn] / etime); 6481590Srgrimes } 6491590Srgrimes} 6501590Srgrimes 6511590Srgrimesvoid 6521590Srgrimescpustats() 6531590Srgrimes{ 6541590Srgrimes register int state; 6551590Srgrimes double pct, total; 6561590Srgrimes 6571590Srgrimes total = 0; 6581590Srgrimes for (state = 0; state < CPUSTATES; ++state) 6591590Srgrimes total += cur.time[state]; 6601590Srgrimes if (total) 6611590Srgrimes pct = 100 / total; 6621590Srgrimes else 6631590Srgrimes pct = 0; 6641590Srgrimes (void)printf("%2.0f ", (cur.time[CP_USER] + cur.time[CP_NICE]) * pct); 6651590Srgrimes (void)printf("%2.0f ", (cur.time[CP_SYS] + cur.time[CP_INTR]) * pct); 6661590Srgrimes (void)printf("%2.0f", cur.time[CP_IDLE] * pct); 6671590Srgrimes} 6681590Srgrimes 6691590Srgrimesvoid 6701590Srgrimesdointr() 6711590Srgrimes{ 6721590Srgrimes register long *intrcnt, inttotal, uptime; 6731590Srgrimes register int nintr, inamlen; 6741590Srgrimes register char *intrname; 6751590Srgrimes 6761590Srgrimes uptime = getuptime(); 6771590Srgrimes nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value; 6781590Srgrimes inamlen = 6791590Srgrimes namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value; 6801590Srgrimes intrcnt = malloc((size_t)nintr); 6811590Srgrimes intrname = malloc((size_t)inamlen); 68228693Scharnier if (intrcnt == NULL || intrname == NULL) 68328693Scharnier errx(1, "malloc"); 6841590Srgrimes kread(X_INTRCNT, intrcnt, (size_t)nintr); 6851590Srgrimes kread(X_INTRNAMES, intrname, (size_t)inamlen); 6861590Srgrimes (void)printf("interrupt total rate\n"); 6871590Srgrimes inttotal = 0; 6881590Srgrimes nintr /= sizeof(long); 6891590Srgrimes while (--nintr >= 0) { 6901590Srgrimes if (*intrcnt) 6911590Srgrimes (void)printf("%-12s %8ld %8ld\n", intrname, 6921590Srgrimes *intrcnt, *intrcnt / uptime); 6931590Srgrimes intrname += strlen(intrname) + 1; 6941590Srgrimes inttotal += *intrcnt++; 6951590Srgrimes } 6961590Srgrimes (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 6971590Srgrimes} 6981590Srgrimes 6991590Srgrimesvoid 7001590Srgrimesdomem() 7011590Srgrimes{ 7021590Srgrimes register struct kmembuckets *kp; 70330287Sphk register struct malloc_type *ks; 7041590Srgrimes register int i, j; 70530279Sphk int len, size, first, nkms; 7061590Srgrimes long totuse = 0, totfree = 0, totreq = 0; 70731560Sbde const char *name; 70830287Sphk struct malloc_type kmemstats[200],*kmsp; 70930279Sphk char *kmemnames[200]; 71030279Sphk char buf[1024]; 7111590Srgrimes struct kmembuckets buckets[MINBUCKET + 16]; 7121590Srgrimes 7131590Srgrimes kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 71430279Sphk kread(X_KMEMSTATISTICS, &kmsp, sizeof(kmsp)); 71530279Sphk for (nkms=0; nkms < 200 && kmsp; nkms++) { 71630279Sphk if (sizeof(kmemstats[0]) != kvm_read(kd, (u_long)kmsp, 71730279Sphk &kmemstats[nkms], sizeof(kmemstats[0]))) 71830279Sphk err(1,"kvm_read(%08x)", (u_long)kmsp); 71930279Sphk if (sizeof(buf) != kvm_read(kd, 72030279Sphk (u_long)kmemstats[nkms].ks_shortdesc, buf, sizeof(buf))) 72130279Sphk err(1,"kvm_read(%08x)", 72230279Sphk (u_long)kmemstats[nkms].ks_shortdesc); 72330279Sphk kmemstats[nkms].ks_shortdesc = strdup(buf); 72430279Sphk kmsp = kmemstats[nkms].ks_next; 72530279Sphk } 7261590Srgrimes (void)printf("Memory statistics by bucket size\n"); 7271590Srgrimes (void)printf( 7283372Sphk "Size In Use Free Requests HighWater Couldfree\n"); 7291590Srgrimes for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 7301590Srgrimes if (kp->kb_calls == 0) 7311590Srgrimes continue; 7321590Srgrimes size = 1 << i; 7333372Sphk if(size < 1024) 7343372Sphk (void)printf("%4d",size); 7353372Sphk else 7363372Sphk (void)printf("%3dK",size>>10); 7378874Srgrimes (void)printf(" %8ld %6ld %10ld %7ld %10ld\n", 7381590Srgrimes kp->kb_total - kp->kb_totalfree, 7391590Srgrimes kp->kb_totalfree, kp->kb_calls, 7401590Srgrimes kp->kb_highwat, kp->kb_couldfree); 7411590Srgrimes totfree += size * kp->kb_totalfree; 7421590Srgrimes } 7431590Srgrimes 7441590Srgrimes (void)printf("\nMemory usage type by bucket size\n"); 7453372Sphk (void)printf("Size Type(s)\n"); 7461590Srgrimes kp = &buckets[MINBUCKET]; 7471590Srgrimes for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) { 7481590Srgrimes if (kp->kb_calls == 0) 7491590Srgrimes continue; 7501590Srgrimes first = 1; 7511590Srgrimes len = 8; 75230279Sphk for (i = 0, ks = &kmemstats[0]; i < nkms; i++, ks++) { 7531590Srgrimes if (ks->ks_calls == 0) 7541590Srgrimes continue; 7551590Srgrimes if ((ks->ks_size & j) == 0) 7561590Srgrimes continue; 75730279Sphk name = ks->ks_shortdesc; 7581590Srgrimes len += 2 + strlen(name); 7593372Sphk if (first && j < 1024) 7603372Sphk printf("%4d %s", j, name); 7613372Sphk else if (first) 7623372Sphk printf("%3dK %s", j>>10, name); 7631590Srgrimes else 7641590Srgrimes printf(","); 7653372Sphk if (len >= 79) { 7661590Srgrimes printf("\n\t "); 7671590Srgrimes len = 10 + strlen(name); 7681590Srgrimes } 7691590Srgrimes if (!first) 7701590Srgrimes printf(" %s", name); 7711590Srgrimes first = 0; 7721590Srgrimes } 7731590Srgrimes printf("\n"); 7741590Srgrimes } 7751590Srgrimes 7761590Srgrimes (void)printf( 7773372Sphk "\nMemory statistics by type Type Kern\n"); 7781590Srgrimes (void)printf( 7793372Sphk" Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n"); 78030279Sphk for (i = 0, ks = &kmemstats[0]; i < nkms; i++, ks++) { 7811590Srgrimes if (ks->ks_calls == 0) 7821590Srgrimes continue; 7833372Sphk (void)printf("%13s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u", 78430279Sphk ks->ks_shortdesc, 7851590Srgrimes ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 7861590Srgrimes (ks->ks_maxused + 1023) / 1024, 7871590Srgrimes (ks->ks_limit + 1023) / 1024, ks->ks_calls, 7881590Srgrimes ks->ks_limblocks, ks->ks_mapblocks); 7891590Srgrimes first = 1; 7901590Srgrimes for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) { 7911590Srgrimes if ((ks->ks_size & j) == 0) 7921590Srgrimes continue; 7931590Srgrimes if (first) 7943372Sphk printf(" "); 7951590Srgrimes else 7963372Sphk printf(","); 7973372Sphk if(j<1024) 7983372Sphk printf("%d",j); 7993372Sphk else 8003372Sphk printf("%dK",j>>10); 8011590Srgrimes first = 0; 8021590Srgrimes } 8031590Srgrimes printf("\n"); 8041590Srgrimes totuse += ks->ks_memuse; 8051590Srgrimes totreq += ks->ks_calls; 8061590Srgrimes } 8071590Srgrimes (void)printf("\nMemory Totals: In Use Free Requests\n"); 8081590Srgrimes (void)printf(" %7ldK %6ldK %8ld\n", 8091590Srgrimes (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 8101590Srgrimes} 8111590Srgrimes 8121590Srgrimes/* 8131590Srgrimes * kread reads something from the kernel, given its nlist index. 8141590Srgrimes */ 8151590Srgrimesvoid 8161590Srgrimeskread(nlx, addr, size) 8171590Srgrimes int nlx; 8181590Srgrimes void *addr; 8191590Srgrimes size_t size; 8201590Srgrimes{ 8211590Srgrimes char *sym; 8221590Srgrimes 8231590Srgrimes if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { 8241590Srgrimes sym = namelist[nlx].n_name; 8251590Srgrimes if (*sym == '_') 8261590Srgrimes ++sym; 82728693Scharnier errx(1, "symbol %s not defined", sym); 8281590Srgrimes } 8291590Srgrimes if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) { 8301590Srgrimes sym = namelist[nlx].n_name; 8311590Srgrimes if (*sym == '_') 8321590Srgrimes ++sym; 83328693Scharnier errx(1, "%s: %s", sym, kvm_geterr(kd)); 8341590Srgrimes } 8351590Srgrimes} 8361590Srgrimes 8371590Srgrimesvoid 8381590Srgrimesusage() 8391590Srgrimes{ 8401590Srgrimes (void)fprintf(stderr, 84128693Scharnier"usage: vmstat [-ims] [-c count] [-M core] [-N system] [-w wait] [disks]\n"); 8421590Srgrimes exit(1); 8431590Srgrimes} 844