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 * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3128693Scharnierstatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1980, 1986, 1991, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 34123441Sbde#endif /* not lint */ 351590Srgrimes 36123441Sbde#if 0 371590Srgrimes#ifndef lint 38123441Sbdestatic char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93"; 39123441Sbde#endif /* not lint */ 4028693Scharnier#endif 411590Srgrimes 42123441Sbde#include <sys/cdefs.h> 43123441Sbde__FBSDID("$FreeBSD: releng/10.3/usr.bin/vmstat/vmstat.c 288453 2015-10-01 17:09:20Z jhb $"); 44123441Sbde 451590Srgrimes#include <sys/param.h> 461590Srgrimes#include <sys/proc.h> 4712811Sbde#include <sys/uio.h> 481590Srgrimes#include <sys/namei.h> 491590Srgrimes#include <sys/malloc.h> 501590Srgrimes#include <sys/signal.h> 511590Srgrimes#include <sys/fcntl.h> 521590Srgrimes#include <sys/ioctl.h> 53111008Sphk#include <sys/resource.h> 541590Srgrimes#include <sys/sysctl.h> 55208389Ssbruno#include <sys/time.h> 56288453Sjhb#include <sys/user.h> 5712804Speter#include <sys/vmmeter.h> 58198620Sjhb#include <sys/pcpu.h> 5912811Sbde 6012811Sbde#include <vm/vm_param.h> 6112811Sbde 6228693Scharnier#include <ctype.h> 6387690Smarkm#include <devstat.h> 6428693Scharnier#include <err.h> 6528693Scharnier#include <errno.h> 66228654Sdim#include <inttypes.h> 6728693Scharnier#include <kvm.h> 6828693Scharnier#include <limits.h> 69148413Srwatson#include <memstat.h> 701590Srgrimes#include <nlist.h> 7128693Scharnier#include <paths.h> 721590Srgrimes#include <stdio.h> 731590Srgrimes#include <stdlib.h> 741590Srgrimes#include <string.h> 7530180Sdima#include <sysexits.h> 7628693Scharnier#include <time.h> 7728693Scharnier#include <unistd.h> 78174573Speter#include <libutil.h> 791590Srgrimes 8087690Smarkmstatic char da[] = "da"; 8187690Smarkm 8287690Smarkmstatic struct nlist namelist[] = { 83181881Sjhb#define X_SUM 0 841590Srgrimes { "_cnt" }, 85233298Spluknet#define X_HZ 1 861590Srgrimes { "_hz" }, 87233298Spluknet#define X_STATHZ 2 881590Srgrimes { "_stathz" }, 89233298Spluknet#define X_NCHSTATS 3 901590Srgrimes { "_nchstats" }, 91233298Spluknet#define X_INTRNAMES 4 921590Srgrimes { "_intrnames" }, 93233298Spluknet#define X_SINTRNAMES 5 94224187Sattilio { "_sintrnames" }, 95233298Spluknet#define X_INTRCNT 6 961590Srgrimes { "_intrcnt" }, 97233298Spluknet#define X_SINTRCNT 7 98224187Sattilio { "_sintrcnt" }, 9930180Sdima#ifdef notyet 100131300Sgreen#define X_DEFICIT XXX 1011590Srgrimes { "_deficit" }, 102131300Sgreen#define X_REC XXX 1031590Srgrimes { "_rectime" }, 104131300Sgreen#define X_PGIN XXX 1051590Srgrimes { "_pgintime" }, 106131300Sgreen#define X_XSTATS XXX 1071590Srgrimes { "_xstats" }, 108131300Sgreen#define X_END XXX 10992653Sjeff#else 110233298Spluknet#define X_END 8 1111590Srgrimes#endif 1121590Srgrimes { "" }, 1131590Srgrimes}; 1141590Srgrimes 115123250Sdesstatic struct statinfo cur, last; 116123250Sdesstatic int num_devices, maxshowdevs; 117123250Sdesstatic long generation; 118123250Sdesstatic struct device_selection *dev_select; 119123250Sdesstatic int num_selected; 120123250Sdesstatic struct devstat_match *matches; 121123250Sdesstatic int num_matches = 0; 122123250Sdesstatic int num_devices_specified, num_selections; 123123250Sdesstatic long select_generation; 124123250Sdesstatic char **specified_devices; 125123250Sdesstatic devstat_select_mode select_mode; 1261590Srgrimes 127123250Sdesstatic struct vmmeter sum, osum; 1281590Srgrimes 129184645Skeramida#define VMSTAT_DEFAULT_LINES 20 /* Default number of `winlines'. */ 130184645Skeramidavolatile sig_atomic_t wresized; /* Tty resized, when non-zero. */ 131184645Skeramidastatic int winlines = VMSTAT_DEFAULT_LINES; /* Current number of tty rows. */ 132184645Skeramida 133123250Sdesstatic int aflag; 134123250Sdesstatic int nflag; 135174573Speterstatic int Pflag; 136174573Speterstatic int hflag; 1371590Srgrimes 138123250Sdesstatic kvm_t *kd; 1391590Srgrimes 1401590Srgrimes#define FORKSTAT 0x01 1411590Srgrimes#define INTRSTAT 0x02 1421590Srgrimes#define MEMSTAT 0x04 1431590Srgrimes#define SUMSTAT 0x08 1441590Srgrimes#define TIMESTAT 0x10 1451590Srgrimes#define VMSTAT 0x20 14643962Sdillon#define ZMEMSTAT 0x40 147288453Sjhb#define OBJSTAT 0x80 1481590Srgrimes 14992922Simpstatic void cpustats(void); 150174573Speterstatic void pcpustats(int, u_long, int); 15192922Simpstatic void devstats(void); 152122300Sjmgstatic void doforkst(void); 15392922Simpstatic void dointr(void); 154288453Sjhbstatic void doobjstat(void); 15592922Simpstatic void dosum(void); 156123407Sdesstatic void dovmstat(unsigned int, int); 157148790Srwatsonstatic void domemstat_malloc(void); 158148630Srwatsonstatic void domemstat_zone(void); 15992922Simpstatic void kread(int, void *, size_t); 160131300Sgreenstatic void kreado(int, void *, size_t, size_t); 161131300Sgreenstatic char *kgetstr(const char *); 16292922Simpstatic void needhdr(int); 163184645Skeramidastatic void needresize(int); 164184645Skeramidastatic void doresize(void); 165174573Speterstatic void printhdr(int, u_long); 16692922Simpstatic void usage(void); 1671590Srgrimes 16892922Simpstatic long pct(long, long); 16992922Simpstatic long getuptime(void); 17087690Smarkm 171123250Sdesstatic char **getdrivedata(char **); 17287690Smarkm 17328693Scharnierint 174123250Sdesmain(int argc, char *argv[]) 1751590Srgrimes{ 17687690Smarkm int c, todo; 177123407Sdes unsigned int interval; 178208389Ssbruno float f; 1791590Srgrimes int reps; 1801590Srgrimes char *memf, *nlistf; 18178474Sschweikh char errbuf[_POSIX2_LINE_MAX]; 1821590Srgrimes 1831590Srgrimes memf = nlistf = NULL; 1841590Srgrimes interval = reps = todo = 0; 18543822Sken maxshowdevs = 2; 186174573Speter hflag = isatty(1); 187288453Sjhb while ((c = getopt(argc, argv, "ac:fhHiM:mN:n:oPp:stw:z")) != -1) { 1881590Srgrimes switch (c) { 189123250Sdes case 'a': 190123250Sdes aflag++; 191123250Sdes break; 1921590Srgrimes case 'c': 1931590Srgrimes reps = atoi(optarg); 1941590Srgrimes break; 195174573Speter case 'P': 196174573Speter Pflag++; 197174573Speter break; 1981590Srgrimes case 'f': 199113460Stjr todo |= FORKSTAT; 2001590Srgrimes break; 201174573Speter case 'h': 202174573Speter hflag = 1; 203174573Speter break; 204174573Speter case 'H': 205174573Speter hflag = 0; 206174573Speter break; 2071590Srgrimes case 'i': 2081590Srgrimes todo |= INTRSTAT; 2091590Srgrimes break; 2101590Srgrimes case 'M': 2111590Srgrimes memf = optarg; 2121590Srgrimes break; 2131590Srgrimes case 'm': 2141590Srgrimes todo |= MEMSTAT; 2151590Srgrimes break; 2161590Srgrimes case 'N': 2171590Srgrimes nlistf = optarg; 2181590Srgrimes break; 21939230Sgibbs case 'n': 22039372Sdillon nflag = 1; 22139230Sgibbs maxshowdevs = atoi(optarg); 22239230Sgibbs if (maxshowdevs < 0) 22339230Sgibbs errx(1, "number of devices %d is < 0", 22439230Sgibbs maxshowdevs); 22539230Sgibbs break; 226288453Sjhb case 'o': 227288453Sjhb todo |= OBJSTAT; 228288453Sjhb break; 22939230Sgibbs case 'p': 230112284Sphk if (devstat_buildmatch(optarg, &matches, &num_matches) != 0) 23139230Sgibbs errx(1, "%s", devstat_errbuf); 23239230Sgibbs break; 2331590Srgrimes case 's': 2341590Srgrimes todo |= SUMSTAT; 2351590Srgrimes break; 2361590Srgrimes case 't': 23730180Sdima#ifdef notyet 2381590Srgrimes todo |= TIMESTAT; 23930180Sdima#else 24030180Sdima errx(EX_USAGE, "sorry, -t is not (re)implemented yet"); 24130180Sdima#endif 2421590Srgrimes break; 2431590Srgrimes case 'w': 244208389Ssbruno /* Convert to milliseconds. */ 245208389Ssbruno f = atof(optarg); 246208389Ssbruno interval = f * 1000; 2471590Srgrimes break; 24844067Sbde case 'z': 24944067Sbde todo |= ZMEMSTAT; 25044067Sbde break; 2511590Srgrimes case '?': 2521590Srgrimes default: 2531590Srgrimes usage(); 2541590Srgrimes } 2551590Srgrimes } 2561590Srgrimes argc -= optind; 2571590Srgrimes argv += optind; 2581590Srgrimes 2591590Srgrimes if (todo == 0) 2601590Srgrimes todo = VMSTAT; 2611590Srgrimes 262123250Sdes if (memf != NULL) { 263123250Sdes kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 264123250Sdes if (kd == NULL) 265123250Sdes errx(1, "kvm_openfiles: %s", errbuf); 266123250Sdes } 2671590Srgrimes 268123250Sdes if (kd != NULL && (c = kvm_nlist(kd, namelist)) != 0) { 2691590Srgrimes if (c > 0) { 27028693Scharnier warnx("undefined symbols:"); 2711590Srgrimes for (c = 0; 272123250Sdes c < (int)(sizeof(namelist)/sizeof(namelist[0])); 273123250Sdes c++) 2741590Srgrimes if (namelist[c].n_type == 0) 27581537Sken (void)fprintf(stderr, " %s", 2761590Srgrimes namelist[c].n_name); 2771590Srgrimes (void)fputc('\n', stderr); 2781590Srgrimes } else 27928693Scharnier warnx("kvm_nlist: %s", kvm_geterr(kd)); 2801590Srgrimes exit(1); 2811590Srgrimes } 282174573Speter if (kd && Pflag) 283174573Speter errx(1, "Cannot use -P with crash dumps"); 2841590Srgrimes 2851590Srgrimes if (todo & VMSTAT) { 28643819Sken /* 28743819Sken * Make sure that the userland devstat version matches the 28843819Sken * kernel devstat version. If not, exit and print a 28943819Sken * message informing the user of his mistake. 29043819Sken */ 291112284Sphk if (devstat_checkversion(NULL) < 0) 29243819Sken errx(1, "%s", devstat_errbuf); 29343819Sken 29443819Sken 2951590Srgrimes argv = getdrivedata(argv); 2961590Srgrimes } 2971590Srgrimes 2981590Srgrimes if (*argv) { 299208389Ssbruno f = atof(*argv); 300208389Ssbruno interval = f * 1000; 3011590Srgrimes if (*++argv) 3021590Srgrimes reps = atoi(*argv); 3031590Srgrimes } 3041590Srgrimes 3051590Srgrimes if (interval) { 3061590Srgrimes if (!reps) 3071590Srgrimes reps = -1; 3081590Srgrimes } else if (reps) 309208389Ssbruno interval = 1 * 1000; 3101590Srgrimes 3111590Srgrimes if (todo & FORKSTAT) 3121590Srgrimes doforkst(); 3131590Srgrimes if (todo & MEMSTAT) 314148790Srwatson domemstat_malloc(); 31543962Sdillon if (todo & ZMEMSTAT) 316148630Srwatson domemstat_zone(); 3171590Srgrimes if (todo & SUMSTAT) 3181590Srgrimes dosum(); 319288453Sjhb if (todo & OBJSTAT) 320288453Sjhb doobjstat(); 32130180Sdima#ifdef notyet 3221590Srgrimes if (todo & TIMESTAT) 3231590Srgrimes dotimes(); 3241590Srgrimes#endif 3251590Srgrimes if (todo & INTRSTAT) 3261590Srgrimes dointr(); 3271590Srgrimes if (todo & VMSTAT) 3281590Srgrimes dovmstat(interval, reps); 3291590Srgrimes exit(0); 3301590Srgrimes} 3311590Srgrimes 332123250Sdesstatic int 333123250Sdesmysysctl(const char *name, void *oldp, size_t *oldlenp, 334123250Sdes void *newp, size_t newlen) 3351590Srgrimes{ 336123250Sdes int error; 337123250Sdes 338123250Sdes error = sysctlbyname(name, oldp, oldlenp, newp, newlen); 339123250Sdes if (error != 0 && errno != ENOMEM) 340123250Sdes err(1, "sysctl(%s)", name); 341123250Sdes return (error); 342123250Sdes} 343123250Sdes 344123250Sdesstatic char ** 345123250Sdesgetdrivedata(char **argv) 346123250Sdes{ 347112284Sphk if ((num_devices = devstat_getnumdevs(NULL)) < 0) 34839230Sgibbs errx(1, "%s", devstat_errbuf); 3491590Srgrimes 350188888Sdelphij cur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); 351188888Sdelphij last.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo)); 35239230Sgibbs 353112284Sphk if (devstat_getdevs(NULL, &cur) == -1) 35439230Sgibbs errx(1, "%s", devstat_errbuf); 35539230Sgibbs 35639230Sgibbs num_devices = cur.dinfo->numdevs; 35739230Sgibbs generation = cur.dinfo->generation; 35839230Sgibbs 35939230Sgibbs specified_devices = (char **)malloc(sizeof(char *)); 36039230Sgibbs for (num_devices_specified = 0; *argv; ++argv) { 3611590Srgrimes if (isdigit(**argv)) 3621590Srgrimes break; 36339230Sgibbs num_devices_specified++; 36439230Sgibbs specified_devices = (char **)realloc(specified_devices, 36539230Sgibbs sizeof(char *) * 36639230Sgibbs num_devices_specified); 36739230Sgibbs specified_devices[num_devices_specified - 1] = *argv; 3681590Srgrimes } 36939230Sgibbs dev_select = NULL; 37039230Sgibbs 37139372Sdillon if (nflag == 0 && maxshowdevs < num_devices_specified) 37239372Sdillon maxshowdevs = num_devices_specified; 37339372Sdillon 37439230Sgibbs /* 37539230Sgibbs * People are generally only interested in disk statistics when 37639230Sgibbs * they're running vmstat. So, that's what we're going to give 37739230Sgibbs * them if they don't specify anything by default. We'll also give 37839230Sgibbs * them any other random devices in the system so that we get to 37939230Sgibbs * maxshowdevs devices, if that many devices exist. If the user 38039230Sgibbs * specifies devices on the command line, either through a pattern 38139230Sgibbs * match or by naming them explicitly, we will give the user only 38239230Sgibbs * those devices. 38339230Sgibbs */ 38439230Sgibbs if ((num_devices_specified == 0) && (num_matches == 0)) { 385112284Sphk if (devstat_buildmatch(da, &matches, &num_matches) != 0) 38639230Sgibbs errx(1, "%s", devstat_errbuf); 38739230Sgibbs 38839230Sgibbs select_mode = DS_SELECT_ADD; 38939230Sgibbs } else 39039230Sgibbs select_mode = DS_SELECT_ONLY; 39139230Sgibbs 39239230Sgibbs /* 39339230Sgibbs * At this point, selectdevs will almost surely indicate that the 39439230Sgibbs * device list has changed, so we don't look for return values of 0 39539230Sgibbs * or 1. If we get back -1, though, there is an error. 39639230Sgibbs */ 397112284Sphk if (devstat_selectdevs(&dev_select, &num_selected, &num_selections, 39839230Sgibbs &select_generation, generation, cur.dinfo->devices, 39939230Sgibbs num_devices, matches, num_matches, specified_devices, 40039230Sgibbs num_devices_specified, select_mode, 40139230Sgibbs maxshowdevs, 0) == -1) 40239230Sgibbs errx(1, "%s", devstat_errbuf); 40339230Sgibbs 4041590Srgrimes return(argv); 4051590Srgrimes} 4061590Srgrimes 407123250Sdesstatic long 408123250Sdesgetuptime(void) 4091590Srgrimes{ 410151417Sandre struct timespec sp; 4111590Srgrimes 412151417Sandre (void)clock_gettime(CLOCK_MONOTONIC, &sp); 413151417Sandre 414219708Semaste return(sp.tv_sec); 4151590Srgrimes} 4161590Srgrimes 417123250Sdesstatic void 418198620Sjhbfill_pcpu(struct pcpu ***pcpup, int* maxcpup) 419198620Sjhb{ 420198620Sjhb struct pcpu **pcpu; 421198620Sjhb 422215569Skevlo int maxcpu, i; 423198620Sjhb 424198620Sjhb *pcpup = NULL; 425198620Sjhb 426198620Sjhb if (kd == NULL) 427198620Sjhb return; 428198620Sjhb 429198620Sjhb maxcpu = kvm_getmaxcpu(kd); 430198620Sjhb if (maxcpu < 0) 431198620Sjhb errx(1, "kvm_getmaxcpu: %s", kvm_geterr(kd)); 432198620Sjhb 433198620Sjhb pcpu = calloc(maxcpu, sizeof(struct pcpu *)); 434198620Sjhb if (pcpu == NULL) 435198620Sjhb err(1, "calloc"); 436198620Sjhb 437198620Sjhb for (i = 0; i < maxcpu; i++) { 438198620Sjhb pcpu[i] = kvm_getpcpu(kd, i); 439198620Sjhb if (pcpu[i] == (struct pcpu *)-1) 440198620Sjhb errx(1, "kvm_getpcpu: %s", kvm_geterr(kd)); 441198620Sjhb } 442198620Sjhb 443198620Sjhb *maxcpup = maxcpu; 444198620Sjhb *pcpup = pcpu; 445198620Sjhb} 446198620Sjhb 447198620Sjhbstatic void 448198620Sjhbfree_pcpu(struct pcpu **pcpu, int maxcpu) 449198620Sjhb{ 450198620Sjhb int i; 451198620Sjhb 452198620Sjhb for (i = 0; i < maxcpu; i++) 453198620Sjhb free(pcpu[i]); 454198620Sjhb free(pcpu); 455198620Sjhb} 456198620Sjhb 457198620Sjhbstatic void 458123250Sdesfill_vmmeter(struct vmmeter *vmmp) 459123250Sdes{ 460198620Sjhb struct pcpu **pcpu; 461198620Sjhb int maxcpu, i; 462198620Sjhb 463123250Sdes if (kd != NULL) { 464123250Sdes kread(X_SUM, vmmp, sizeof(*vmmp)); 465198620Sjhb fill_pcpu(&pcpu, &maxcpu); 466198620Sjhb for (i = 0; i < maxcpu; i++) { 467198620Sjhb if (pcpu[i] == NULL) 468198620Sjhb continue; 469198620Sjhb#define ADD_FROM_PCPU(i, name) \ 470198620Sjhb vmmp->name += pcpu[i]->pc_cnt.name 471198620Sjhb ADD_FROM_PCPU(i, v_swtch); 472198620Sjhb ADD_FROM_PCPU(i, v_trap); 473198620Sjhb ADD_FROM_PCPU(i, v_syscall); 474198620Sjhb ADD_FROM_PCPU(i, v_intr); 475198620Sjhb ADD_FROM_PCPU(i, v_soft); 476198620Sjhb ADD_FROM_PCPU(i, v_vm_faults); 477246034Szont ADD_FROM_PCPU(i, v_io_faults); 478198620Sjhb ADD_FROM_PCPU(i, v_cow_faults); 479198620Sjhb ADD_FROM_PCPU(i, v_cow_optim); 480198620Sjhb ADD_FROM_PCPU(i, v_zfod); 481198620Sjhb ADD_FROM_PCPU(i, v_ozfod); 482198620Sjhb ADD_FROM_PCPU(i, v_swapin); 483198620Sjhb ADD_FROM_PCPU(i, v_swapout); 484198620Sjhb ADD_FROM_PCPU(i, v_swappgsin); 485198620Sjhb ADD_FROM_PCPU(i, v_swappgsout); 486198620Sjhb ADD_FROM_PCPU(i, v_vnodein); 487198620Sjhb ADD_FROM_PCPU(i, v_vnodeout); 488198620Sjhb ADD_FROM_PCPU(i, v_vnodepgsin); 489198620Sjhb ADD_FROM_PCPU(i, v_vnodepgsout); 490198620Sjhb ADD_FROM_PCPU(i, v_intrans); 491198620Sjhb ADD_FROM_PCPU(i, v_tfree); 492198620Sjhb ADD_FROM_PCPU(i, v_forks); 493198620Sjhb ADD_FROM_PCPU(i, v_vforks); 494198620Sjhb ADD_FROM_PCPU(i, v_rforks); 495198620Sjhb ADD_FROM_PCPU(i, v_kthreads); 496198620Sjhb ADD_FROM_PCPU(i, v_forkpages); 497198620Sjhb ADD_FROM_PCPU(i, v_vforkpages); 498198620Sjhb ADD_FROM_PCPU(i, v_rforkpages); 499198620Sjhb ADD_FROM_PCPU(i, v_kthreadpages); 500198620Sjhb#undef ADD_FROM_PCPU 501198620Sjhb } 502198620Sjhb free_pcpu(pcpu, maxcpu); 503123250Sdes } else { 504123250Sdes size_t size = sizeof(unsigned int); 505123250Sdes#define GET_VM_STATS(cat, name) \ 506123250Sdes mysysctl("vm.stats." #cat "." #name, &vmmp->name, &size, NULL, 0) 507123250Sdes /* sys */ 508123250Sdes GET_VM_STATS(sys, v_swtch); 509123250Sdes GET_VM_STATS(sys, v_trap); 510123250Sdes GET_VM_STATS(sys, v_syscall); 511123250Sdes GET_VM_STATS(sys, v_intr); 512123250Sdes GET_VM_STATS(sys, v_soft); 5131590Srgrimes 514123250Sdes /* vm */ 515123414Sdes GET_VM_STATS(vm, v_vm_faults); 516246034Szont GET_VM_STATS(vm, v_io_faults); 517123414Sdes GET_VM_STATS(vm, v_cow_faults); 518123414Sdes GET_VM_STATS(vm, v_cow_optim); 519123414Sdes GET_VM_STATS(vm, v_zfod); 520123414Sdes GET_VM_STATS(vm, v_ozfod); 521123414Sdes GET_VM_STATS(vm, v_swapin); 522123414Sdes GET_VM_STATS(vm, v_swapout); 523123414Sdes GET_VM_STATS(vm, v_swappgsin); 524123414Sdes GET_VM_STATS(vm, v_swappgsout); 525123414Sdes GET_VM_STATS(vm, v_vnodein); 526123414Sdes GET_VM_STATS(vm, v_vnodeout); 527123414Sdes GET_VM_STATS(vm, v_vnodepgsin); 528123414Sdes GET_VM_STATS(vm, v_vnodepgsout); 529123414Sdes GET_VM_STATS(vm, v_intrans); 530123414Sdes GET_VM_STATS(vm, v_reactivated); 531123414Sdes GET_VM_STATS(vm, v_pdwakeups); 532123414Sdes GET_VM_STATS(vm, v_pdpages); 533171633Salc GET_VM_STATS(vm, v_tcached); 534123414Sdes GET_VM_STATS(vm, v_dfree); 535123414Sdes GET_VM_STATS(vm, v_pfree); 536123414Sdes GET_VM_STATS(vm, v_tfree); 537123414Sdes GET_VM_STATS(vm, v_page_size); 538123414Sdes GET_VM_STATS(vm, v_page_count); 539123414Sdes GET_VM_STATS(vm, v_free_reserved); 540123414Sdes GET_VM_STATS(vm, v_free_target); 541123414Sdes GET_VM_STATS(vm, v_free_min); 542123414Sdes GET_VM_STATS(vm, v_free_count); 543123414Sdes GET_VM_STATS(vm, v_wire_count); 544123414Sdes GET_VM_STATS(vm, v_active_count); 545123414Sdes GET_VM_STATS(vm, v_inactive_target); 546123414Sdes GET_VM_STATS(vm, v_inactive_count); 547123414Sdes GET_VM_STATS(vm, v_cache_count); 548123414Sdes GET_VM_STATS(vm, v_cache_min); 549123414Sdes GET_VM_STATS(vm, v_cache_max); 550123414Sdes GET_VM_STATS(vm, v_pageout_free_min); 551123414Sdes GET_VM_STATS(vm, v_interrupt_free_min); 552123414Sdes /*GET_VM_STATS(vm, v_free_severe);*/ 553123250Sdes GET_VM_STATS(vm, v_forks); 554123250Sdes GET_VM_STATS(vm, v_vforks); 555123250Sdes GET_VM_STATS(vm, v_rforks); 556123250Sdes GET_VM_STATS(vm, v_kthreads); 557123250Sdes GET_VM_STATS(vm, v_forkpages); 558123250Sdes GET_VM_STATS(vm, v_vforkpages); 559123250Sdes GET_VM_STATS(vm, v_rforkpages); 560123250Sdes GET_VM_STATS(vm, v_kthreadpages); 561123250Sdes#undef GET_VM_STATS 562123250Sdes } 563123250Sdes} 564123250Sdes 565123250Sdesstatic void 566123250Sdesfill_vmtotal(struct vmtotal *vmtp) 5671590Srgrimes{ 568123250Sdes if (kd != NULL) { 569123250Sdes /* XXX fill vmtp */ 570123250Sdes errx(1, "not implemented"); 571123250Sdes } else { 572123250Sdes size_t size = sizeof(*vmtp); 573123250Sdes mysysctl("vm.vmtotal", vmtp, &size, NULL, 0); 574123250Sdes if (size != sizeof(*vmtp)) 575123250Sdes errx(1, "vm.total size mismatch"); 576123250Sdes } 577123250Sdes} 578123250Sdes 579174573Speter/* Determine how many cpu columns, and what index they are in kern.cp_times */ 580174573Speterstatic int 581174573Spetergetcpuinfo(u_long *maskp, int *maxidp) 582174573Speter{ 583174573Speter int maxcpu; 584174573Speter int maxid; 585174573Speter int ncpus; 586174573Speter int i, j; 587174573Speter int empty; 588174573Speter size_t size; 589174573Speter long *times; 590174573Speter u_long mask; 591174573Speter 592174573Speter if (kd != NULL) 593174573Speter errx(1, "not implemented"); 594174573Speter mask = 0; 595174573Speter ncpus = 0; 596174573Speter size = sizeof(maxcpu); 597174573Speter mysysctl("kern.smp.maxcpus", &maxcpu, &size, NULL, 0); 598174573Speter if (size != sizeof(maxcpu)) 599174573Speter errx(1, "sysctl kern.smp.maxcpus"); 600174573Speter size = sizeof(long) * maxcpu * CPUSTATES; 601174573Speter times = malloc(size); 602174573Speter if (times == NULL) 603174573Speter err(1, "malloc %zd bytes", size); 604174573Speter mysysctl("kern.cp_times", times, &size, NULL, 0); 605174573Speter maxid = (size / CPUSTATES / sizeof(long)) - 1; 606174573Speter for (i = 0; i <= maxid; i++) { 607174573Speter empty = 1; 608174573Speter for (j = 0; empty && j < CPUSTATES; j++) { 609174573Speter if (times[i * CPUSTATES + j] != 0) 610174573Speter empty = 0; 611174573Speter } 612174573Speter if (!empty) { 613174573Speter mask |= (1ul << i); 614174573Speter ncpus++; 615174573Speter } 616174573Speter } 617174573Speter if (maskp) 618174573Speter *maskp = mask; 619174573Speter if (maxidp) 620174573Speter *maxidp = maxid; 621174573Speter return (ncpus); 622174573Speter} 623174573Speter 624174573Speter 625174573Speterstatic void 626174573Speterprthuman(u_int64_t val, int size) 627174573Speter{ 628174573Speter char buf[10]; 629174573Speter int flags; 630174573Speter 631174573Speter if (size < 5 || size > 9) 632174573Speter errx(1, "doofus"); 633174573Speter flags = HN_B | HN_NOSPACE | HN_DECIMAL; 634174573Speter humanize_number(buf, size, val, "", HN_AUTOSCALE, flags); 635174573Speter printf("%*s", size, buf); 636174573Speter} 637174573Speter 638123250Sdesstatic int hz, hdrcnt; 639123250Sdes 640174573Speterstatic long *cur_cp_times; 641174573Speterstatic long *last_cp_times; 642174573Speterstatic size_t size_cp_times; 643174573Speter 644123250Sdesstatic void 645123407Sdesdovmstat(unsigned int interval, int reps) 646123250Sdes{ 6471590Srgrimes struct vmtotal total; 6481590Srgrimes time_t uptime, halfuptime; 64939230Sgibbs struct devinfo *tmp_dinfo; 65080551Stmm size_t size; 651174573Speter int ncpus, maxid; 652174573Speter u_long cpumask; 653208389Ssbruno int rate_adj; 6541590Srgrimes 6551590Srgrimes uptime = getuptime(); 6561590Srgrimes halfuptime = uptime / 2; 657208389Ssbruno rate_adj = 1; 658272866Shrs ncpus = 1; 659272866Shrs maxid = 0; 660184645Skeramida 661184645Skeramida /* 662184645Skeramida * If the user stops the program (control-Z) and then resumes it, 663184645Skeramida * print out the header again. 664184645Skeramida */ 6651590Srgrimes (void)signal(SIGCONT, needhdr); 6661590Srgrimes 667184645Skeramida /* 668184645Skeramida * If our standard output is a tty, then install a SIGWINCH handler 669184645Skeramida * and set wresized so that our first iteration through the main 670184646Skeramida * vmstat loop will peek at the terminal's current rows to find out 671184645Skeramida * how many lines can fit in a screenful of output. 672184645Skeramida */ 673184645Skeramida if (isatty(fileno(stdout)) != 0) { 674184645Skeramida wresized = 1; 675184645Skeramida (void)signal(SIGWINCH, needresize); 676184645Skeramida } else { 677184645Skeramida wresized = 0; 678184645Skeramida winlines = VMSTAT_DEFAULT_LINES; 679184645Skeramida } 680184645Skeramida 681123250Sdes if (kd != NULL) { 682123250Sdes if (namelist[X_STATHZ].n_type != 0 && 683123250Sdes namelist[X_STATHZ].n_value != 0) 684123250Sdes kread(X_STATHZ, &hz, sizeof(hz)); 685123250Sdes if (!hz) 686123250Sdes kread(X_HZ, &hz, sizeof(hz)); 687123250Sdes } else { 688123250Sdes struct clockinfo clockrate; 6891590Srgrimes 690123250Sdes size = sizeof(clockrate); 691123250Sdes mysysctl("kern.clockrate", &clockrate, &size, NULL, 0); 692123250Sdes if (size != sizeof(clockrate)) 693123250Sdes errx(1, "clockrate size mismatch"); 694123250Sdes hz = clockrate.hz; 695123250Sdes } 696123250Sdes 697174573Speter if (Pflag) { 698174573Speter ncpus = getcpuinfo(&cpumask, &maxid); 699174573Speter size_cp_times = sizeof(long) * (maxid + 1) * CPUSTATES; 700188888Sdelphij cur_cp_times = calloc(1, size_cp_times); 701188888Sdelphij last_cp_times = calloc(1, size_cp_times); 702174573Speter } 7031590Srgrimes for (hdrcnt = 1;;) { 7041590Srgrimes if (!--hdrcnt) 705272866Shrs printhdr(maxid, cpumask); 706123250Sdes if (kd != NULL) { 707181881Sjhb if (kvm_getcptime(kd, cur.cp_time) < 0) 708181881Sjhb errx(1, "kvm_getcptime: %s", kvm_geterr(kd)); 709123250Sdes } else { 710123250Sdes size = sizeof(cur.cp_time); 711123250Sdes mysysctl("kern.cp_time", &cur.cp_time, &size, NULL, 0); 712123250Sdes if (size != sizeof(cur.cp_time)) 713123250Sdes errx(1, "cp_time size mismatch"); 714123250Sdes } 715174573Speter if (Pflag) { 716174573Speter size = size_cp_times; 717174573Speter mysysctl("kern.cp_times", cur_cp_times, &size, NULL, 0); 718174573Speter if (size != size_cp_times) 719174573Speter errx(1, "cp_times mismatch"); 720174573Speter } 72139230Sgibbs 72239230Sgibbs tmp_dinfo = last.dinfo; 72339230Sgibbs last.dinfo = cur.dinfo; 72439230Sgibbs cur.dinfo = tmp_dinfo; 725112288Sphk last.snap_time = cur.snap_time; 72639230Sgibbs 72739230Sgibbs /* 72839230Sgibbs * Here what we want to do is refresh our device stats. 72939230Sgibbs * getdevs() returns 1 when the device list has changed. 73039230Sgibbs * If the device list has changed, we want to go through 73139230Sgibbs * the selection process again, in case a device that we 73239230Sgibbs * were previously displaying has gone away. 73339230Sgibbs */ 734112284Sphk switch (devstat_getdevs(NULL, &cur)) { 73539230Sgibbs case -1: 73639230Sgibbs errx(1, "%s", devstat_errbuf); 73739230Sgibbs break; 73839230Sgibbs case 1: { 73939230Sgibbs int retval; 74039230Sgibbs 74139230Sgibbs num_devices = cur.dinfo->numdevs; 74239230Sgibbs generation = cur.dinfo->generation; 74339230Sgibbs 744112284Sphk retval = devstat_selectdevs(&dev_select, &num_selected, 74539230Sgibbs &num_selections, &select_generation, 74639230Sgibbs generation, cur.dinfo->devices, 74739230Sgibbs num_devices, matches, num_matches, 74839230Sgibbs specified_devices, 74939230Sgibbs num_devices_specified, select_mode, 75039230Sgibbs maxshowdevs, 0); 75139230Sgibbs switch (retval) { 75239230Sgibbs case -1: 75339230Sgibbs errx(1, "%s", devstat_errbuf); 75439230Sgibbs break; 75539230Sgibbs case 1: 756272866Shrs printhdr(maxid, cpumask); 75739230Sgibbs break; 75839230Sgibbs default: 75939230Sgibbs break; 76039230Sgibbs } 76139230Sgibbs } 76239230Sgibbs default: 76339230Sgibbs break; 76439230Sgibbs } 76539230Sgibbs 766123250Sdes fill_vmmeter(&sum); 767123250Sdes fill_vmtotal(&total); 768164718Sru (void)printf("%2d %1d %1d", 7691590Srgrimes total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); 770164718Sru#define vmstat_pgtok(a) ((a) * (sum.v_page_size >> 10)) 771208389Ssbruno#define rate(x) (((x) * rate_adj + halfuptime) / uptime) /* round */ 772174573Speter if (hflag) { 773174573Speter printf(" "); 774174573Speter prthuman(total.t_avm * (u_int64_t)sum.v_page_size, 7); 775174573Speter printf(" "); 776174573Speter prthuman(total.t_free * (u_int64_t)sum.v_page_size, 6); 777174573Speter printf(" "); 778174573Speter } else { 779174573Speter printf(" %7d ", vmstat_pgtok(total.t_avm)); 780174573Speter printf(" %6d ", vmstat_pgtok(total.t_free)); 781174573Speter } 782159200Sobrien (void)printf("%5lu ", 783123407Sdes (unsigned long)rate(sum.v_vm_faults - osum.v_vm_faults)); 7841590Srgrimes (void)printf("%3lu ", 785123407Sdes (unsigned long)rate(sum.v_reactivated - osum.v_reactivated)); 78637453Sbde (void)printf("%3lu ", 787123407Sdes (unsigned long)rate(sum.v_swapin + sum.v_vnodein - 7883659Sdg (osum.v_swapin + osum.v_vnodein))); 78937453Sbde (void)printf("%3lu ", 790123407Sdes (unsigned long)rate(sum.v_swapout + sum.v_vnodeout - 7913693Sdg (osum.v_swapout + osum.v_vnodeout))); 792159200Sobrien (void)printf("%5lu ", 793123407Sdes (unsigned long)rate(sum.v_tfree - osum.v_tfree)); 79437453Sbde (void)printf("%3lu ", 795123407Sdes (unsigned long)rate(sum.v_pdpages - osum.v_pdpages)); 79639230Sgibbs devstats(); 797174573Speter (void)printf("%4lu %4lu %4lu", 798123407Sdes (unsigned long)rate(sum.v_intr - osum.v_intr), 799123407Sdes (unsigned long)rate(sum.v_syscall - osum.v_syscall), 800123407Sdes (unsigned long)rate(sum.v_swtch - osum.v_swtch)); 801174573Speter if (Pflag) 802174573Speter pcpustats(ncpus, cpumask, maxid); 803174573Speter else 804174573Speter cpustats(); 8051590Srgrimes (void)printf("\n"); 8061590Srgrimes (void)fflush(stdout); 8071590Srgrimes if (reps >= 0 && --reps <= 0) 8081590Srgrimes break; 8091590Srgrimes osum = sum; 8101590Srgrimes uptime = interval; 811208389Ssbruno rate_adj = 1000; 8121590Srgrimes /* 8131590Srgrimes * We round upward to avoid losing low-frequency events 814208389Ssbruno * (i.e., >= 1 per interval but < 1 per millisecond). 8151590Srgrimes */ 8163659Sdg if (interval != 1) 8173659Sdg halfuptime = (uptime + 1) / 2; 8183659Sdg else 8193659Sdg halfuptime = 0; 820208389Ssbruno (void)usleep(interval * 1000); 8211590Srgrimes } 8221590Srgrimes} 8231590Srgrimes 824123250Sdesstatic void 825272866Shrsprinthdr(int maxid, u_long cpumask) 8261590Srgrimes{ 82743822Sken int i, num_shown; 8281590Srgrimes 82943822Sken num_shown = (num_selected < maxshowdevs) ? num_selected : maxshowdevs; 83078672Sschweikh (void)printf(" procs memory page%*s", 19, ""); 83143822Sken if (num_shown > 1) 83243822Sken (void)printf(" disks %*s", num_shown * 4 - 7, ""); 83343822Sken else if (num_shown == 1) 83443822Sken (void)printf("disk"); 835174573Speter (void)printf(" faults "); 836174573Speter if (Pflag) { 837272866Shrs for (i = 0; i <= maxid; i++) { 838175465Speter if (cpumask & (1ul << i)) 839174573Speter printf("cpu%-2d ", i); 840174573Speter } 841174573Speter printf("\n"); 842174573Speter } else 843174573Speter printf("cpu\n"); 844159200Sobrien (void)printf(" r b w avm fre flt re pi po fr sr "); 84539230Sgibbs for (i = 0; i < num_devices; i++) 84639230Sgibbs if ((dev_select[i].selected) 84739230Sgibbs && (dev_select[i].selected <= maxshowdevs)) 84839230Sgibbs (void)printf("%c%c%d ", dev_select[i].device_name[0], 84939230Sgibbs dev_select[i].device_name[1], 85039230Sgibbs dev_select[i].unit_number); 851174573Speter (void)printf(" in sy cs"); 852174573Speter if (Pflag) { 853272866Shrs for (i = 0; i <= maxid; i++) { 854272866Shrs if (cpumask & (1ul << i)) 855272866Shrs printf(" us sy id"); 856272866Shrs } 857174573Speter printf("\n"); 858174573Speter } else 859174573Speter printf(" us sy id\n"); 860184645Skeramida if (wresized != 0) 861184645Skeramida doresize(); 862184645Skeramida hdrcnt = winlines; 8631590Srgrimes} 8641590Srgrimes 8651590Srgrimes/* 8661590Srgrimes * Force a header to be prepended to the next output. 8671590Srgrimes */ 868123250Sdesstatic void 869123250Sdesneedhdr(int dummy __unused) 8701590Srgrimes{ 8711590Srgrimes 8721590Srgrimes hdrcnt = 1; 8731590Srgrimes} 8741590Srgrimes 875184645Skeramida/* 876184645Skeramida * When the terminal is resized, force an update of the maximum number of rows 877184645Skeramida * printed between each header repetition. Then force a new header to be 878184645Skeramida * prepended to the next output. 879184645Skeramida */ 880184645Skeramidavoid 881184645Skeramidaneedresize(int signo) 882184645Skeramida{ 883184645Skeramida 884184645Skeramida wresized = 1; 885184645Skeramida hdrcnt = 1; 886184645Skeramida} 887184645Skeramida 888184645Skeramida/* 889184645Skeramida * Update the global `winlines' count of terminal rows. 890184645Skeramida */ 891184645Skeramidavoid 892184645Skeramidadoresize(void) 893184645Skeramida{ 894184645Skeramida int status; 895184645Skeramida struct winsize w; 896184645Skeramida 897184645Skeramida for (;;) { 898184645Skeramida status = ioctl(fileno(stdout), TIOCGWINSZ, &w); 899184645Skeramida if (status == -1 && errno == EINTR) 900184645Skeramida continue; 901184645Skeramida else if (status == -1) 902184645Skeramida err(1, "ioctl"); 903184645Skeramida if (w.ws_row > 3) 904184645Skeramida winlines = w.ws_row - 3; 905184645Skeramida else 906184645Skeramida winlines = VMSTAT_DEFAULT_LINES; 907184645Skeramida break; 908184645Skeramida } 909184645Skeramida 910184645Skeramida /* 911184645Skeramida * Inhibit doresize() calls until we are rescheduled by SIGWINCH. 912184645Skeramida */ 913184645Skeramida wresized = 0; 914184645Skeramida} 915184645Skeramida 91630180Sdima#ifdef notyet 917123250Sdesstatic void 918123250Sdesdotimes(void) 9191590Srgrimes{ 920123407Sdes unsigned int pgintime, rectime; 9211590Srgrimes 9221590Srgrimes kread(X_REC, &rectime, sizeof(rectime)); 9231590Srgrimes kread(X_PGIN, &pgintime, sizeof(pgintime)); 9241590Srgrimes kread(X_SUM, &sum, sizeof(sum)); 9251590Srgrimes (void)printf("%u reclaims, %u total time (usec)\n", 9261590Srgrimes sum.v_pgrec, rectime); 9271590Srgrimes (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 9281590Srgrimes (void)printf("\n"); 9291590Srgrimes (void)printf("%u page ins, %u total time (msec)\n", 9301590Srgrimes sum.v_pgin, pgintime / 10); 9311590Srgrimes (void)printf("average: %8.1f msec / page in\n", 9321590Srgrimes pgintime / (sum.v_pgin * 10.0)); 9331590Srgrimes} 9341590Srgrimes#endif 9351590Srgrimes 936123250Sdesstatic long 937123250Sdespct(long top, long bot) 9381590Srgrimes{ 9391590Srgrimes long ans; 9401590Srgrimes 9411590Srgrimes if (bot == 0) 9421590Srgrimes return(0); 9431590Srgrimes ans = (quad_t)top * 100 / bot; 9441590Srgrimes return (ans); 9451590Srgrimes} 9461590Srgrimes 9471590Srgrimes#define PCT(top, bot) pct((long)(top), (long)(bot)) 9481590Srgrimes 949123250Sdesstatic void 950123250Sdesdosum(void) 9511590Srgrimes{ 95287690Smarkm struct nchstats lnchstats; 9531590Srgrimes long nchtotal; 9541590Srgrimes 955123250Sdes fill_vmmeter(&sum); 9561590Srgrimes (void)printf("%9u cpu context switches\n", sum.v_swtch); 9571590Srgrimes (void)printf("%9u device interrupts\n", sum.v_intr); 9581590Srgrimes (void)printf("%9u software interrupts\n", sum.v_soft); 9591590Srgrimes (void)printf("%9u traps\n", sum.v_trap); 9601590Srgrimes (void)printf("%9u system calls\n", sum.v_syscall); 96171429Sume (void)printf("%9u kernel threads created\n", sum.v_kthreads); 96271429Sume (void)printf("%9u fork() calls\n", sum.v_forks); 96371429Sume (void)printf("%9u vfork() calls\n", sum.v_vforks); 96471429Sume (void)printf("%9u rfork() calls\n", sum.v_rforks); 9653659Sdg (void)printf("%9u swap pager pageins\n", sum.v_swapin); 9663693Sdg (void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin); 9673659Sdg (void)printf("%9u swap pager pageouts\n", sum.v_swapout); 9683659Sdg (void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout); 9693659Sdg (void)printf("%9u vnode pager pageins\n", sum.v_vnodein); 9703693Sdg (void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin); 9713659Sdg (void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout); 9723659Sdg (void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout); 9733693Sdg (void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups); 9743693Sdg (void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages); 9751590Srgrimes (void)printf("%9u pages reactivated\n", sum.v_reactivated); 9767351Sdg (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 97734214Sdyson (void)printf("%9u copy-on-write optimized faults\n", sum.v_cow_optim); 9787351Sdg (void)printf("%9u zero fill pages zeroed\n", sum.v_zfod); 97934214Sdyson (void)printf("%9u zero fill pages prezeroed\n", sum.v_ozfod); 9801590Srgrimes (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 9811590Srgrimes (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 982246034Szont (void)printf("%9u page faults requiring I/O\n", sum.v_io_faults); 98371429Sume (void)printf("%9u pages affected by kernel thread creation\n", sum.v_kthreadpages); 98471429Sume (void)printf("%9u pages affected by fork()\n", sum.v_forkpages); 98571429Sume (void)printf("%9u pages affected by vfork()\n", sum.v_vforkpages); 98671429Sume (void)printf("%9u pages affected by rfork()\n", sum.v_rforkpages); 987171633Salc (void)printf("%9u pages cached\n", sum.v_tcached); 9883693Sdg (void)printf("%9u pages freed\n", sum.v_tfree); 9891590Srgrimes (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 9901590Srgrimes (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 9911590Srgrimes (void)printf("%9u pages active\n", sum.v_active_count); 9921590Srgrimes (void)printf("%9u pages inactive\n", sum.v_inactive_count); 9935463Sdg (void)printf("%9u pages in VM cache\n", sum.v_cache_count); 9943693Sdg (void)printf("%9u pages wired down\n", sum.v_wire_count); 9953693Sdg (void)printf("%9u pages free\n", sum.v_free_count); 9961590Srgrimes (void)printf("%9u bytes per page\n", sum.v_page_size); 997123250Sdes if (kd != NULL) { 998123250Sdes kread(X_NCHSTATS, &lnchstats, sizeof(lnchstats)); 999123250Sdes } else { 1000123250Sdes size_t size = sizeof(lnchstats); 1001123250Sdes mysysctl("vfs.cache.nchstats", &lnchstats, &size, NULL, 0); 1002123250Sdes if (size != sizeof(lnchstats)) 1003123250Sdes errx(1, "vfs.cache.nchstats size mismatch"); 1004123250Sdes } 100587690Smarkm nchtotal = lnchstats.ncs_goodhits + lnchstats.ncs_neghits + 100687690Smarkm lnchstats.ncs_badhits + lnchstats.ncs_falsehits + 100787690Smarkm lnchstats.ncs_miss + lnchstats.ncs_long; 10081590Srgrimes (void)printf("%9ld total name lookups\n", nchtotal); 10091590Srgrimes (void)printf( 101028693Scharnier "%9s cache hits (%ld%% pos + %ld%% neg) system %ld%% per-directory\n", 101187690Smarkm "", PCT(lnchstats.ncs_goodhits, nchtotal), 101287690Smarkm PCT(lnchstats.ncs_neghits, nchtotal), 101387690Smarkm PCT(lnchstats.ncs_pass2, nchtotal)); 101428693Scharnier (void)printf("%9s deletions %ld%%, falsehits %ld%%, toolong %ld%%\n", "", 101587690Smarkm PCT(lnchstats.ncs_badhits, nchtotal), 101687690Smarkm PCT(lnchstats.ncs_falsehits, nchtotal), 101787690Smarkm PCT(lnchstats.ncs_long, nchtotal)); 10181590Srgrimes} 10191590Srgrimes 1020123250Sdesstatic void 1021123250Sdesdoforkst(void) 10221590Srgrimes{ 1023123250Sdes fill_vmmeter(&sum); 1024128573Stjr (void)printf("%u forks, %u pages, average %.2f\n", 1025113460Stjr sum.v_forks, sum.v_forkpages, 1026113460Stjr sum.v_forks == 0 ? 0.0 : 1027113460Stjr (double)sum.v_forkpages / sum.v_forks); 1028128573Stjr (void)printf("%u vforks, %u pages, average %.2f\n", 1029113460Stjr sum.v_vforks, sum.v_vforkpages, 1030113460Stjr sum.v_vforks == 0 ? 0.0 : 1031113460Stjr (double)sum.v_vforkpages / sum.v_vforks); 1032128573Stjr (void)printf("%u rforks, %u pages, average %.2f\n", 1033113460Stjr sum.v_rforks, sum.v_rforkpages, 1034113460Stjr sum.v_rforks == 0 ? 0.0 : 1035113460Stjr (double)sum.v_rforkpages / sum.v_rforks); 10361590Srgrimes} 10371590Srgrimes 103839230Sgibbsstatic void 1039123250Sdesdevstats(void) 10401590Srgrimes{ 104187690Smarkm int dn, state; 104239230Sgibbs long double transfers_per_second; 104339230Sgibbs long double busy_seconds; 10441590Srgrimes long tmp; 1045123250Sdes 10461590Srgrimes for (state = 0; state < CPUSTATES; ++state) { 104739230Sgibbs tmp = cur.cp_time[state]; 104839230Sgibbs cur.cp_time[state] -= last.cp_time[state]; 104939230Sgibbs last.cp_time[state] = tmp; 10501590Srgrimes } 105139230Sgibbs 1052112288Sphk busy_seconds = cur.snap_time - last.snap_time; 105339230Sgibbs 105439230Sgibbs for (dn = 0; dn < num_devices; dn++) { 105539230Sgibbs int di; 105639230Sgibbs 105739230Sgibbs if ((dev_select[dn].selected == 0) 105839230Sgibbs || (dev_select[dn].selected > maxshowdevs)) 10591590Srgrimes continue; 106039230Sgibbs 106139230Sgibbs di = dev_select[dn].position; 106239230Sgibbs 106381537Sken if (devstat_compute_statistics(&cur.dinfo->devices[di], 106481537Sken &last.dinfo->devices[di], busy_seconds, 106581537Sken DSM_TRANSFERS_PER_SECOND, &transfers_per_second, 106681537Sken DSM_NONE) != 0) 106739230Sgibbs errx(1, "%s", devstat_errbuf); 106839230Sgibbs 106981537Sken (void)printf("%3.0Lf ", transfers_per_second); 10701590Srgrimes } 10711590Srgrimes} 10721590Srgrimes 1073123250Sdesstatic void 1074174573Speterpercent(double pct, int *over) 1075174573Speter{ 1076174573Speter char buf[10]; 1077174573Speter int l; 1078174573Speter 1079174573Speter l = snprintf(buf, sizeof(buf), "%.0f", pct); 1080174573Speter if (l == 1 && *over) { 1081174573Speter printf("%s", buf); 1082174573Speter (*over)--; 1083174573Speter } else 1084174573Speter printf("%2s", buf); 1085174573Speter if (l > 2) 1086174573Speter (*over)++; 1087174573Speter} 1088174573Speter 1089174573Speterstatic void 1090123250Sdescpustats(void) 10911590Srgrimes{ 1092174573Speter int state, over; 109387690Smarkm double lpct, total; 10941590Srgrimes 10951590Srgrimes total = 0; 10961590Srgrimes for (state = 0; state < CPUSTATES; ++state) 109739230Sgibbs total += cur.cp_time[state]; 10981590Srgrimes if (total) 109987690Smarkm lpct = 100.0 / total; 11001590Srgrimes else 110187690Smarkm lpct = 0.0; 1102174573Speter over = 0; 1103174573Speter printf(" "); 1104174573Speter percent((cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * lpct, &over); 1105174573Speter printf(" "); 1106174573Speter percent((cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * lpct, &over); 1107174573Speter printf(" "); 1108174573Speter percent(cur.cp_time[CP_IDLE] * lpct, &over); 11091590Srgrimes} 11101590Srgrimes 1111123250Sdesstatic void 1112174573Speterpcpustats(int ncpus, u_long cpumask, int maxid) 1113174573Speter{ 1114174573Speter int state, i; 1115174573Speter double lpct, total; 1116174573Speter long tmp; 1117174573Speter int over; 1118174573Speter 1119174573Speter /* devstats does this for cp_time */ 1120174573Speter for (i = 0; i <= maxid; i++) { 1121175465Speter if ((cpumask & (1ul << i)) == 0) 1122174573Speter continue; 1123174573Speter for (state = 0; state < CPUSTATES; ++state) { 1124174573Speter tmp = cur_cp_times[i * CPUSTATES + state]; 1125174573Speter cur_cp_times[i * CPUSTATES + state] -= last_cp_times[i * CPUSTATES + state]; 1126174573Speter last_cp_times[i * CPUSTATES + state] = tmp; 1127174573Speter } 1128174573Speter } 1129174573Speter 1130174573Speter over = 0; 1131174573Speter for (i = 0; i <= maxid; i++) { 1132175465Speter if ((cpumask & (1ul << i)) == 0) 1133174573Speter continue; 1134174573Speter total = 0; 1135174573Speter for (state = 0; state < CPUSTATES; ++state) 1136174573Speter total += cur_cp_times[i * CPUSTATES + state]; 1137174573Speter if (total) 1138174573Speter lpct = 100.0 / total; 1139174573Speter else 1140174573Speter lpct = 0.0; 1141174573Speter printf(" "); 1142174573Speter percent((cur_cp_times[i * CPUSTATES + CP_USER] + 1143174573Speter cur_cp_times[i * CPUSTATES + CP_NICE]) * lpct, &over); 1144174573Speter printf(" "); 1145174573Speter percent((cur_cp_times[i * CPUSTATES + CP_SYS] + 1146174573Speter cur_cp_times[i * CPUSTATES + CP_INTR]) * lpct, &over); 1147174573Speter printf(" "); 1148174573Speter percent(cur_cp_times[i * CPUSTATES + CP_IDLE] * lpct, &over); 1149174573Speter } 1150174573Speter} 1151174573Speter 1152174573Speterstatic void 1153123250Sdesdointr(void) 11541590Srgrimes{ 1155123407Sdes unsigned long *intrcnt, uptime; 1156123409Sdes uint64_t inttotal; 1157123409Sdes size_t clen, inamlen, intrcntlen, istrnamlen; 1158123409Sdes unsigned int i, nintr; 1159121626Sjmg char *intrname, *tintrname; 11601590Srgrimes 11611590Srgrimes uptime = getuptime(); 1162123250Sdes if (kd != NULL) { 1163224198Spluknet kread(X_SINTRCNT, &intrcntlen, sizeof(intrcntlen)); 1164224198Spluknet kread(X_SINTRNAMES, &inamlen, sizeof(inamlen)); 1165123409Sdes if ((intrcnt = malloc(intrcntlen)) == NULL || 1166123290Smarcel (intrname = malloc(inamlen)) == NULL) 1167123250Sdes err(1, "malloc()"); 1168123409Sdes kread(X_INTRCNT, intrcnt, intrcntlen); 1169123290Smarcel kread(X_INTRNAMES, intrname, inamlen); 1170123250Sdes } else { 1171123438Sdes for (intrcnt = NULL, intrcntlen = 1024; ; intrcntlen *= 2) { 1172123438Sdes if ((intrcnt = reallocf(intrcnt, intrcntlen)) == NULL) 1173123438Sdes err(1, "reallocf()"); 1174123438Sdes if (mysysctl("hw.intrcnt", 1175123438Sdes intrcnt, &intrcntlen, NULL, 0) == 0) 1176123438Sdes break; 1177123438Sdes } 1178123250Sdes for (intrname = NULL, inamlen = 1024; ; inamlen *= 2) { 1179123250Sdes if ((intrname = reallocf(intrname, inamlen)) == NULL) 1180123250Sdes err(1, "reallocf()"); 1181123250Sdes if (mysysctl("hw.intrnames", 1182123250Sdes intrname, &inamlen, NULL, 0) == 0) 1183123250Sdes break; 1184123250Sdes } 1185123250Sdes } 1186123409Sdes nintr = intrcntlen / sizeof(unsigned long); 1187121626Sjmg tintrname = intrname; 1188122365Sjmg istrnamlen = strlen("interrupt"); 1189121626Sjmg for (i = 0; i < nintr; i++) { 1190121626Sjmg clen = strlen(tintrname); 1191121626Sjmg if (clen > istrnamlen) 1192121626Sjmg istrnamlen = clen; 1193121626Sjmg tintrname += clen + 1; 1194121626Sjmg } 1195228654Sdim (void)printf("%-*s %20s %10s\n", (int)istrnamlen, "interrupt", "total", 1196121626Sjmg "rate"); 11971590Srgrimes inttotal = 0; 1198123290Smarcel for (i = 0; i < nintr; i++) { 1199123409Sdes if (intrname[0] != '\0' && (*intrcnt != 0 || aflag)) 1200228654Sdim (void)printf("%-*s %20lu %10lu\n", (int)istrnamlen, 1201228654Sdim intrname, *intrcnt, *intrcnt / uptime); 12021590Srgrimes intrname += strlen(intrname) + 1; 12031590Srgrimes inttotal += *intrcnt++; 12041590Srgrimes } 1205228654Sdim (void)printf("%-*s %20" PRIu64 " %10" PRIu64 "\n", (int)istrnamlen, 1206228654Sdim "Total", inttotal, inttotal / uptime); 12071590Srgrimes} 12081590Srgrimes 1209148413Srwatsonstatic void 1210148413Srwatsondomemstat_malloc(void) 1211148413Srwatson{ 1212148413Srwatson struct memory_type_list *mtlp; 1213148413Srwatson struct memory_type *mtp; 1214148790Srwatson int error, first, i; 1215148413Srwatson 1216148413Srwatson mtlp = memstat_mtl_alloc(); 1217148413Srwatson if (mtlp == NULL) { 1218148413Srwatson warn("memstat_mtl_alloc"); 1219148413Srwatson return; 1220148413Srwatson } 1221148790Srwatson if (kd == NULL) { 1222148790Srwatson if (memstat_sysctl_malloc(mtlp, 0) < 0) { 1223148790Srwatson warnx("memstat_sysctl_malloc: %s", 1224148790Srwatson memstat_strerror(memstat_mtl_geterror(mtlp))); 1225148790Srwatson return; 1226148790Srwatson } 1227148790Srwatson } else { 1228148790Srwatson if (memstat_kvm_malloc(mtlp, kd) < 0) { 1229148790Srwatson error = memstat_mtl_geterror(mtlp); 1230148790Srwatson if (error == MEMSTAT_ERROR_KVM) 1231148790Srwatson warnx("memstat_kvm_malloc: %s", 1232148790Srwatson kvm_geterr(kd)); 1233148790Srwatson else 1234148790Srwatson warnx("memstat_kvm_malloc: %s", 1235148790Srwatson memstat_strerror(error)); 1236148790Srwatson } 1237148413Srwatson } 1238148413Srwatson printf("%13s %5s %6s %7s %8s Size(s)\n", "Type", "InUse", "MemUse", 1239148413Srwatson "HighUse", "Requests"); 1240148413Srwatson for (mtp = memstat_mtl_first(mtlp); mtp != NULL; 1241148413Srwatson mtp = memstat_mtl_next(mtp)) { 1242148413Srwatson if (memstat_get_numallocs(mtp) == 0 && 1243148413Srwatson memstat_get_count(mtp) == 0) 1244148413Srwatson continue; 1245228654Sdim printf("%13s %5" PRIu64 " %5" PRIu64 "K %7s %8" PRIu64 " ", 1246148413Srwatson memstat_get_name(mtp), memstat_get_count(mtp), 1247228654Sdim (memstat_get_bytes(mtp) + 1023) / 1024, "-", 1248148413Srwatson memstat_get_numallocs(mtp)); 1249148413Srwatson first = 1; 1250148413Srwatson for (i = 0; i < 32; i++) { 1251148413Srwatson if (memstat_get_sizemask(mtp) & (1 << i)) { 1252148413Srwatson if (!first) 1253148413Srwatson printf(","); 1254148413Srwatson printf("%d", 1 << (i + 4)); 1255148413Srwatson first = 0; 1256148413Srwatson } 1257148413Srwatson } 1258148413Srwatson printf("\n"); 1259148413Srwatson } 1260148413Srwatson memstat_mtl_free(mtlp); 1261148413Srwatson} 1262148413Srwatson 1263148413Srwatsonstatic void 1264148413Srwatsondomemstat_zone(void) 1265148413Srwatson{ 1266148413Srwatson struct memory_type_list *mtlp; 1267148413Srwatson struct memory_type *mtp; 1268148413Srwatson char name[MEMTYPE_MAXNAME + 1]; 1269148630Srwatson int error; 1270148413Srwatson 1271148413Srwatson mtlp = memstat_mtl_alloc(); 1272148413Srwatson if (mtlp == NULL) { 1273148413Srwatson warn("memstat_mtl_alloc"); 1274148413Srwatson return; 1275148413Srwatson } 1276148630Srwatson if (kd == NULL) { 1277148630Srwatson if (memstat_sysctl_uma(mtlp, 0) < 0) { 1278148630Srwatson warnx("memstat_sysctl_uma: %s", 1279148630Srwatson memstat_strerror(memstat_mtl_geterror(mtlp))); 1280148630Srwatson return; 1281148630Srwatson } 1282148630Srwatson } else { 1283148630Srwatson if (memstat_kvm_uma(mtlp, kd) < 0) { 1284148630Srwatson error = memstat_mtl_geterror(mtlp); 1285148630Srwatson if (error == MEMSTAT_ERROR_KVM) 1286148630Srwatson warnx("memstat_kvm_uma: %s", 1287148630Srwatson kvm_geterr(kd)); 1288148630Srwatson else 1289148630Srwatson warnx("memstat_kvm_uma: %s", 1290148630Srwatson memstat_strerror(error)); 1291148630Srwatson } 1292148413Srwatson } 1293209215Ssbruno printf("%-20s %6s %6s %8s %8s %8s %4s %4s\n\n", "ITEM", "SIZE", 1294209215Ssbruno "LIMIT", "USED", "FREE", "REQ", "FAIL", "SLEEP"); 1295148413Srwatson for (mtp = memstat_mtl_first(mtlp); mtp != NULL; 1296148413Srwatson mtp = memstat_mtl_next(mtp)) { 1297148413Srwatson strlcpy(name, memstat_get_name(mtp), MEMTYPE_MAXNAME); 1298148413Srwatson strcat(name, ":"); 1299228654Sdim printf("%-20s %6" PRIu64 ", %6" PRIu64 ",%8" PRIu64 ",%8" PRIu64 1300228654Sdim ",%8" PRIu64 ",%4" PRIu64 ",%4" PRIu64 "\n", name, 1301148413Srwatson memstat_get_size(mtp), memstat_get_countlimit(mtp), 1302148413Srwatson memstat_get_count(mtp), memstat_get_free(mtp), 1303209215Ssbruno memstat_get_numallocs(mtp), memstat_get_failures(mtp), 1304209215Ssbruno memstat_get_sleeps(mtp)); 1305148413Srwatson } 1306148413Srwatson memstat_mtl_free(mtlp); 1307148413Srwatson printf("\n"); 1308148413Srwatson} 1309148413Srwatson 1310288453Sjhbstatic void 1311288453Sjhbdisplay_object(struct kinfo_vmobject *kvo) 1312288453Sjhb{ 1313288453Sjhb const char *str; 1314288453Sjhb 1315288453Sjhb printf("%5jd ", (uintmax_t)kvo->kvo_resident); 1316288453Sjhb printf("%5jd ", (uintmax_t)kvo->kvo_active); 1317288453Sjhb printf("%5jd ", (uintmax_t)kvo->kvo_inactive); 1318288453Sjhb printf("%3d ", kvo->kvo_ref_count); 1319288453Sjhb printf("%3d ", kvo->kvo_shadow_count); 1320288453Sjhb switch (kvo->kvo_memattr) { 1321288453Sjhb#ifdef VM_MEMATTR_UNCACHEABLE 1322288453Sjhb case VM_MEMATTR_UNCACHEABLE: 1323288453Sjhb str = "UC"; 1324288453Sjhb break; 1325288453Sjhb#endif 1326288453Sjhb#ifdef VM_MEMATTR_WRITE_COMBINING 1327288453Sjhb case VM_MEMATTR_WRITE_COMBINING: 1328288453Sjhb str = "WC"; 1329288453Sjhb break; 1330288453Sjhb#endif 1331288453Sjhb#ifdef VM_MEMATTR_WRITE_THROUGH 1332288453Sjhb case VM_MEMATTR_WRITE_THROUGH: 1333288453Sjhb str = "WT"; 1334288453Sjhb break; 1335288453Sjhb#endif 1336288453Sjhb#ifdef VM_MEMATTR_WRITE_PROTECTED 1337288453Sjhb case VM_MEMATTR_WRITE_PROTECTED: 1338288453Sjhb str = "WP"; 1339288453Sjhb break; 1340288453Sjhb#endif 1341288453Sjhb#ifdef VM_MEMATTR_WRITE_BACK 1342288453Sjhb case VM_MEMATTR_WRITE_BACK: 1343288453Sjhb str = "WB"; 1344288453Sjhb break; 1345288453Sjhb#endif 1346288453Sjhb#ifdef VM_MEMATTR_WEAK_UNCACHEABLE 1347288453Sjhb case VM_MEMATTR_WEAK_UNCACHEABLE: 1348288453Sjhb str = "UC-"; 1349288453Sjhb break; 1350288453Sjhb#endif 1351288453Sjhb#ifdef VM_MEMATTR_WB_WA 1352288453Sjhb case VM_MEMATTR_WB_WA: 1353288453Sjhb str = "WB"; 1354288453Sjhb break; 1355288453Sjhb#endif 1356288453Sjhb#ifdef VM_MEMATTR_NOCACHE 1357288453Sjhb case VM_MEMATTR_NOCACHE: 1358288453Sjhb str = "NC"; 1359288453Sjhb break; 1360288453Sjhb#endif 1361288453Sjhb#ifdef VM_MEMATTR_DEVICE 1362288453Sjhb case VM_MEMATTR_DEVICE: 1363288453Sjhb str = "DEV"; 1364288453Sjhb break; 1365288453Sjhb#endif 1366288453Sjhb#ifdef VM_MEMATTR_CACHEABLE 1367288453Sjhb case VM_MEMATTR_CACHEABLE: 1368288453Sjhb str = "C"; 1369288453Sjhb break; 1370288453Sjhb#endif 1371288453Sjhb#ifdef VM_MEMATTR_PREFETCHABLE 1372288453Sjhb case VM_MEMATTR_PREFETCHABLE: 1373288453Sjhb str = "PRE"; 1374288453Sjhb break; 1375288453Sjhb#endif 1376288453Sjhb default: 1377288453Sjhb str = "??"; 1378288453Sjhb break; 1379288453Sjhb } 1380288453Sjhb printf("%-3s ", str); 1381288453Sjhb switch (kvo->kvo_type) { 1382288453Sjhb case KVME_TYPE_NONE: 1383288453Sjhb str = "--"; 1384288453Sjhb break; 1385288453Sjhb case KVME_TYPE_DEFAULT: 1386288453Sjhb str = "df"; 1387288453Sjhb break; 1388288453Sjhb case KVME_TYPE_VNODE: 1389288453Sjhb str = "vn"; 1390288453Sjhb break; 1391288453Sjhb case KVME_TYPE_SWAP: 1392288453Sjhb str = "sw"; 1393288453Sjhb break; 1394288453Sjhb case KVME_TYPE_DEVICE: 1395288453Sjhb str = "dv"; 1396288453Sjhb break; 1397288453Sjhb case KVME_TYPE_PHYS: 1398288453Sjhb str = "ph"; 1399288453Sjhb break; 1400288453Sjhb case KVME_TYPE_DEAD: 1401288453Sjhb str = "dd"; 1402288453Sjhb break; 1403288453Sjhb case KVME_TYPE_SG: 1404288453Sjhb str = "sg"; 1405288453Sjhb break; 1406288453Sjhb case KVME_TYPE_UNKNOWN: 1407288453Sjhb default: 1408288453Sjhb str = "??"; 1409288453Sjhb break; 1410288453Sjhb } 1411288453Sjhb printf("%-2s ", str); 1412288453Sjhb printf("%-s\n", kvo->kvo_path); 1413288453Sjhb} 1414288453Sjhb 1415288453Sjhbstatic void 1416288453Sjhbdoobjstat(void) 1417288453Sjhb{ 1418288453Sjhb struct kinfo_vmobject *kvo; 1419288453Sjhb int cnt, i; 1420288453Sjhb 1421288453Sjhb kvo = kinfo_getvmobject(&cnt); 1422288453Sjhb if (kvo == NULL) { 1423288453Sjhb warn("Failed to fetch VM object list"); 1424288453Sjhb return; 1425288453Sjhb } 1426288453Sjhb printf("%5s %5s %5s %3s %3s %3s %2s %s\n", "RES", "ACT", "INACT", 1427288453Sjhb "REF", "SHD", "CM", "TP", "PATH"); 1428288453Sjhb for (i = 0; i < cnt; i++) 1429288453Sjhb display_object(&kvo[i]); 1430288453Sjhb free(kvo); 1431288453Sjhb} 1432288453Sjhb 1433148413Srwatson/* 14341590Srgrimes * kread reads something from the kernel, given its nlist index. 14351590Srgrimes */ 1436123250Sdesstatic void 1437131300Sgreenkreado(int nlx, void *addr, size_t size, size_t offset) 14381590Srgrimes{ 1439123825Sdwmalone const char *sym; 14401590Srgrimes 144140690Sjdp if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { 14421590Srgrimes sym = namelist[nlx].n_name; 14431590Srgrimes if (*sym == '_') 14441590Srgrimes ++sym; 144528693Scharnier errx(1, "symbol %s not defined", sym); 14461590Srgrimes } 1447131300Sgreen if ((size_t)kvm_read(kd, namelist[nlx].n_value + offset, addr, 1448131300Sgreen size) != size) { 14491590Srgrimes sym = namelist[nlx].n_name; 14501590Srgrimes if (*sym == '_') 14511590Srgrimes ++sym; 145228693Scharnier errx(1, "%s: %s", sym, kvm_geterr(kd)); 14531590Srgrimes } 14541590Srgrimes} 14551590Srgrimes 1456123250Sdesstatic void 1457131300Sgreenkread(int nlx, void *addr, size_t size) 1458131300Sgreen{ 1459131300Sgreen kreado(nlx, addr, size, 0); 1460131300Sgreen} 1461131300Sgreen 1462131300Sgreenstatic char * 1463131300Sgreenkgetstr(const char *strp) 1464131300Sgreen{ 1465131300Sgreen int n = 0, size = 1; 1466131300Sgreen char *ret = NULL; 1467131300Sgreen 1468131300Sgreen do { 1469131300Sgreen if (size == n + 1) { 1470131300Sgreen ret = realloc(ret, size); 1471131300Sgreen if (ret == NULL) 1472131300Sgreen err(1, "%s: realloc", __func__); 1473131300Sgreen size *= 2; 1474131300Sgreen } 1475131300Sgreen if (kvm_read(kd, (u_long)strp + n, &ret[n], 1) != 1) 1476131300Sgreen errx(1, "%s: %s", __func__, kvm_geterr(kd)); 1477131300Sgreen } while (ret[n++] != '\0'); 1478131300Sgreen return (ret); 1479131300Sgreen} 1480131300Sgreen 1481131300Sgreenstatic void 1482123250Sdesusage(void) 14831590Srgrimes{ 148472887Salfred (void)fprintf(stderr, "%s%s", 1485288453Sjhb "usage: vmstat [-afHhimoPsz] [-M core [-N system]] [-c count] [-n devs]\n", 1486288407Sjhb " [-p type,if,pass] [-w wait] [disks] [wait [count]]\n"); 14871590Srgrimes exit(1); 14881590Srgrimes} 1489