vmstat.c revision 215569
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"; 38123441Sbde#endif /* not lint */ 391590Srgrimes 40123441Sbde#if 0 411590Srgrimes#ifndef lint 42123441Sbdestatic char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93"; 43123441Sbde#endif /* not lint */ 4428693Scharnier#endif 451590Srgrimes 46123441Sbde#include <sys/cdefs.h> 47123441Sbde__FBSDID("$FreeBSD: head/usr.bin/vmstat/vmstat.c 215569 2010-11-20 15:22:16Z kevlo $"); 48123441Sbde 491590Srgrimes#include <sys/param.h> 501590Srgrimes#include <sys/time.h> 511590Srgrimes#include <sys/proc.h> 5212811Sbde#include <sys/uio.h> 531590Srgrimes#include <sys/namei.h> 541590Srgrimes#include <sys/malloc.h> 551590Srgrimes#include <sys/signal.h> 561590Srgrimes#include <sys/fcntl.h> 571590Srgrimes#include <sys/ioctl.h> 58111008Sphk#include <sys/resource.h> 591590Srgrimes#include <sys/sysctl.h> 60208389Ssbruno#include <sys/time.h> 6112804Speter#include <sys/vmmeter.h> 62198620Sjhb#include <sys/pcpu.h> 6312811Sbde 6412811Sbde#include <vm/vm_param.h> 6512811Sbde 6628693Scharnier#include <ctype.h> 6787690Smarkm#include <devstat.h> 6828693Scharnier#include <err.h> 6928693Scharnier#include <errno.h> 7028693Scharnier#include <kvm.h> 7128693Scharnier#include <limits.h> 72148413Srwatson#include <memstat.h> 731590Srgrimes#include <nlist.h> 7428693Scharnier#include <paths.h> 751590Srgrimes#include <stdio.h> 761590Srgrimes#include <stdlib.h> 771590Srgrimes#include <string.h> 7830180Sdima#include <sysexits.h> 7928693Scharnier#include <time.h> 8028693Scharnier#include <unistd.h> 81174573Speter#include <libutil.h> 821590Srgrimes 8387690Smarkmstatic char da[] = "da"; 8487690Smarkm 8587690Smarkmstatic struct nlist namelist[] = { 86181881Sjhb#define X_SUM 0 871590Srgrimes { "_cnt" }, 88181881Sjhb#define X_BOOTTIME 1 891590Srgrimes { "_boottime" }, 90181881Sjhb#define X_HZ 2 911590Srgrimes { "_hz" }, 92181881Sjhb#define X_STATHZ 3 931590Srgrimes { "_stathz" }, 94181881Sjhb#define X_NCHSTATS 4 951590Srgrimes { "_nchstats" }, 96181881Sjhb#define X_INTRNAMES 5 971590Srgrimes { "_intrnames" }, 98181881Sjhb#define X_EINTRNAMES 6 991590Srgrimes { "_eintrnames" }, 100181881Sjhb#define X_INTRCNT 7 1011590Srgrimes { "_intrcnt" }, 102181881Sjhb#define X_EINTRCNT 8 1031590Srgrimes { "_eintrcnt" }, 104181881Sjhb#define X_KMEMSTATS 9 105131300Sgreen { "_kmemstatistics" }, 106181881Sjhb#define X_KMEMZONES 10 107131300Sgreen { "_kmemzones" }, 10830180Sdima#ifdef notyet 109131300Sgreen#define X_DEFICIT XXX 1101590Srgrimes { "_deficit" }, 111131300Sgreen#define X_REC XXX 1121590Srgrimes { "_rectime" }, 113131300Sgreen#define X_PGIN XXX 1141590Srgrimes { "_pgintime" }, 115131300Sgreen#define X_XSTATS XXX 1161590Srgrimes { "_xstats" }, 117131300Sgreen#define X_END XXX 11892653Sjeff#else 119181881Sjhb#define X_END 11 1201590Srgrimes#endif 1211590Srgrimes { "" }, 1221590Srgrimes}; 1231590Srgrimes 124123250Sdesstatic struct statinfo cur, last; 125123250Sdesstatic int num_devices, maxshowdevs; 126123250Sdesstatic long generation; 127123250Sdesstatic struct device_selection *dev_select; 128123250Sdesstatic int num_selected; 129123250Sdesstatic struct devstat_match *matches; 130123250Sdesstatic int num_matches = 0; 131123250Sdesstatic int num_devices_specified, num_selections; 132123250Sdesstatic long select_generation; 133123250Sdesstatic char **specified_devices; 134123250Sdesstatic devstat_select_mode select_mode; 1351590Srgrimes 136123250Sdesstatic struct vmmeter sum, osum; 1371590Srgrimes 138184645Skeramida#define VMSTAT_DEFAULT_LINES 20 /* Default number of `winlines'. */ 139184645Skeramidavolatile sig_atomic_t wresized; /* Tty resized, when non-zero. */ 140184645Skeramidastatic int winlines = VMSTAT_DEFAULT_LINES; /* Current number of tty rows. */ 141184645Skeramida 142123250Sdesstatic int aflag; 143123250Sdesstatic int nflag; 144174573Speterstatic int Pflag; 145174573Speterstatic int hflag; 1461590Srgrimes 147123250Sdesstatic kvm_t *kd; 1481590Srgrimes 1491590Srgrimes#define FORKSTAT 0x01 1501590Srgrimes#define INTRSTAT 0x02 1511590Srgrimes#define MEMSTAT 0x04 1521590Srgrimes#define SUMSTAT 0x08 1531590Srgrimes#define TIMESTAT 0x10 1541590Srgrimes#define VMSTAT 0x20 15543962Sdillon#define ZMEMSTAT 0x40 1561590Srgrimes 15792922Simpstatic void cpustats(void); 158174573Speterstatic void pcpustats(int, u_long, int); 15992922Simpstatic void devstats(void); 160122300Sjmgstatic void doforkst(void); 16192922Simpstatic void dointr(void); 16292922Simpstatic void dosum(void); 163123407Sdesstatic void dovmstat(unsigned int, int); 164148790Srwatsonstatic void domemstat_malloc(void); 165148630Srwatsonstatic void domemstat_zone(void); 16692922Simpstatic void kread(int, void *, size_t); 167131300Sgreenstatic void kreado(int, void *, size_t, size_t); 168131300Sgreenstatic char *kgetstr(const char *); 16992922Simpstatic void needhdr(int); 170184645Skeramidastatic void needresize(int); 171184645Skeramidastatic void doresize(void); 172174573Speterstatic void printhdr(int, u_long); 17392922Simpstatic void usage(void); 1741590Srgrimes 17592922Simpstatic long pct(long, long); 17692922Simpstatic long getuptime(void); 17787690Smarkm 178123250Sdesstatic char **getdrivedata(char **); 17987690Smarkm 18028693Scharnierint 181123250Sdesmain(int argc, char *argv[]) 1821590Srgrimes{ 18387690Smarkm int c, todo; 184123407Sdes unsigned int interval; 185208389Ssbruno float f; 1861590Srgrimes int reps; 1871590Srgrimes char *memf, *nlistf; 18878474Sschweikh char errbuf[_POSIX2_LINE_MAX]; 1891590Srgrimes 1901590Srgrimes memf = nlistf = NULL; 1911590Srgrimes interval = reps = todo = 0; 19243822Sken maxshowdevs = 2; 193174573Speter hflag = isatty(1); 194174573Speter while ((c = getopt(argc, argv, "ac:fhHiM:mN:n:Pp:stw:z")) != -1) { 1951590Srgrimes switch (c) { 196123250Sdes case 'a': 197123250Sdes aflag++; 198123250Sdes break; 1991590Srgrimes case 'c': 2001590Srgrimes reps = atoi(optarg); 2011590Srgrimes break; 202174573Speter case 'P': 203174573Speter Pflag++; 204174573Speter break; 2051590Srgrimes case 'f': 206113460Stjr todo |= FORKSTAT; 2071590Srgrimes break; 208174573Speter case 'h': 209174573Speter hflag = 1; 210174573Speter break; 211174573Speter case 'H': 212174573Speter hflag = 0; 213174573Speter break; 2141590Srgrimes case 'i': 2151590Srgrimes todo |= INTRSTAT; 2161590Srgrimes break; 2171590Srgrimes case 'M': 2181590Srgrimes memf = optarg; 2191590Srgrimes break; 2201590Srgrimes case 'm': 2211590Srgrimes todo |= MEMSTAT; 2221590Srgrimes break; 2231590Srgrimes case 'N': 2241590Srgrimes nlistf = optarg; 2251590Srgrimes break; 22639230Sgibbs case 'n': 22739372Sdillon nflag = 1; 22839230Sgibbs maxshowdevs = atoi(optarg); 22939230Sgibbs if (maxshowdevs < 0) 23039230Sgibbs errx(1, "number of devices %d is < 0", 23139230Sgibbs maxshowdevs); 23239230Sgibbs break; 23339230Sgibbs case 'p': 234112284Sphk if (devstat_buildmatch(optarg, &matches, &num_matches) != 0) 23539230Sgibbs errx(1, "%s", devstat_errbuf); 23639230Sgibbs break; 2371590Srgrimes case 's': 2381590Srgrimes todo |= SUMSTAT; 2391590Srgrimes break; 2401590Srgrimes case 't': 24130180Sdima#ifdef notyet 2421590Srgrimes todo |= TIMESTAT; 24330180Sdima#else 24430180Sdima errx(EX_USAGE, "sorry, -t is not (re)implemented yet"); 24530180Sdima#endif 2461590Srgrimes break; 2471590Srgrimes case 'w': 248208389Ssbruno /* Convert to milliseconds. */ 249208389Ssbruno f = atof(optarg); 250208389Ssbruno interval = f * 1000; 2511590Srgrimes break; 25244067Sbde case 'z': 25344067Sbde todo |= ZMEMSTAT; 25444067Sbde break; 2551590Srgrimes case '?': 2561590Srgrimes default: 2571590Srgrimes usage(); 2581590Srgrimes } 2591590Srgrimes } 2601590Srgrimes argc -= optind; 2611590Srgrimes argv += optind; 2621590Srgrimes 2631590Srgrimes if (todo == 0) 2641590Srgrimes todo = VMSTAT; 2651590Srgrimes 266123250Sdes if (memf != NULL) { 267123250Sdes kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 268123250Sdes if (kd == NULL) 269123250Sdes errx(1, "kvm_openfiles: %s", errbuf); 270123250Sdes } 2711590Srgrimes 272123250Sdes if (kd != NULL && (c = kvm_nlist(kd, namelist)) != 0) { 2731590Srgrimes if (c > 0) { 27428693Scharnier warnx("undefined symbols:"); 2751590Srgrimes for (c = 0; 276123250Sdes c < (int)(sizeof(namelist)/sizeof(namelist[0])); 277123250Sdes c++) 2781590Srgrimes if (namelist[c].n_type == 0) 27981537Sken (void)fprintf(stderr, " %s", 2801590Srgrimes namelist[c].n_name); 2811590Srgrimes (void)fputc('\n', stderr); 2821590Srgrimes } else 28328693Scharnier warnx("kvm_nlist: %s", kvm_geterr(kd)); 2841590Srgrimes exit(1); 2851590Srgrimes } 286174573Speter if (kd && Pflag) 287174573Speter errx(1, "Cannot use -P with crash dumps"); 2881590Srgrimes 2891590Srgrimes if (todo & VMSTAT) { 29043819Sken /* 29143819Sken * Make sure that the userland devstat version matches the 29243819Sken * kernel devstat version. If not, exit and print a 29343819Sken * message informing the user of his mistake. 29443819Sken */ 295112284Sphk if (devstat_checkversion(NULL) < 0) 29643819Sken errx(1, "%s", devstat_errbuf); 29743819Sken 29843819Sken 2991590Srgrimes argv = getdrivedata(argv); 3001590Srgrimes } 3011590Srgrimes 3021590Srgrimes#define BACKWARD_COMPATIBILITY 3031590Srgrimes#ifdef BACKWARD_COMPATIBILITY 3041590Srgrimes if (*argv) { 305208389Ssbruno f = atof(*argv); 306208389Ssbruno interval = f * 1000; 3071590Srgrimes if (*++argv) 3081590Srgrimes reps = atoi(*argv); 3091590Srgrimes } 3101590Srgrimes#endif 3111590Srgrimes 3121590Srgrimes if (interval) { 3131590Srgrimes if (!reps) 3141590Srgrimes reps = -1; 3151590Srgrimes } else if (reps) 316208389Ssbruno interval = 1 * 1000; 3171590Srgrimes 3181590Srgrimes if (todo & FORKSTAT) 3191590Srgrimes doforkst(); 3201590Srgrimes if (todo & MEMSTAT) 321148790Srwatson domemstat_malloc(); 32243962Sdillon if (todo & ZMEMSTAT) 323148630Srwatson domemstat_zone(); 3241590Srgrimes if (todo & SUMSTAT) 3251590Srgrimes dosum(); 32630180Sdima#ifdef notyet 3271590Srgrimes if (todo & TIMESTAT) 3281590Srgrimes dotimes(); 3291590Srgrimes#endif 3301590Srgrimes if (todo & INTRSTAT) 3311590Srgrimes dointr(); 3321590Srgrimes if (todo & VMSTAT) 3331590Srgrimes dovmstat(interval, reps); 3341590Srgrimes exit(0); 3351590Srgrimes} 3361590Srgrimes 337123250Sdesstatic int 338123250Sdesmysysctl(const char *name, void *oldp, size_t *oldlenp, 339123250Sdes void *newp, size_t newlen) 3401590Srgrimes{ 341123250Sdes int error; 342123250Sdes 343123250Sdes error = sysctlbyname(name, oldp, oldlenp, newp, newlen); 344123250Sdes if (error != 0 && errno != ENOMEM) 345123250Sdes err(1, "sysctl(%s)", name); 346123250Sdes return (error); 347123250Sdes} 348123250Sdes 349123250Sdesstatic char ** 350123250Sdesgetdrivedata(char **argv) 351123250Sdes{ 352112284Sphk if ((num_devices = devstat_getnumdevs(NULL)) < 0) 35339230Sgibbs errx(1, "%s", devstat_errbuf); 3541590Srgrimes 355188888Sdelphij cur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); 356188888Sdelphij last.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); 35739230Sgibbs 358112284Sphk if (devstat_getdevs(NULL, &cur) == -1) 35939230Sgibbs errx(1, "%s", devstat_errbuf); 36039230Sgibbs 36139230Sgibbs num_devices = cur.dinfo->numdevs; 36239230Sgibbs generation = cur.dinfo->generation; 36339230Sgibbs 36439230Sgibbs specified_devices = (char **)malloc(sizeof(char *)); 36539230Sgibbs for (num_devices_specified = 0; *argv; ++argv) { 3661590Srgrimes if (isdigit(**argv)) 3671590Srgrimes break; 36839230Sgibbs num_devices_specified++; 36939230Sgibbs specified_devices = (char **)realloc(specified_devices, 37039230Sgibbs sizeof(char *) * 37139230Sgibbs num_devices_specified); 37239230Sgibbs specified_devices[num_devices_specified - 1] = *argv; 3731590Srgrimes } 37439230Sgibbs dev_select = NULL; 37539230Sgibbs 37639372Sdillon if (nflag == 0 && maxshowdevs < num_devices_specified) 37739372Sdillon maxshowdevs = num_devices_specified; 37839372Sdillon 37939230Sgibbs /* 38039230Sgibbs * People are generally only interested in disk statistics when 38139230Sgibbs * they're running vmstat. So, that's what we're going to give 38239230Sgibbs * them if they don't specify anything by default. We'll also give 38339230Sgibbs * them any other random devices in the system so that we get to 38439230Sgibbs * maxshowdevs devices, if that many devices exist. If the user 38539230Sgibbs * specifies devices on the command line, either through a pattern 38639230Sgibbs * match or by naming them explicitly, we will give the user only 38739230Sgibbs * those devices. 38839230Sgibbs */ 38939230Sgibbs if ((num_devices_specified == 0) && (num_matches == 0)) { 390112284Sphk if (devstat_buildmatch(da, &matches, &num_matches) != 0) 39139230Sgibbs errx(1, "%s", devstat_errbuf); 39239230Sgibbs 39339230Sgibbs select_mode = DS_SELECT_ADD; 39439230Sgibbs } else 39539230Sgibbs select_mode = DS_SELECT_ONLY; 39639230Sgibbs 39739230Sgibbs /* 39839230Sgibbs * At this point, selectdevs will almost surely indicate that the 39939230Sgibbs * device list has changed, so we don't look for return values of 0 40039230Sgibbs * or 1. If we get back -1, though, there is an error. 40139230Sgibbs */ 402112284Sphk if (devstat_selectdevs(&dev_select, &num_selected, &num_selections, 40339230Sgibbs &select_generation, generation, cur.dinfo->devices, 40439230Sgibbs num_devices, matches, num_matches, specified_devices, 40539230Sgibbs num_devices_specified, select_mode, 40639230Sgibbs maxshowdevs, 0) == -1) 40739230Sgibbs errx(1, "%s", devstat_errbuf); 40839230Sgibbs 4091590Srgrimes return(argv); 4101590Srgrimes} 4111590Srgrimes 412123250Sdesstatic long 413123250Sdesgetuptime(void) 4141590Srgrimes{ 415151417Sandre struct timespec sp; 4161590Srgrimes time_t uptime; 4171590Srgrimes 418151417Sandre (void)clock_gettime(CLOCK_MONOTONIC, &sp); 419151417Sandre uptime = sp.tv_sec; 42028693Scharnier if (uptime <= 0 || uptime > 60*60*24*365*10) 42128693Scharnier errx(1, "time makes no sense; namelist must be wrong"); 422151417Sandre 4231590Srgrimes return(uptime); 4241590Srgrimes} 4251590Srgrimes 426123250Sdesstatic void 427198620Sjhbfill_pcpu(struct pcpu ***pcpup, int* maxcpup) 428198620Sjhb{ 429198620Sjhb struct pcpu **pcpu; 430198620Sjhb 431215569Skevlo int maxcpu, i; 432198620Sjhb 433198620Sjhb *pcpup = NULL; 434198620Sjhb 435198620Sjhb if (kd == NULL) 436198620Sjhb return; 437198620Sjhb 438198620Sjhb maxcpu = kvm_getmaxcpu(kd); 439198620Sjhb if (maxcpu < 0) 440198620Sjhb errx(1, "kvm_getmaxcpu: %s", kvm_geterr(kd)); 441198620Sjhb 442198620Sjhb pcpu = calloc(maxcpu, sizeof(struct pcpu *)); 443198620Sjhb if (pcpu == NULL) 444198620Sjhb err(1, "calloc"); 445198620Sjhb 446198620Sjhb for (i = 0; i < maxcpu; i++) { 447198620Sjhb pcpu[i] = kvm_getpcpu(kd, i); 448198620Sjhb if (pcpu[i] == (struct pcpu *)-1) 449198620Sjhb errx(1, "kvm_getpcpu: %s", kvm_geterr(kd)); 450198620Sjhb } 451198620Sjhb 452198620Sjhb *maxcpup = maxcpu; 453198620Sjhb *pcpup = pcpu; 454198620Sjhb} 455198620Sjhb 456198620Sjhbstatic void 457198620Sjhbfree_pcpu(struct pcpu **pcpu, int maxcpu) 458198620Sjhb{ 459198620Sjhb int i; 460198620Sjhb 461198620Sjhb for (i = 0; i < maxcpu; i++) 462198620Sjhb free(pcpu[i]); 463198620Sjhb free(pcpu); 464198620Sjhb} 465198620Sjhb 466198620Sjhbstatic void 467123250Sdesfill_vmmeter(struct vmmeter *vmmp) 468123250Sdes{ 469198620Sjhb struct pcpu **pcpu; 470198620Sjhb int maxcpu, i; 471198620Sjhb 472123250Sdes if (kd != NULL) { 473123250Sdes kread(X_SUM, vmmp, sizeof(*vmmp)); 474198620Sjhb fill_pcpu(&pcpu, &maxcpu); 475198620Sjhb for (i = 0; i < maxcpu; i++) { 476198620Sjhb if (pcpu[i] == NULL) 477198620Sjhb continue; 478198620Sjhb#define ADD_FROM_PCPU(i, name) \ 479198620Sjhb vmmp->name += pcpu[i]->pc_cnt.name 480198620Sjhb ADD_FROM_PCPU(i, v_swtch); 481198620Sjhb ADD_FROM_PCPU(i, v_trap); 482198620Sjhb ADD_FROM_PCPU(i, v_syscall); 483198620Sjhb ADD_FROM_PCPU(i, v_intr); 484198620Sjhb ADD_FROM_PCPU(i, v_soft); 485198620Sjhb ADD_FROM_PCPU(i, v_vm_faults); 486198620Sjhb ADD_FROM_PCPU(i, v_cow_faults); 487198620Sjhb ADD_FROM_PCPU(i, v_cow_optim); 488198620Sjhb ADD_FROM_PCPU(i, v_zfod); 489198620Sjhb ADD_FROM_PCPU(i, v_ozfod); 490198620Sjhb ADD_FROM_PCPU(i, v_swapin); 491198620Sjhb ADD_FROM_PCPU(i, v_swapout); 492198620Sjhb ADD_FROM_PCPU(i, v_swappgsin); 493198620Sjhb ADD_FROM_PCPU(i, v_swappgsout); 494198620Sjhb ADD_FROM_PCPU(i, v_vnodein); 495198620Sjhb ADD_FROM_PCPU(i, v_vnodeout); 496198620Sjhb ADD_FROM_PCPU(i, v_vnodepgsin); 497198620Sjhb ADD_FROM_PCPU(i, v_vnodepgsout); 498198620Sjhb ADD_FROM_PCPU(i, v_intrans); 499198620Sjhb ADD_FROM_PCPU(i, v_tfree); 500198620Sjhb ADD_FROM_PCPU(i, v_forks); 501198620Sjhb ADD_FROM_PCPU(i, v_vforks); 502198620Sjhb ADD_FROM_PCPU(i, v_rforks); 503198620Sjhb ADD_FROM_PCPU(i, v_kthreads); 504198620Sjhb ADD_FROM_PCPU(i, v_forkpages); 505198620Sjhb ADD_FROM_PCPU(i, v_vforkpages); 506198620Sjhb ADD_FROM_PCPU(i, v_rforkpages); 507198620Sjhb ADD_FROM_PCPU(i, v_kthreadpages); 508198620Sjhb#undef ADD_FROM_PCPU 509198620Sjhb } 510198620Sjhb free_pcpu(pcpu, maxcpu); 511123250Sdes } else { 512123250Sdes size_t size = sizeof(unsigned int); 513123250Sdes#define GET_VM_STATS(cat, name) \ 514123250Sdes mysysctl("vm.stats." #cat "." #name, &vmmp->name, &size, NULL, 0) 515123250Sdes /* sys */ 516123250Sdes GET_VM_STATS(sys, v_swtch); 517123250Sdes GET_VM_STATS(sys, v_trap); 518123250Sdes GET_VM_STATS(sys, v_syscall); 519123250Sdes GET_VM_STATS(sys, v_intr); 520123250Sdes GET_VM_STATS(sys, v_soft); 5211590Srgrimes 522123250Sdes /* vm */ 523123414Sdes GET_VM_STATS(vm, v_vm_faults); 524123414Sdes GET_VM_STATS(vm, v_cow_faults); 525123414Sdes GET_VM_STATS(vm, v_cow_optim); 526123414Sdes GET_VM_STATS(vm, v_zfod); 527123414Sdes GET_VM_STATS(vm, v_ozfod); 528123414Sdes GET_VM_STATS(vm, v_swapin); 529123414Sdes GET_VM_STATS(vm, v_swapout); 530123414Sdes GET_VM_STATS(vm, v_swappgsin); 531123414Sdes GET_VM_STATS(vm, v_swappgsout); 532123414Sdes GET_VM_STATS(vm, v_vnodein); 533123414Sdes GET_VM_STATS(vm, v_vnodeout); 534123414Sdes GET_VM_STATS(vm, v_vnodepgsin); 535123414Sdes GET_VM_STATS(vm, v_vnodepgsout); 536123414Sdes GET_VM_STATS(vm, v_intrans); 537123414Sdes GET_VM_STATS(vm, v_reactivated); 538123414Sdes GET_VM_STATS(vm, v_pdwakeups); 539123414Sdes GET_VM_STATS(vm, v_pdpages); 540171633Salc GET_VM_STATS(vm, v_tcached); 541123414Sdes GET_VM_STATS(vm, v_dfree); 542123414Sdes GET_VM_STATS(vm, v_pfree); 543123414Sdes GET_VM_STATS(vm, v_tfree); 544123414Sdes GET_VM_STATS(vm, v_page_size); 545123414Sdes GET_VM_STATS(vm, v_page_count); 546123414Sdes GET_VM_STATS(vm, v_free_reserved); 547123414Sdes GET_VM_STATS(vm, v_free_target); 548123414Sdes GET_VM_STATS(vm, v_free_min); 549123414Sdes GET_VM_STATS(vm, v_free_count); 550123414Sdes GET_VM_STATS(vm, v_wire_count); 551123414Sdes GET_VM_STATS(vm, v_active_count); 552123414Sdes GET_VM_STATS(vm, v_inactive_target); 553123414Sdes GET_VM_STATS(vm, v_inactive_count); 554123414Sdes GET_VM_STATS(vm, v_cache_count); 555123414Sdes GET_VM_STATS(vm, v_cache_min); 556123414Sdes GET_VM_STATS(vm, v_cache_max); 557123414Sdes GET_VM_STATS(vm, v_pageout_free_min); 558123414Sdes GET_VM_STATS(vm, v_interrupt_free_min); 559123414Sdes /*GET_VM_STATS(vm, v_free_severe);*/ 560123250Sdes GET_VM_STATS(vm, v_forks); 561123250Sdes GET_VM_STATS(vm, v_vforks); 562123250Sdes GET_VM_STATS(vm, v_rforks); 563123250Sdes GET_VM_STATS(vm, v_kthreads); 564123250Sdes GET_VM_STATS(vm, v_forkpages); 565123250Sdes GET_VM_STATS(vm, v_vforkpages); 566123250Sdes GET_VM_STATS(vm, v_rforkpages); 567123250Sdes GET_VM_STATS(vm, v_kthreadpages); 568123250Sdes#undef GET_VM_STATS 569123250Sdes } 570123250Sdes} 571123250Sdes 572123250Sdesstatic void 573123250Sdesfill_vmtotal(struct vmtotal *vmtp) 5741590Srgrimes{ 575123250Sdes if (kd != NULL) { 576123250Sdes /* XXX fill vmtp */ 577123250Sdes errx(1, "not implemented"); 578123250Sdes } else { 579123250Sdes size_t size = sizeof(*vmtp); 580123250Sdes mysysctl("vm.vmtotal", vmtp, &size, NULL, 0); 581123250Sdes if (size != sizeof(*vmtp)) 582123250Sdes errx(1, "vm.total size mismatch"); 583123250Sdes } 584123250Sdes} 585123250Sdes 586174573Speter/* Determine how many cpu columns, and what index they are in kern.cp_times */ 587174573Speterstatic int 588174573Spetergetcpuinfo(u_long *maskp, int *maxidp) 589174573Speter{ 590174573Speter int maxcpu; 591174573Speter int maxid; 592174573Speter int ncpus; 593174573Speter int i, j; 594174573Speter int empty; 595174573Speter size_t size; 596174573Speter long *times; 597174573Speter u_long mask; 598174573Speter 599174573Speter if (kd != NULL) 600174573Speter errx(1, "not implemented"); 601174573Speter mask = 0; 602174573Speter ncpus = 0; 603174573Speter size = sizeof(maxcpu); 604174573Speter mysysctl("kern.smp.maxcpus", &maxcpu, &size, NULL, 0); 605174573Speter if (size != sizeof(maxcpu)) 606174573Speter errx(1, "sysctl kern.smp.maxcpus"); 607174573Speter size = sizeof(long) * maxcpu * CPUSTATES; 608174573Speter times = malloc(size); 609174573Speter if (times == NULL) 610174573Speter err(1, "malloc %zd bytes", size); 611174573Speter mysysctl("kern.cp_times", times, &size, NULL, 0); 612174573Speter maxid = (size / CPUSTATES / sizeof(long)) - 1; 613174573Speter for (i = 0; i <= maxid; i++) { 614174573Speter empty = 1; 615174573Speter for (j = 0; empty && j < CPUSTATES; j++) { 616174573Speter if (times[i * CPUSTATES + j] != 0) 617174573Speter empty = 0; 618174573Speter } 619174573Speter if (!empty) { 620174573Speter mask |= (1ul << i); 621174573Speter ncpus++; 622174573Speter } 623174573Speter } 624174573Speter if (maskp) 625174573Speter *maskp = mask; 626174573Speter if (maxidp) 627174573Speter *maxidp = maxid; 628174573Speter return (ncpus); 629174573Speter} 630174573Speter 631174573Speter 632174573Speterstatic void 633174573Speterprthuman(u_int64_t val, int size) 634174573Speter{ 635174573Speter char buf[10]; 636174573Speter int flags; 637174573Speter 638174573Speter if (size < 5 || size > 9) 639174573Speter errx(1, "doofus"); 640174573Speter flags = HN_B | HN_NOSPACE | HN_DECIMAL; 641174573Speter humanize_number(buf, size, val, "", HN_AUTOSCALE, flags); 642174573Speter printf("%*s", size, buf); 643174573Speter} 644174573Speter 645123250Sdesstatic int hz, hdrcnt; 646123250Sdes 647174573Speterstatic long *cur_cp_times; 648174573Speterstatic long *last_cp_times; 649174573Speterstatic size_t size_cp_times; 650174573Speter 651123250Sdesstatic void 652123407Sdesdovmstat(unsigned int interval, int reps) 653123250Sdes{ 6541590Srgrimes struct vmtotal total; 6551590Srgrimes time_t uptime, halfuptime; 65639230Sgibbs struct devinfo *tmp_dinfo; 65780551Stmm size_t size; 658174573Speter int ncpus, maxid; 659174573Speter u_long cpumask; 660208389Ssbruno int rate_adj; 6611590Srgrimes 6621590Srgrimes uptime = getuptime(); 6631590Srgrimes halfuptime = uptime / 2; 664208389Ssbruno rate_adj = 1; 665184645Skeramida 666184645Skeramida /* 667184645Skeramida * If the user stops the program (control-Z) and then resumes it, 668184645Skeramida * print out the header again. 669184645Skeramida */ 6701590Srgrimes (void)signal(SIGCONT, needhdr); 6711590Srgrimes 672184645Skeramida /* 673184645Skeramida * If our standard output is a tty, then install a SIGWINCH handler 674184645Skeramida * and set wresized so that our first iteration through the main 675184646Skeramida * vmstat loop will peek at the terminal's current rows to find out 676184645Skeramida * how many lines can fit in a screenful of output. 677184645Skeramida */ 678184645Skeramida if (isatty(fileno(stdout)) != 0) { 679184645Skeramida wresized = 1; 680184645Skeramida (void)signal(SIGWINCH, needresize); 681184645Skeramida } else { 682184645Skeramida wresized = 0; 683184645Skeramida winlines = VMSTAT_DEFAULT_LINES; 684184645Skeramida } 685184645Skeramida 686123250Sdes if (kd != NULL) { 687123250Sdes if (namelist[X_STATHZ].n_type != 0 && 688123250Sdes namelist[X_STATHZ].n_value != 0) 689123250Sdes kread(X_STATHZ, &hz, sizeof(hz)); 690123250Sdes if (!hz) 691123250Sdes kread(X_HZ, &hz, sizeof(hz)); 692123250Sdes } else { 693123250Sdes struct clockinfo clockrate; 6941590Srgrimes 695123250Sdes size = sizeof(clockrate); 696123250Sdes mysysctl("kern.clockrate", &clockrate, &size, NULL, 0); 697123250Sdes if (size != sizeof(clockrate)) 698123250Sdes errx(1, "clockrate size mismatch"); 699123250Sdes hz = clockrate.hz; 700123250Sdes } 701123250Sdes 702174573Speter if (Pflag) { 703174573Speter ncpus = getcpuinfo(&cpumask, &maxid); 704174573Speter size_cp_times = sizeof(long) * (maxid + 1) * CPUSTATES; 705188888Sdelphij cur_cp_times = calloc(1, size_cp_times); 706188888Sdelphij last_cp_times = calloc(1, size_cp_times); 707174573Speter } 7081590Srgrimes for (hdrcnt = 1;;) { 7091590Srgrimes if (!--hdrcnt) 710174573Speter printhdr(ncpus, cpumask); 711123250Sdes if (kd != NULL) { 712181881Sjhb if (kvm_getcptime(kd, cur.cp_time) < 0) 713181881Sjhb errx(1, "kvm_getcptime: %s", kvm_geterr(kd)); 714123250Sdes } else { 715123250Sdes size = sizeof(cur.cp_time); 716123250Sdes mysysctl("kern.cp_time", &cur.cp_time, &size, NULL, 0); 717123250Sdes if (size != sizeof(cur.cp_time)) 718123250Sdes errx(1, "cp_time size mismatch"); 719123250Sdes } 720174573Speter if (Pflag) { 721174573Speter size = size_cp_times; 722174573Speter mysysctl("kern.cp_times", cur_cp_times, &size, NULL, 0); 723174573Speter if (size != size_cp_times) 724174573Speter errx(1, "cp_times mismatch"); 725174573Speter } 72639230Sgibbs 72739230Sgibbs tmp_dinfo = last.dinfo; 72839230Sgibbs last.dinfo = cur.dinfo; 72939230Sgibbs cur.dinfo = tmp_dinfo; 730112288Sphk last.snap_time = cur.snap_time; 73139230Sgibbs 73239230Sgibbs /* 73339230Sgibbs * Here what we want to do is refresh our device stats. 73439230Sgibbs * getdevs() returns 1 when the device list has changed. 73539230Sgibbs * If the device list has changed, we want to go through 73639230Sgibbs * the selection process again, in case a device that we 73739230Sgibbs * were previously displaying has gone away. 73839230Sgibbs */ 739112284Sphk switch (devstat_getdevs(NULL, &cur)) { 74039230Sgibbs case -1: 74139230Sgibbs errx(1, "%s", devstat_errbuf); 74239230Sgibbs break; 74339230Sgibbs case 1: { 74439230Sgibbs int retval; 74539230Sgibbs 74639230Sgibbs num_devices = cur.dinfo->numdevs; 74739230Sgibbs generation = cur.dinfo->generation; 74839230Sgibbs 749112284Sphk retval = devstat_selectdevs(&dev_select, &num_selected, 75039230Sgibbs &num_selections, &select_generation, 75139230Sgibbs generation, cur.dinfo->devices, 75239230Sgibbs num_devices, matches, num_matches, 75339230Sgibbs specified_devices, 75439230Sgibbs num_devices_specified, select_mode, 75539230Sgibbs maxshowdevs, 0); 75639230Sgibbs switch (retval) { 75739230Sgibbs case -1: 75839230Sgibbs errx(1, "%s", devstat_errbuf); 75939230Sgibbs break; 76039230Sgibbs case 1: 761174573Speter printhdr(ncpus, cpumask); 76239230Sgibbs break; 76339230Sgibbs default: 76439230Sgibbs break; 76539230Sgibbs } 76639230Sgibbs } 76739230Sgibbs default: 76839230Sgibbs break; 76939230Sgibbs } 77039230Sgibbs 771123250Sdes fill_vmmeter(&sum); 772123250Sdes fill_vmtotal(&total); 773164718Sru (void)printf("%2d %1d %1d", 7741590Srgrimes total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); 775164718Sru#define vmstat_pgtok(a) ((a) * (sum.v_page_size >> 10)) 776208389Ssbruno#define rate(x) (((x) * rate_adj + halfuptime) / uptime) /* round */ 777174573Speter if (hflag) { 778174573Speter printf(" "); 779174573Speter prthuman(total.t_avm * (u_int64_t)sum.v_page_size, 7); 780174573Speter printf(" "); 781174573Speter prthuman(total.t_free * (u_int64_t)sum.v_page_size, 6); 782174573Speter printf(" "); 783174573Speter } else { 784174573Speter printf(" %7d ", vmstat_pgtok(total.t_avm)); 785174573Speter printf(" %6d ", vmstat_pgtok(total.t_free)); 786174573Speter } 787159200Sobrien (void)printf("%5lu ", 788123407Sdes (unsigned long)rate(sum.v_vm_faults - osum.v_vm_faults)); 7891590Srgrimes (void)printf("%3lu ", 790123407Sdes (unsigned long)rate(sum.v_reactivated - osum.v_reactivated)); 79137453Sbde (void)printf("%3lu ", 792123407Sdes (unsigned long)rate(sum.v_swapin + sum.v_vnodein - 7933659Sdg (osum.v_swapin + osum.v_vnodein))); 79437453Sbde (void)printf("%3lu ", 795123407Sdes (unsigned long)rate(sum.v_swapout + sum.v_vnodeout - 7963693Sdg (osum.v_swapout + osum.v_vnodeout))); 797159200Sobrien (void)printf("%5lu ", 798123407Sdes (unsigned long)rate(sum.v_tfree - osum.v_tfree)); 79937453Sbde (void)printf("%3lu ", 800123407Sdes (unsigned long)rate(sum.v_pdpages - osum.v_pdpages)); 80139230Sgibbs devstats(); 802174573Speter (void)printf("%4lu %4lu %4lu", 803123407Sdes (unsigned long)rate(sum.v_intr - osum.v_intr), 804123407Sdes (unsigned long)rate(sum.v_syscall - osum.v_syscall), 805123407Sdes (unsigned long)rate(sum.v_swtch - osum.v_swtch)); 806174573Speter if (Pflag) 807174573Speter pcpustats(ncpus, cpumask, maxid); 808174573Speter else 809174573Speter cpustats(); 8101590Srgrimes (void)printf("\n"); 8111590Srgrimes (void)fflush(stdout); 8121590Srgrimes if (reps >= 0 && --reps <= 0) 8131590Srgrimes break; 8141590Srgrimes osum = sum; 8151590Srgrimes uptime = interval; 816208389Ssbruno rate_adj = 1000; 8171590Srgrimes /* 8181590Srgrimes * We round upward to avoid losing low-frequency events 819208389Ssbruno * (i.e., >= 1 per interval but < 1 per millisecond). 8201590Srgrimes */ 8213659Sdg if (interval != 1) 8223659Sdg halfuptime = (uptime + 1) / 2; 8233659Sdg else 8243659Sdg halfuptime = 0; 825208389Ssbruno (void)usleep(interval * 1000); 8261590Srgrimes } 8271590Srgrimes} 8281590Srgrimes 829123250Sdesstatic void 830174573Speterprinthdr(int ncpus, u_long cpumask) 8311590Srgrimes{ 83243822Sken int i, num_shown; 8331590Srgrimes 83443822Sken num_shown = (num_selected < maxshowdevs) ? num_selected : maxshowdevs; 83578672Sschweikh (void)printf(" procs memory page%*s", 19, ""); 83643822Sken if (num_shown > 1) 83743822Sken (void)printf(" disks %*s", num_shown * 4 - 7, ""); 83843822Sken else if (num_shown == 1) 83943822Sken (void)printf("disk"); 840174573Speter (void)printf(" faults "); 841174573Speter if (Pflag) { 842174573Speter for (i = 0; i < ncpus; i++) { 843175465Speter if (cpumask & (1ul << i)) 844174573Speter printf("cpu%-2d ", i); 845174573Speter } 846174573Speter printf("\n"); 847174573Speter } else 848174573Speter printf("cpu\n"); 849159200Sobrien (void)printf(" r b w avm fre flt re pi po fr sr "); 85039230Sgibbs for (i = 0; i < num_devices; i++) 85139230Sgibbs if ((dev_select[i].selected) 85239230Sgibbs && (dev_select[i].selected <= maxshowdevs)) 85339230Sgibbs (void)printf("%c%c%d ", dev_select[i].device_name[0], 85439230Sgibbs dev_select[i].device_name[1], 85539230Sgibbs dev_select[i].unit_number); 856174573Speter (void)printf(" in sy cs"); 857174573Speter if (Pflag) { 858174573Speter for (i = 0; i < ncpus; i++) 859174573Speter printf(" us sy id"); 860174573Speter printf("\n"); 861174573Speter } else 862174573Speter printf(" us sy id\n"); 863184645Skeramida if (wresized != 0) 864184645Skeramida doresize(); 865184645Skeramida hdrcnt = winlines; 8661590Srgrimes} 8671590Srgrimes 8681590Srgrimes/* 8691590Srgrimes * Force a header to be prepended to the next output. 8701590Srgrimes */ 871123250Sdesstatic void 872123250Sdesneedhdr(int dummy __unused) 8731590Srgrimes{ 8741590Srgrimes 8751590Srgrimes hdrcnt = 1; 8761590Srgrimes} 8771590Srgrimes 878184645Skeramida/* 879184645Skeramida * When the terminal is resized, force an update of the maximum number of rows 880184645Skeramida * printed between each header repetition. Then force a new header to be 881184645Skeramida * prepended to the next output. 882184645Skeramida */ 883184645Skeramidavoid 884184645Skeramidaneedresize(int signo) 885184645Skeramida{ 886184645Skeramida 887184645Skeramida wresized = 1; 888184645Skeramida hdrcnt = 1; 889184645Skeramida} 890184645Skeramida 891184645Skeramida/* 892184645Skeramida * Update the global `winlines' count of terminal rows. 893184645Skeramida */ 894184645Skeramidavoid 895184645Skeramidadoresize(void) 896184645Skeramida{ 897184645Skeramida int status; 898184645Skeramida struct winsize w; 899184645Skeramida 900184645Skeramida for (;;) { 901184645Skeramida status = ioctl(fileno(stdout), TIOCGWINSZ, &w); 902184645Skeramida if (status == -1 && errno == EINTR) 903184645Skeramida continue; 904184645Skeramida else if (status == -1) 905184645Skeramida err(1, "ioctl"); 906184645Skeramida if (w.ws_row > 3) 907184645Skeramida winlines = w.ws_row - 3; 908184645Skeramida else 909184645Skeramida winlines = VMSTAT_DEFAULT_LINES; 910184645Skeramida break; 911184645Skeramida } 912184645Skeramida 913184645Skeramida /* 914184645Skeramida * Inhibit doresize() calls until we are rescheduled by SIGWINCH. 915184645Skeramida */ 916184645Skeramida wresized = 0; 917184645Skeramida} 918184645Skeramida 91930180Sdima#ifdef notyet 920123250Sdesstatic void 921123250Sdesdotimes(void) 9221590Srgrimes{ 923123407Sdes unsigned int pgintime, rectime; 9241590Srgrimes 9251590Srgrimes kread(X_REC, &rectime, sizeof(rectime)); 9261590Srgrimes kread(X_PGIN, &pgintime, sizeof(pgintime)); 9271590Srgrimes kread(X_SUM, &sum, sizeof(sum)); 9281590Srgrimes (void)printf("%u reclaims, %u total time (usec)\n", 9291590Srgrimes sum.v_pgrec, rectime); 9301590Srgrimes (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 9311590Srgrimes (void)printf("\n"); 9321590Srgrimes (void)printf("%u page ins, %u total time (msec)\n", 9331590Srgrimes sum.v_pgin, pgintime / 10); 9341590Srgrimes (void)printf("average: %8.1f msec / page in\n", 9351590Srgrimes pgintime / (sum.v_pgin * 10.0)); 9361590Srgrimes} 9371590Srgrimes#endif 9381590Srgrimes 939123250Sdesstatic long 940123250Sdespct(long top, long bot) 9411590Srgrimes{ 9421590Srgrimes long ans; 9431590Srgrimes 9441590Srgrimes if (bot == 0) 9451590Srgrimes return(0); 9461590Srgrimes ans = (quad_t)top * 100 / bot; 9471590Srgrimes return (ans); 9481590Srgrimes} 9491590Srgrimes 9501590Srgrimes#define PCT(top, bot) pct((long)(top), (long)(bot)) 9511590Srgrimes 952123250Sdesstatic void 953123250Sdesdosum(void) 9541590Srgrimes{ 95587690Smarkm struct nchstats lnchstats; 9561590Srgrimes long nchtotal; 9571590Srgrimes 958123250Sdes fill_vmmeter(&sum); 9591590Srgrimes (void)printf("%9u cpu context switches\n", sum.v_swtch); 9601590Srgrimes (void)printf("%9u device interrupts\n", sum.v_intr); 9611590Srgrimes (void)printf("%9u software interrupts\n", sum.v_soft); 9621590Srgrimes (void)printf("%9u traps\n", sum.v_trap); 9631590Srgrimes (void)printf("%9u system calls\n", sum.v_syscall); 96471429Sume (void)printf("%9u kernel threads created\n", sum.v_kthreads); 96571429Sume (void)printf("%9u fork() calls\n", sum.v_forks); 96671429Sume (void)printf("%9u vfork() calls\n", sum.v_vforks); 96771429Sume (void)printf("%9u rfork() calls\n", sum.v_rforks); 9683659Sdg (void)printf("%9u swap pager pageins\n", sum.v_swapin); 9693693Sdg (void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin); 9703659Sdg (void)printf("%9u swap pager pageouts\n", sum.v_swapout); 9713659Sdg (void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout); 9723659Sdg (void)printf("%9u vnode pager pageins\n", sum.v_vnodein); 9733693Sdg (void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin); 9743659Sdg (void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout); 9753659Sdg (void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout); 9763693Sdg (void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups); 9773693Sdg (void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages); 9781590Srgrimes (void)printf("%9u pages reactivated\n", sum.v_reactivated); 9797351Sdg (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 98034214Sdyson (void)printf("%9u copy-on-write optimized faults\n", sum.v_cow_optim); 9817351Sdg (void)printf("%9u zero fill pages zeroed\n", sum.v_zfod); 98234214Sdyson (void)printf("%9u zero fill pages prezeroed\n", sum.v_ozfod); 9831590Srgrimes (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 9841590Srgrimes (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 98571429Sume (void)printf("%9u pages affected by kernel thread creation\n", sum.v_kthreadpages); 98671429Sume (void)printf("%9u pages affected by fork()\n", sum.v_forkpages); 98771429Sume (void)printf("%9u pages affected by vfork()\n", sum.v_vforkpages); 98871429Sume (void)printf("%9u pages affected by rfork()\n", sum.v_rforkpages); 989171633Salc (void)printf("%9u pages cached\n", sum.v_tcached); 9903693Sdg (void)printf("%9u pages freed\n", sum.v_tfree); 9911590Srgrimes (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 9921590Srgrimes (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 9931590Srgrimes (void)printf("%9u pages active\n", sum.v_active_count); 9941590Srgrimes (void)printf("%9u pages inactive\n", sum.v_inactive_count); 9955463Sdg (void)printf("%9u pages in VM cache\n", sum.v_cache_count); 9963693Sdg (void)printf("%9u pages wired down\n", sum.v_wire_count); 9973693Sdg (void)printf("%9u pages free\n", sum.v_free_count); 9981590Srgrimes (void)printf("%9u bytes per page\n", sum.v_page_size); 999123250Sdes if (kd != NULL) { 1000123250Sdes kread(X_NCHSTATS, &lnchstats, sizeof(lnchstats)); 1001123250Sdes } else { 1002123250Sdes size_t size = sizeof(lnchstats); 1003123250Sdes mysysctl("vfs.cache.nchstats", &lnchstats, &size, NULL, 0); 1004123250Sdes if (size != sizeof(lnchstats)) 1005123250Sdes errx(1, "vfs.cache.nchstats size mismatch"); 1006123250Sdes } 100787690Smarkm nchtotal = lnchstats.ncs_goodhits + lnchstats.ncs_neghits + 100887690Smarkm lnchstats.ncs_badhits + lnchstats.ncs_falsehits + 100987690Smarkm lnchstats.ncs_miss + lnchstats.ncs_long; 10101590Srgrimes (void)printf("%9ld total name lookups\n", nchtotal); 10111590Srgrimes (void)printf( 101228693Scharnier "%9s cache hits (%ld%% pos + %ld%% neg) system %ld%% per-directory\n", 101387690Smarkm "", PCT(lnchstats.ncs_goodhits, nchtotal), 101487690Smarkm PCT(lnchstats.ncs_neghits, nchtotal), 101587690Smarkm PCT(lnchstats.ncs_pass2, nchtotal)); 101628693Scharnier (void)printf("%9s deletions %ld%%, falsehits %ld%%, toolong %ld%%\n", "", 101787690Smarkm PCT(lnchstats.ncs_badhits, nchtotal), 101887690Smarkm PCT(lnchstats.ncs_falsehits, nchtotal), 101987690Smarkm PCT(lnchstats.ncs_long, nchtotal)); 10201590Srgrimes} 10211590Srgrimes 1022123250Sdesstatic void 1023123250Sdesdoforkst(void) 10241590Srgrimes{ 1025123250Sdes fill_vmmeter(&sum); 1026128573Stjr (void)printf("%u forks, %u pages, average %.2f\n", 1027113460Stjr sum.v_forks, sum.v_forkpages, 1028113460Stjr sum.v_forks == 0 ? 0.0 : 1029113460Stjr (double)sum.v_forkpages / sum.v_forks); 1030128573Stjr (void)printf("%u vforks, %u pages, average %.2f\n", 1031113460Stjr sum.v_vforks, sum.v_vforkpages, 1032113460Stjr sum.v_vforks == 0 ? 0.0 : 1033113460Stjr (double)sum.v_vforkpages / sum.v_vforks); 1034128573Stjr (void)printf("%u rforks, %u pages, average %.2f\n", 1035113460Stjr sum.v_rforks, sum.v_rforkpages, 1036113460Stjr sum.v_rforks == 0 ? 0.0 : 1037113460Stjr (double)sum.v_rforkpages / sum.v_rforks); 10381590Srgrimes} 10391590Srgrimes 104039230Sgibbsstatic void 1041123250Sdesdevstats(void) 10421590Srgrimes{ 104387690Smarkm int dn, state; 104439230Sgibbs long double transfers_per_second; 104539230Sgibbs long double busy_seconds; 10461590Srgrimes long tmp; 1047123250Sdes 10481590Srgrimes for (state = 0; state < CPUSTATES; ++state) { 104939230Sgibbs tmp = cur.cp_time[state]; 105039230Sgibbs cur.cp_time[state] -= last.cp_time[state]; 105139230Sgibbs last.cp_time[state] = tmp; 10521590Srgrimes } 105339230Sgibbs 1054112288Sphk busy_seconds = cur.snap_time - last.snap_time; 105539230Sgibbs 105639230Sgibbs for (dn = 0; dn < num_devices; dn++) { 105739230Sgibbs int di; 105839230Sgibbs 105939230Sgibbs if ((dev_select[dn].selected == 0) 106039230Sgibbs || (dev_select[dn].selected > maxshowdevs)) 10611590Srgrimes continue; 106239230Sgibbs 106339230Sgibbs di = dev_select[dn].position; 106439230Sgibbs 106581537Sken if (devstat_compute_statistics(&cur.dinfo->devices[di], 106681537Sken &last.dinfo->devices[di], busy_seconds, 106781537Sken DSM_TRANSFERS_PER_SECOND, &transfers_per_second, 106881537Sken DSM_NONE) != 0) 106939230Sgibbs errx(1, "%s", devstat_errbuf); 107039230Sgibbs 107181537Sken (void)printf("%3.0Lf ", transfers_per_second); 10721590Srgrimes } 10731590Srgrimes} 10741590Srgrimes 1075123250Sdesstatic void 1076174573Speterpercent(double pct, int *over) 1077174573Speter{ 1078174573Speter char buf[10]; 1079174573Speter int l; 1080174573Speter 1081174573Speter l = snprintf(buf, sizeof(buf), "%.0f", pct); 1082174573Speter if (l == 1 && *over) { 1083174573Speter printf("%s", buf); 1084174573Speter (*over)--; 1085174573Speter } else 1086174573Speter printf("%2s", buf); 1087174573Speter if (l > 2) 1088174573Speter (*over)++; 1089174573Speter} 1090174573Speter 1091174573Speterstatic void 1092123250Sdescpustats(void) 10931590Srgrimes{ 1094174573Speter int state, over; 109587690Smarkm double lpct, total; 10961590Srgrimes 10971590Srgrimes total = 0; 10981590Srgrimes for (state = 0; state < CPUSTATES; ++state) 109939230Sgibbs total += cur.cp_time[state]; 11001590Srgrimes if (total) 110187690Smarkm lpct = 100.0 / total; 11021590Srgrimes else 110387690Smarkm lpct = 0.0; 1104174573Speter over = 0; 1105174573Speter printf(" "); 1106174573Speter percent((cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * lpct, &over); 1107174573Speter printf(" "); 1108174573Speter percent((cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * lpct, &over); 1109174573Speter printf(" "); 1110174573Speter percent(cur.cp_time[CP_IDLE] * lpct, &over); 11111590Srgrimes} 11121590Srgrimes 1113123250Sdesstatic void 1114174573Speterpcpustats(int ncpus, u_long cpumask, int maxid) 1115174573Speter{ 1116174573Speter int state, i; 1117174573Speter double lpct, total; 1118174573Speter long tmp; 1119174573Speter int over; 1120174573Speter 1121174573Speter /* devstats does this for cp_time */ 1122174573Speter for (i = 0; i <= maxid; i++) { 1123175465Speter if ((cpumask & (1ul << i)) == 0) 1124174573Speter continue; 1125174573Speter for (state = 0; state < CPUSTATES; ++state) { 1126174573Speter tmp = cur_cp_times[i * CPUSTATES + state]; 1127174573Speter cur_cp_times[i * CPUSTATES + state] -= last_cp_times[i * CPUSTATES + state]; 1128174573Speter last_cp_times[i * CPUSTATES + state] = tmp; 1129174573Speter } 1130174573Speter } 1131174573Speter 1132174573Speter over = 0; 1133174573Speter for (i = 0; i <= maxid; i++) { 1134175465Speter if ((cpumask & (1ul << i)) == 0) 1135174573Speter continue; 1136174573Speter total = 0; 1137174573Speter for (state = 0; state < CPUSTATES; ++state) 1138174573Speter total += cur_cp_times[i * CPUSTATES + state]; 1139174573Speter if (total) 1140174573Speter lpct = 100.0 / total; 1141174573Speter else 1142174573Speter lpct = 0.0; 1143174573Speter printf(" "); 1144174573Speter percent((cur_cp_times[i * CPUSTATES + CP_USER] + 1145174573Speter cur_cp_times[i * CPUSTATES + CP_NICE]) * lpct, &over); 1146174573Speter printf(" "); 1147174573Speter percent((cur_cp_times[i * CPUSTATES + CP_SYS] + 1148174573Speter cur_cp_times[i * CPUSTATES + CP_INTR]) * lpct, &over); 1149174573Speter printf(" "); 1150174573Speter percent(cur_cp_times[i * CPUSTATES + CP_IDLE] * lpct, &over); 1151174573Speter } 1152174573Speter} 1153174573Speter 1154174573Speterstatic void 1155123250Sdesdointr(void) 11561590Srgrimes{ 1157123407Sdes unsigned long *intrcnt, uptime; 1158123409Sdes uint64_t inttotal; 1159123409Sdes size_t clen, inamlen, intrcntlen, istrnamlen; 1160123409Sdes unsigned int i, nintr; 1161121626Sjmg char *intrname, *tintrname; 11621590Srgrimes 11631590Srgrimes uptime = getuptime(); 1164123250Sdes if (kd != NULL) { 1165123409Sdes intrcntlen = namelist[X_EINTRCNT].n_value - 1166123250Sdes namelist[X_INTRCNT].n_value; 1167123250Sdes inamlen = namelist[X_EINTRNAMES].n_value - 1168123250Sdes namelist[X_INTRNAMES].n_value; 1169123409Sdes if ((intrcnt = malloc(intrcntlen)) == NULL || 1170123290Smarcel (intrname = malloc(inamlen)) == NULL) 1171123250Sdes err(1, "malloc()"); 1172123409Sdes kread(X_INTRCNT, intrcnt, intrcntlen); 1173123290Smarcel kread(X_INTRNAMES, intrname, inamlen); 1174123250Sdes } else { 1175123438Sdes for (intrcnt = NULL, intrcntlen = 1024; ; intrcntlen *= 2) { 1176123438Sdes if ((intrcnt = reallocf(intrcnt, intrcntlen)) == NULL) 1177123438Sdes err(1, "reallocf()"); 1178123438Sdes if (mysysctl("hw.intrcnt", 1179123438Sdes intrcnt, &intrcntlen, NULL, 0) == 0) 1180123438Sdes break; 1181123438Sdes } 1182123250Sdes for (intrname = NULL, inamlen = 1024; ; inamlen *= 2) { 1183123250Sdes if ((intrname = reallocf(intrname, inamlen)) == NULL) 1184123250Sdes err(1, "reallocf()"); 1185123250Sdes if (mysysctl("hw.intrnames", 1186123250Sdes intrname, &inamlen, NULL, 0) == 0) 1187123250Sdes break; 1188123250Sdes } 1189123250Sdes } 1190123409Sdes nintr = intrcntlen / sizeof(unsigned long); 1191121626Sjmg tintrname = intrname; 1192122365Sjmg istrnamlen = strlen("interrupt"); 1193121626Sjmg for (i = 0; i < nintr; i++) { 1194121626Sjmg clen = strlen(tintrname); 1195121626Sjmg if (clen > istrnamlen) 1196121626Sjmg istrnamlen = clen; 1197121626Sjmg tintrname += clen + 1; 1198121626Sjmg } 1199121626Sjmg (void)printf("%-*s %20s %10s\n", istrnamlen, "interrupt", "total", 1200121626Sjmg "rate"); 12011590Srgrimes inttotal = 0; 1202123290Smarcel for (i = 0; i < nintr; i++) { 1203123409Sdes if (intrname[0] != '\0' && (*intrcnt != 0 || aflag)) 1204121626Sjmg (void)printf("%-*s %20lu %10lu\n", istrnamlen, intrname, 12051590Srgrimes *intrcnt, *intrcnt / uptime); 12061590Srgrimes intrname += strlen(intrname) + 1; 12071590Srgrimes inttotal += *intrcnt++; 12081590Srgrimes } 1209123290Smarcel (void)printf("%-*s %20llu %10llu\n", istrnamlen, "Total", 1210123290Smarcel (long long)inttotal, (long long)(inttotal / uptime)); 12111590Srgrimes} 12121590Srgrimes 1213148413Srwatsonstatic void 1214148413Srwatsondomemstat_malloc(void) 1215148413Srwatson{ 1216148413Srwatson struct memory_type_list *mtlp; 1217148413Srwatson struct memory_type *mtp; 1218148790Srwatson int error, first, i; 1219148413Srwatson 1220148413Srwatson mtlp = memstat_mtl_alloc(); 1221148413Srwatson if (mtlp == NULL) { 1222148413Srwatson warn("memstat_mtl_alloc"); 1223148413Srwatson return; 1224148413Srwatson } 1225148790Srwatson if (kd == NULL) { 1226148790Srwatson if (memstat_sysctl_malloc(mtlp, 0) < 0) { 1227148790Srwatson warnx("memstat_sysctl_malloc: %s", 1228148790Srwatson memstat_strerror(memstat_mtl_geterror(mtlp))); 1229148790Srwatson return; 1230148790Srwatson } 1231148790Srwatson } else { 1232148790Srwatson if (memstat_kvm_malloc(mtlp, kd) < 0) { 1233148790Srwatson error = memstat_mtl_geterror(mtlp); 1234148790Srwatson if (error == MEMSTAT_ERROR_KVM) 1235148790Srwatson warnx("memstat_kvm_malloc: %s", 1236148790Srwatson kvm_geterr(kd)); 1237148790Srwatson else 1238148790Srwatson warnx("memstat_kvm_malloc: %s", 1239148790Srwatson memstat_strerror(error)); 1240148790Srwatson } 1241148413Srwatson } 1242148413Srwatson printf("%13s %5s %6s %7s %8s Size(s)\n", "Type", "InUse", "MemUse", 1243148413Srwatson "HighUse", "Requests"); 1244148413Srwatson for (mtp = memstat_mtl_first(mtlp); mtp != NULL; 1245148413Srwatson mtp = memstat_mtl_next(mtp)) { 1246148413Srwatson if (memstat_get_numallocs(mtp) == 0 && 1247148413Srwatson memstat_get_count(mtp) == 0) 1248148413Srwatson continue; 1249148413Srwatson printf("%13s %5lld %5lldK %7s %8lld ", 1250148413Srwatson memstat_get_name(mtp), memstat_get_count(mtp), 1251148413Srwatson ((int64_t)memstat_get_bytes(mtp) + 1023) / 1024, "-", 1252148413Srwatson memstat_get_numallocs(mtp)); 1253148413Srwatson first = 1; 1254148413Srwatson for (i = 0; i < 32; i++) { 1255148413Srwatson if (memstat_get_sizemask(mtp) & (1 << i)) { 1256148413Srwatson if (!first) 1257148413Srwatson printf(","); 1258148413Srwatson printf("%d", 1 << (i + 4)); 1259148413Srwatson first = 0; 1260148413Srwatson } 1261148413Srwatson } 1262148413Srwatson printf("\n"); 1263148413Srwatson } 1264148413Srwatson memstat_mtl_free(mtlp); 1265148413Srwatson} 1266148413Srwatson 1267148413Srwatsonstatic void 1268148413Srwatsondomemstat_zone(void) 1269148413Srwatson{ 1270148413Srwatson struct memory_type_list *mtlp; 1271148413Srwatson struct memory_type *mtp; 1272148413Srwatson char name[MEMTYPE_MAXNAME + 1]; 1273148630Srwatson int error; 1274148413Srwatson 1275148413Srwatson mtlp = memstat_mtl_alloc(); 1276148413Srwatson if (mtlp == NULL) { 1277148413Srwatson warn("memstat_mtl_alloc"); 1278148413Srwatson return; 1279148413Srwatson } 1280148630Srwatson if (kd == NULL) { 1281148630Srwatson if (memstat_sysctl_uma(mtlp, 0) < 0) { 1282148630Srwatson warnx("memstat_sysctl_uma: %s", 1283148630Srwatson memstat_strerror(memstat_mtl_geterror(mtlp))); 1284148630Srwatson return; 1285148630Srwatson } 1286148630Srwatson } else { 1287148630Srwatson if (memstat_kvm_uma(mtlp, kd) < 0) { 1288148630Srwatson error = memstat_mtl_geterror(mtlp); 1289148630Srwatson if (error == MEMSTAT_ERROR_KVM) 1290148630Srwatson warnx("memstat_kvm_uma: %s", 1291148630Srwatson kvm_geterr(kd)); 1292148630Srwatson else 1293148630Srwatson warnx("memstat_kvm_uma: %s", 1294148630Srwatson memstat_strerror(error)); 1295148630Srwatson } 1296148413Srwatson } 1297209215Ssbruno printf("%-20s %6s %6s %8s %8s %8s %4s %4s\n\n", "ITEM", "SIZE", 1298209215Ssbruno "LIMIT", "USED", "FREE", "REQ", "FAIL", "SLEEP"); 1299148413Srwatson for (mtp = memstat_mtl_first(mtlp); mtp != NULL; 1300148413Srwatson mtp = memstat_mtl_next(mtp)) { 1301148413Srwatson strlcpy(name, memstat_get_name(mtp), MEMTYPE_MAXNAME); 1302148413Srwatson strcat(name, ":"); 1303209215Ssbruno printf("%-20s %6llu, %6llu,%8llu,%8llu,%8llu,%4llu,%4llu\n",name, 1304148413Srwatson memstat_get_size(mtp), memstat_get_countlimit(mtp), 1305148413Srwatson memstat_get_count(mtp), memstat_get_free(mtp), 1306209215Ssbruno memstat_get_numallocs(mtp), memstat_get_failures(mtp), 1307209215Ssbruno memstat_get_sleeps(mtp)); 1308148413Srwatson } 1309148413Srwatson memstat_mtl_free(mtlp); 1310148413Srwatson printf("\n"); 1311148413Srwatson} 1312148413Srwatson 1313148413Srwatson/* 13141590Srgrimes * kread reads something from the kernel, given its nlist index. 13151590Srgrimes */ 1316123250Sdesstatic void 1317131300Sgreenkreado(int nlx, void *addr, size_t size, size_t offset) 13181590Srgrimes{ 1319123825Sdwmalone const char *sym; 13201590Srgrimes 132140690Sjdp if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { 13221590Srgrimes sym = namelist[nlx].n_name; 13231590Srgrimes if (*sym == '_') 13241590Srgrimes ++sym; 132528693Scharnier errx(1, "symbol %s not defined", sym); 13261590Srgrimes } 1327131300Sgreen if ((size_t)kvm_read(kd, namelist[nlx].n_value + offset, addr, 1328131300Sgreen size) != size) { 13291590Srgrimes sym = namelist[nlx].n_name; 13301590Srgrimes if (*sym == '_') 13311590Srgrimes ++sym; 133228693Scharnier errx(1, "%s: %s", sym, kvm_geterr(kd)); 13331590Srgrimes } 13341590Srgrimes} 13351590Srgrimes 1336123250Sdesstatic void 1337131300Sgreenkread(int nlx, void *addr, size_t size) 1338131300Sgreen{ 1339131300Sgreen kreado(nlx, addr, size, 0); 1340131300Sgreen} 1341131300Sgreen 1342131300Sgreenstatic char * 1343131300Sgreenkgetstr(const char *strp) 1344131300Sgreen{ 1345131300Sgreen int n = 0, size = 1; 1346131300Sgreen char *ret = NULL; 1347131300Sgreen 1348131300Sgreen do { 1349131300Sgreen if (size == n + 1) { 1350131300Sgreen ret = realloc(ret, size); 1351131300Sgreen if (ret == NULL) 1352131300Sgreen err(1, "%s: realloc", __func__); 1353131300Sgreen size *= 2; 1354131300Sgreen } 1355131300Sgreen if (kvm_read(kd, (u_long)strp + n, &ret[n], 1) != 1) 1356131300Sgreen errx(1, "%s: %s", __func__, kvm_geterr(kd)); 1357131300Sgreen } while (ret[n++] != '\0'); 1358131300Sgreen return (ret); 1359131300Sgreen} 1360131300Sgreen 1361131300Sgreenstatic void 1362123250Sdesusage(void) 13631590Srgrimes{ 136472887Salfred (void)fprintf(stderr, "%s%s", 1365178063Sru "usage: vmstat [-afHhimPsz] [-c count] [-M core [-N system]] [-w wait]\n", 1366146466Sru " [-n devs] [-p type,if,pass] [disks]\n"); 13671590Srgrimes exit(1); 13681590Srgrimes} 1369