vmstat.c revision 131300
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 131300 2004-06-30 01:34:26Z green $"); 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> 6012804Speter#include <sys/vmmeter.h> 6112811Sbde 6212811Sbde#include <vm/vm_param.h> 6312811Sbde 6428693Scharnier#include <ctype.h> 6587690Smarkm#include <devstat.h> 6628693Scharnier#include <err.h> 6728693Scharnier#include <errno.h> 6828693Scharnier#include <kvm.h> 6928693Scharnier#include <limits.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> 781590Srgrimes 7987690Smarkmstatic char da[] = "da"; 8087690Smarkm 8187690Smarkmstatic struct nlist namelist[] = { 821590Srgrimes#define X_CPTIME 0 831590Srgrimes { "_cp_time" }, 8439230Sgibbs#define X_SUM 1 851590Srgrimes { "_cnt" }, 8639230Sgibbs#define X_BOOTTIME 2 871590Srgrimes { "_boottime" }, 8839230Sgibbs#define X_HZ 3 891590Srgrimes { "_hz" }, 9039230Sgibbs#define X_STATHZ 4 911590Srgrimes { "_stathz" }, 9239230Sgibbs#define X_NCHSTATS 5 931590Srgrimes { "_nchstats" }, 9439230Sgibbs#define X_INTRNAMES 6 951590Srgrimes { "_intrnames" }, 9639230Sgibbs#define X_EINTRNAMES 7 971590Srgrimes { "_eintrnames" }, 9839230Sgibbs#define X_INTRCNT 8 991590Srgrimes { "_intrcnt" }, 10039230Sgibbs#define X_EINTRCNT 9 1011590Srgrimes { "_eintrcnt" }, 102131300Sgreen#define X_KMEMSTATS 10 103131300Sgreen { "_kmemstatistics" }, 104131300Sgreen#define X_KMEMZONES 11 105131300Sgreen { "_kmemzones" }, 10630180Sdima#ifdef notyet 107131300Sgreen#define X_DEFICIT XXX 1081590Srgrimes { "_deficit" }, 109131300Sgreen#define X_REC XXX 1101590Srgrimes { "_rectime" }, 111131300Sgreen#define X_PGIN XXX 1121590Srgrimes { "_pgintime" }, 113131300Sgreen#define X_XSTATS XXX 1141590Srgrimes { "_xstats" }, 115131300Sgreen#define X_END XXX 11692653Sjeff#else 117131300Sgreen#define X_END 12 1181590Srgrimes#endif 1191590Srgrimes { "" }, 1201590Srgrimes}; 1211590Srgrimes 122123250Sdesstatic struct statinfo cur, last; 123123250Sdesstatic int num_devices, maxshowdevs; 124123250Sdesstatic long generation; 125123250Sdesstatic struct device_selection *dev_select; 126123250Sdesstatic int num_selected; 127123250Sdesstatic struct devstat_match *matches; 128123250Sdesstatic int num_matches = 0; 129123250Sdesstatic int num_devices_specified, num_selections; 130123250Sdesstatic long select_generation; 131123250Sdesstatic char **specified_devices; 132123250Sdesstatic devstat_select_mode select_mode; 1331590Srgrimes 134123250Sdesstatic struct vmmeter sum, osum; 1351590Srgrimes 136123250Sdesstatic int winlines = 20; 137123250Sdesstatic int aflag; 138123250Sdesstatic int nflag; 1391590Srgrimes 140123250Sdesstatic kvm_t *kd; 1411590Srgrimes 1421590Srgrimes#define FORKSTAT 0x01 1431590Srgrimes#define INTRSTAT 0x02 1441590Srgrimes#define MEMSTAT 0x04 1451590Srgrimes#define SUMSTAT 0x08 1461590Srgrimes#define TIMESTAT 0x10 1471590Srgrimes#define VMSTAT 0x20 14843962Sdillon#define ZMEMSTAT 0x40 1491590Srgrimes 15092922Simpstatic void cpustats(void); 15192922Simpstatic void devstats(void); 152122300Sjmgstatic void doforkst(void); 15392922Simpstatic void domem(void); 15492922Simpstatic void dointr(void); 15592922Simpstatic void dosum(void); 156123401Sdwmalonestatic void dosysctl(const char *); 157123407Sdesstatic void dovmstat(unsigned int, int); 15892922Simpstatic void dozmem(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); 16392922Simpstatic void printhdr(void); 16492922Simpstatic void usage(void); 1651590Srgrimes 16692922Simpstatic long pct(long, long); 16792922Simpstatic long getuptime(void); 16887690Smarkm 169123250Sdesstatic char **getdrivedata(char **); 17087690Smarkm 17128693Scharnierint 172123250Sdesmain(int argc, char *argv[]) 1731590Srgrimes{ 17487690Smarkm int c, todo; 175123407Sdes unsigned int interval; 1761590Srgrimes int reps; 1771590Srgrimes char *memf, *nlistf; 17878474Sschweikh char errbuf[_POSIX2_LINE_MAX]; 1791590Srgrimes 1801590Srgrimes memf = nlistf = NULL; 1811590Srgrimes interval = reps = todo = 0; 18243822Sken maxshowdevs = 2; 183123250Sdes while ((c = getopt(argc, argv, "ac:fiM:mN:n:p:stw:z")) != -1) { 1841590Srgrimes switch (c) { 185123250Sdes case 'a': 186123250Sdes aflag++; 187123250Sdes break; 1881590Srgrimes case 'c': 1891590Srgrimes reps = atoi(optarg); 1901590Srgrimes break; 1911590Srgrimes case 'f': 192113460Stjr todo |= FORKSTAT; 1931590Srgrimes break; 1941590Srgrimes case 'i': 1951590Srgrimes todo |= INTRSTAT; 1961590Srgrimes break; 1971590Srgrimes case 'M': 1981590Srgrimes memf = optarg; 1991590Srgrimes break; 2001590Srgrimes case 'm': 2011590Srgrimes todo |= MEMSTAT; 2021590Srgrimes break; 2031590Srgrimes case 'N': 2041590Srgrimes nlistf = optarg; 2051590Srgrimes break; 20639230Sgibbs case 'n': 20739372Sdillon nflag = 1; 20839230Sgibbs maxshowdevs = atoi(optarg); 20939230Sgibbs if (maxshowdevs < 0) 21039230Sgibbs errx(1, "number of devices %d is < 0", 21139230Sgibbs maxshowdevs); 21239230Sgibbs break; 21339230Sgibbs case 'p': 214112284Sphk if (devstat_buildmatch(optarg, &matches, &num_matches) != 0) 21539230Sgibbs errx(1, "%s", devstat_errbuf); 21639230Sgibbs break; 2171590Srgrimes case 's': 2181590Srgrimes todo |= SUMSTAT; 2191590Srgrimes break; 2201590Srgrimes case 't': 22130180Sdima#ifdef notyet 2221590Srgrimes todo |= TIMESTAT; 22330180Sdima#else 22430180Sdima errx(EX_USAGE, "sorry, -t is not (re)implemented yet"); 22530180Sdima#endif 2261590Srgrimes break; 2271590Srgrimes case 'w': 2281590Srgrimes interval = atoi(optarg); 2291590Srgrimes break; 23044067Sbde case 'z': 23144067Sbde todo |= ZMEMSTAT; 23244067Sbde break; 2331590Srgrimes case '?': 2341590Srgrimes default: 2351590Srgrimes usage(); 2361590Srgrimes } 2371590Srgrimes } 2381590Srgrimes argc -= optind; 2391590Srgrimes argv += optind; 2401590Srgrimes 2411590Srgrimes if (todo == 0) 2421590Srgrimes todo = VMSTAT; 2431590Srgrimes 244123250Sdes if (memf != NULL) { 245123250Sdes kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 246123250Sdes if (kd == NULL) 247123250Sdes errx(1, "kvm_openfiles: %s", errbuf); 248123250Sdes } 2491590Srgrimes 250123250Sdes if (kd != NULL && (c = kvm_nlist(kd, namelist)) != 0) { 2511590Srgrimes if (c > 0) { 25228693Scharnier warnx("undefined symbols:"); 2531590Srgrimes for (c = 0; 254123250Sdes c < (int)(sizeof(namelist)/sizeof(namelist[0])); 255123250Sdes c++) 2561590Srgrimes if (namelist[c].n_type == 0) 25781537Sken (void)fprintf(stderr, " %s", 2581590Srgrimes namelist[c].n_name); 2591590Srgrimes (void)fputc('\n', stderr); 2601590Srgrimes } else 26128693Scharnier warnx("kvm_nlist: %s", kvm_geterr(kd)); 2621590Srgrimes exit(1); 2631590Srgrimes } 2641590Srgrimes 2651590Srgrimes if (todo & VMSTAT) { 2661590Srgrimes struct winsize winsize; 2671590Srgrimes 26843819Sken /* 26943819Sken * Make sure that the userland devstat version matches the 27043819Sken * kernel devstat version. If not, exit and print a 27143819Sken * message informing the user of his mistake. 27243819Sken */ 273112284Sphk if (devstat_checkversion(NULL) < 0) 27443819Sken errx(1, "%s", devstat_errbuf); 27543819Sken 27643819Sken 2771590Srgrimes argv = getdrivedata(argv); 2781590Srgrimes winsize.ws_row = 0; 2791590Srgrimes (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 2801590Srgrimes if (winsize.ws_row > 0) 2811590Srgrimes winlines = winsize.ws_row; 2821590Srgrimes 2831590Srgrimes } 2841590Srgrimes 2851590Srgrimes#define BACKWARD_COMPATIBILITY 2861590Srgrimes#ifdef BACKWARD_COMPATIBILITY 2871590Srgrimes if (*argv) { 2881590Srgrimes interval = atoi(*argv); 2891590Srgrimes if (*++argv) 2901590Srgrimes reps = atoi(*argv); 2911590Srgrimes } 2921590Srgrimes#endif 2931590Srgrimes 2941590Srgrimes if (interval) { 2951590Srgrimes if (!reps) 2961590Srgrimes reps = -1; 2971590Srgrimes } else if (reps) 2981590Srgrimes interval = 1; 2991590Srgrimes 3001590Srgrimes if (todo & FORKSTAT) 3011590Srgrimes doforkst(); 3021590Srgrimes if (todo & MEMSTAT) 3031590Srgrimes domem(); 30443962Sdillon if (todo & ZMEMSTAT) 30543962Sdillon dozmem(); 3061590Srgrimes if (todo & SUMSTAT) 3071590Srgrimes dosum(); 30830180Sdima#ifdef notyet 3091590Srgrimes if (todo & TIMESTAT) 3101590Srgrimes dotimes(); 3111590Srgrimes#endif 3121590Srgrimes if (todo & INTRSTAT) 3131590Srgrimes dointr(); 3141590Srgrimes if (todo & VMSTAT) 3151590Srgrimes dovmstat(interval, reps); 3161590Srgrimes exit(0); 3171590Srgrimes} 3181590Srgrimes 319123250Sdesstatic int 320123250Sdesmysysctl(const char *name, void *oldp, size_t *oldlenp, 321123250Sdes void *newp, size_t newlen) 3221590Srgrimes{ 323123250Sdes int error; 324123250Sdes 325123250Sdes error = sysctlbyname(name, oldp, oldlenp, newp, newlen); 326123250Sdes if (error != 0 && errno != ENOMEM) 327123250Sdes err(1, "sysctl(%s)", name); 328123250Sdes return (error); 329123250Sdes} 330123250Sdes 331123250Sdesstatic char ** 332123250Sdesgetdrivedata(char **argv) 333123250Sdes{ 334112284Sphk if ((num_devices = devstat_getnumdevs(NULL)) < 0) 33539230Sgibbs errx(1, "%s", devstat_errbuf); 3361590Srgrimes 33739230Sgibbs cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); 33839230Sgibbs last.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); 33939230Sgibbs bzero(cur.dinfo, sizeof(struct devinfo)); 34039230Sgibbs bzero(last.dinfo, sizeof(struct devinfo)); 34139230Sgibbs 342112284Sphk if (devstat_getdevs(NULL, &cur) == -1) 34339230Sgibbs errx(1, "%s", devstat_errbuf); 34439230Sgibbs 34539230Sgibbs num_devices = cur.dinfo->numdevs; 34639230Sgibbs generation = cur.dinfo->generation; 34739230Sgibbs 34839230Sgibbs specified_devices = (char **)malloc(sizeof(char *)); 34939230Sgibbs for (num_devices_specified = 0; *argv; ++argv) { 3501590Srgrimes if (isdigit(**argv)) 3511590Srgrimes break; 35239230Sgibbs num_devices_specified++; 35339230Sgibbs specified_devices = (char **)realloc(specified_devices, 35439230Sgibbs sizeof(char *) * 35539230Sgibbs num_devices_specified); 35639230Sgibbs specified_devices[num_devices_specified - 1] = *argv; 3571590Srgrimes } 35839230Sgibbs dev_select = NULL; 35939230Sgibbs 36039372Sdillon if (nflag == 0 && maxshowdevs < num_devices_specified) 36139372Sdillon maxshowdevs = num_devices_specified; 36239372Sdillon 36339230Sgibbs /* 36439230Sgibbs * People are generally only interested in disk statistics when 36539230Sgibbs * they're running vmstat. So, that's what we're going to give 36639230Sgibbs * them if they don't specify anything by default. We'll also give 36739230Sgibbs * them any other random devices in the system so that we get to 36839230Sgibbs * maxshowdevs devices, if that many devices exist. If the user 36939230Sgibbs * specifies devices on the command line, either through a pattern 37039230Sgibbs * match or by naming them explicitly, we will give the user only 37139230Sgibbs * those devices. 37239230Sgibbs */ 37339230Sgibbs if ((num_devices_specified == 0) && (num_matches == 0)) { 374112284Sphk if (devstat_buildmatch(da, &matches, &num_matches) != 0) 37539230Sgibbs errx(1, "%s", devstat_errbuf); 37639230Sgibbs 37739230Sgibbs select_mode = DS_SELECT_ADD; 37839230Sgibbs } else 37939230Sgibbs select_mode = DS_SELECT_ONLY; 38039230Sgibbs 38139230Sgibbs /* 38239230Sgibbs * At this point, selectdevs will almost surely indicate that the 38339230Sgibbs * device list has changed, so we don't look for return values of 0 38439230Sgibbs * or 1. If we get back -1, though, there is an error. 38539230Sgibbs */ 386112284Sphk if (devstat_selectdevs(&dev_select, &num_selected, &num_selections, 38739230Sgibbs &select_generation, generation, cur.dinfo->devices, 38839230Sgibbs num_devices, matches, num_matches, specified_devices, 38939230Sgibbs num_devices_specified, select_mode, 39039230Sgibbs maxshowdevs, 0) == -1) 39139230Sgibbs errx(1, "%s", devstat_errbuf); 39239230Sgibbs 3931590Srgrimes return(argv); 3941590Srgrimes} 3951590Srgrimes 396123250Sdesstatic long 397123250Sdesgetuptime(void) 3981590Srgrimes{ 399101590Stmm static struct timeval boottime; 400101590Stmm static time_t now; 4011590Srgrimes time_t uptime; 4021590Srgrimes 403123250Sdes if (boottime.tv_sec == 0) { 404123250Sdes if (kd != NULL) { 405123250Sdes kread(X_BOOTTIME, &boottime, sizeof(boottime)); 406123250Sdes } else { 407123250Sdes size_t size; 408123250Sdes 409123250Sdes size = sizeof(boottime); 410123250Sdes mysysctl("kern.boottime", &boottime, &size, NULL, 0); 411123250Sdes if (size != sizeof(boottime)) 412123250Sdes errx(1, "kern.boottime size mismatch"); 413123250Sdes } 414123250Sdes } 4151590Srgrimes (void)time(&now); 416101590Stmm uptime = now - boottime.tv_sec; 41728693Scharnier if (uptime <= 0 || uptime > 60*60*24*365*10) 41828693Scharnier errx(1, "time makes no sense; namelist must be wrong"); 4191590Srgrimes return(uptime); 4201590Srgrimes} 4211590Srgrimes 422123250Sdesstatic void 423123250Sdesfill_vmmeter(struct vmmeter *vmmp) 424123250Sdes{ 425123250Sdes if (kd != NULL) { 426123250Sdes kread(X_SUM, vmmp, sizeof(*vmmp)); 427123250Sdes } else { 428123250Sdes size_t size = sizeof(unsigned int); 429123250Sdes#define GET_VM_STATS(cat, name) \ 430123250Sdes mysysctl("vm.stats." #cat "." #name, &vmmp->name, &size, NULL, 0) 431123250Sdes /* sys */ 432123250Sdes GET_VM_STATS(sys, v_swtch); 433123250Sdes GET_VM_STATS(sys, v_trap); 434123250Sdes GET_VM_STATS(sys, v_syscall); 435123250Sdes GET_VM_STATS(sys, v_intr); 436123250Sdes GET_VM_STATS(sys, v_soft); 4371590Srgrimes 438123250Sdes /* vm */ 439123414Sdes GET_VM_STATS(vm, v_vm_faults); 440123414Sdes GET_VM_STATS(vm, v_cow_faults); 441123414Sdes GET_VM_STATS(vm, v_cow_optim); 442123414Sdes GET_VM_STATS(vm, v_zfod); 443123414Sdes GET_VM_STATS(vm, v_ozfod); 444123414Sdes GET_VM_STATS(vm, v_swapin); 445123414Sdes GET_VM_STATS(vm, v_swapout); 446123414Sdes GET_VM_STATS(vm, v_swappgsin); 447123414Sdes GET_VM_STATS(vm, v_swappgsout); 448123414Sdes GET_VM_STATS(vm, v_vnodein); 449123414Sdes GET_VM_STATS(vm, v_vnodeout); 450123414Sdes GET_VM_STATS(vm, v_vnodepgsin); 451123414Sdes GET_VM_STATS(vm, v_vnodepgsout); 452123414Sdes GET_VM_STATS(vm, v_intrans); 453123414Sdes GET_VM_STATS(vm, v_reactivated); 454123414Sdes GET_VM_STATS(vm, v_pdwakeups); 455123414Sdes GET_VM_STATS(vm, v_pdpages); 456123414Sdes GET_VM_STATS(vm, v_dfree); 457123414Sdes GET_VM_STATS(vm, v_pfree); 458123414Sdes GET_VM_STATS(vm, v_tfree); 459123414Sdes GET_VM_STATS(vm, v_page_size); 460123414Sdes GET_VM_STATS(vm, v_page_count); 461123414Sdes GET_VM_STATS(vm, v_free_reserved); 462123414Sdes GET_VM_STATS(vm, v_free_target); 463123414Sdes GET_VM_STATS(vm, v_free_min); 464123414Sdes GET_VM_STATS(vm, v_free_count); 465123414Sdes GET_VM_STATS(vm, v_wire_count); 466123414Sdes GET_VM_STATS(vm, v_active_count); 467123414Sdes GET_VM_STATS(vm, v_inactive_target); 468123414Sdes GET_VM_STATS(vm, v_inactive_count); 469123414Sdes GET_VM_STATS(vm, v_cache_count); 470123414Sdes GET_VM_STATS(vm, v_cache_min); 471123414Sdes GET_VM_STATS(vm, v_cache_max); 472123414Sdes GET_VM_STATS(vm, v_pageout_free_min); 473123414Sdes GET_VM_STATS(vm, v_interrupt_free_min); 474123414Sdes /*GET_VM_STATS(vm, v_free_severe);*/ 475123250Sdes GET_VM_STATS(vm, v_forks); 476123250Sdes GET_VM_STATS(vm, v_vforks); 477123250Sdes GET_VM_STATS(vm, v_rforks); 478123250Sdes GET_VM_STATS(vm, v_kthreads); 479123250Sdes GET_VM_STATS(vm, v_forkpages); 480123250Sdes GET_VM_STATS(vm, v_vforkpages); 481123250Sdes GET_VM_STATS(vm, v_rforkpages); 482123250Sdes GET_VM_STATS(vm, v_kthreadpages); 483123250Sdes#undef GET_VM_STATS 484123250Sdes } 485123250Sdes} 486123250Sdes 487123250Sdesstatic void 488123250Sdesfill_vmtotal(struct vmtotal *vmtp) 4891590Srgrimes{ 490123250Sdes if (kd != NULL) { 491123250Sdes /* XXX fill vmtp */ 492123250Sdes errx(1, "not implemented"); 493123250Sdes } else { 494123250Sdes size_t size = sizeof(*vmtp); 495123250Sdes mysysctl("vm.vmtotal", vmtp, &size, NULL, 0); 496123250Sdes if (size != sizeof(*vmtp)) 497123250Sdes errx(1, "vm.total size mismatch"); 498123250Sdes } 499123250Sdes} 500123250Sdes 501123250Sdesstatic int hz, hdrcnt; 502123250Sdes 503123250Sdesstatic void 504123407Sdesdovmstat(unsigned int interval, int reps) 505123250Sdes{ 5061590Srgrimes struct vmtotal total; 5071590Srgrimes time_t uptime, halfuptime; 50839230Sgibbs struct devinfo *tmp_dinfo; 50980551Stmm size_t size; 5101590Srgrimes 5111590Srgrimes uptime = getuptime(); 5121590Srgrimes halfuptime = uptime / 2; 5131590Srgrimes (void)signal(SIGCONT, needhdr); 5141590Srgrimes 515123250Sdes if (kd != NULL) { 516123250Sdes if (namelist[X_STATHZ].n_type != 0 && 517123250Sdes namelist[X_STATHZ].n_value != 0) 518123250Sdes kread(X_STATHZ, &hz, sizeof(hz)); 519123250Sdes if (!hz) 520123250Sdes kread(X_HZ, &hz, sizeof(hz)); 521123250Sdes } else { 522123250Sdes struct clockinfo clockrate; 5231590Srgrimes 524123250Sdes size = sizeof(clockrate); 525123250Sdes mysysctl("kern.clockrate", &clockrate, &size, NULL, 0); 526123250Sdes if (size != sizeof(clockrate)) 527123250Sdes errx(1, "clockrate size mismatch"); 528123250Sdes hz = clockrate.hz; 529123250Sdes } 530123250Sdes 5311590Srgrimes for (hdrcnt = 1;;) { 5321590Srgrimes if (!--hdrcnt) 5331590Srgrimes printhdr(); 534123250Sdes if (kd != NULL) { 535123250Sdes kread(X_CPTIME, cur.cp_time, sizeof(cur.cp_time)); 536123250Sdes } else { 537123250Sdes size = sizeof(cur.cp_time); 538123250Sdes mysysctl("kern.cp_time", &cur.cp_time, &size, NULL, 0); 539123250Sdes if (size != sizeof(cur.cp_time)) 540123250Sdes errx(1, "cp_time size mismatch"); 541123250Sdes } 54239230Sgibbs 54339230Sgibbs tmp_dinfo = last.dinfo; 54439230Sgibbs last.dinfo = cur.dinfo; 54539230Sgibbs cur.dinfo = tmp_dinfo; 546112288Sphk last.snap_time = cur.snap_time; 54739230Sgibbs 54839230Sgibbs /* 54939230Sgibbs * Here what we want to do is refresh our device stats. 55039230Sgibbs * getdevs() returns 1 when the device list has changed. 55139230Sgibbs * If the device list has changed, we want to go through 55239230Sgibbs * the selection process again, in case a device that we 55339230Sgibbs * were previously displaying has gone away. 55439230Sgibbs */ 555112284Sphk switch (devstat_getdevs(NULL, &cur)) { 55639230Sgibbs case -1: 55739230Sgibbs errx(1, "%s", devstat_errbuf); 55839230Sgibbs break; 55939230Sgibbs case 1: { 56039230Sgibbs int retval; 56139230Sgibbs 56239230Sgibbs num_devices = cur.dinfo->numdevs; 56339230Sgibbs generation = cur.dinfo->generation; 56439230Sgibbs 565112284Sphk retval = devstat_selectdevs(&dev_select, &num_selected, 56639230Sgibbs &num_selections, &select_generation, 56739230Sgibbs generation, cur.dinfo->devices, 56839230Sgibbs num_devices, matches, num_matches, 56939230Sgibbs specified_devices, 57039230Sgibbs num_devices_specified, select_mode, 57139230Sgibbs maxshowdevs, 0); 57239230Sgibbs switch (retval) { 57339230Sgibbs case -1: 57439230Sgibbs errx(1, "%s", devstat_errbuf); 57539230Sgibbs break; 57639230Sgibbs case 1: 57739230Sgibbs printhdr(); 57839230Sgibbs break; 57939230Sgibbs default: 58039230Sgibbs break; 58139230Sgibbs } 58239230Sgibbs } 58339230Sgibbs default: 58439230Sgibbs break; 58539230Sgibbs } 58639230Sgibbs 587123250Sdes fill_vmmeter(&sum); 588123250Sdes fill_vmtotal(&total); 58978672Sschweikh (void)printf("%2d %1d %1d", 5901590Srgrimes total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); 59172887Salfred#define vmstat_pgtok(a) ((a) * sum.v_page_size >> 10) 5921590Srgrimes#define rate(x) (((x) + halfuptime) / uptime) /* round */ 59381537Sken (void)printf(" %7ld %6ld ", (long)vmstat_pgtok(total.t_avm), 59481537Sken (long)vmstat_pgtok(total.t_free)); 59537453Sbde (void)printf("%4lu ", 596123407Sdes (unsigned long)rate(sum.v_vm_faults - osum.v_vm_faults)); 5971590Srgrimes (void)printf("%3lu ", 598123407Sdes (unsigned long)rate(sum.v_reactivated - osum.v_reactivated)); 59937453Sbde (void)printf("%3lu ", 600123407Sdes (unsigned long)rate(sum.v_swapin + sum.v_vnodein - 6013659Sdg (osum.v_swapin + osum.v_vnodein))); 60237453Sbde (void)printf("%3lu ", 603123407Sdes (unsigned long)rate(sum.v_swapout + sum.v_vnodeout - 6043693Sdg (osum.v_swapout + osum.v_vnodeout))); 60537453Sbde (void)printf("%3lu ", 606123407Sdes (unsigned long)rate(sum.v_tfree - osum.v_tfree)); 60737453Sbde (void)printf("%3lu ", 608123407Sdes (unsigned long)rate(sum.v_pdpages - osum.v_pdpages)); 60939230Sgibbs devstats(); 6101590Srgrimes (void)printf("%4lu %4lu %3lu ", 611123407Sdes (unsigned long)rate(sum.v_intr - osum.v_intr), 612123407Sdes (unsigned long)rate(sum.v_syscall - osum.v_syscall), 613123407Sdes (unsigned long)rate(sum.v_swtch - osum.v_swtch)); 6141590Srgrimes cpustats(); 6151590Srgrimes (void)printf("\n"); 6161590Srgrimes (void)fflush(stdout); 6171590Srgrimes if (reps >= 0 && --reps <= 0) 6181590Srgrimes break; 6191590Srgrimes osum = sum; 6201590Srgrimes uptime = interval; 6211590Srgrimes /* 6221590Srgrimes * We round upward to avoid losing low-frequency events 6231590Srgrimes * (i.e., >= 1 per interval but < 1 per second). 6241590Srgrimes */ 6253659Sdg if (interval != 1) 6263659Sdg halfuptime = (uptime + 1) / 2; 6273659Sdg else 6283659Sdg halfuptime = 0; 6291590Srgrimes (void)sleep(interval); 6301590Srgrimes } 6311590Srgrimes} 6321590Srgrimes 633123250Sdesstatic void 634123250Sdesprinthdr(void) 6351590Srgrimes{ 63643822Sken int i, num_shown; 6371590Srgrimes 63843822Sken num_shown = (num_selected < maxshowdevs) ? num_selected : maxshowdevs; 63978672Sschweikh (void)printf(" procs memory page%*s", 19, ""); 64043822Sken if (num_shown > 1) 64143822Sken (void)printf(" disks %*s", num_shown * 4 - 7, ""); 64243822Sken else if (num_shown == 1) 64343822Sken (void)printf("disk"); 64443822Sken (void)printf(" faults cpu\n"); 64578672Sschweikh (void)printf(" r b w avm fre flt re pi po fr sr "); 64639230Sgibbs for (i = 0; i < num_devices; i++) 64739230Sgibbs if ((dev_select[i].selected) 64839230Sgibbs && (dev_select[i].selected <= maxshowdevs)) 64939230Sgibbs (void)printf("%c%c%d ", dev_select[i].device_name[0], 65039230Sgibbs dev_select[i].device_name[1], 65139230Sgibbs dev_select[i].unit_number); 6521590Srgrimes (void)printf(" in sy cs us sy id\n"); 6531590Srgrimes hdrcnt = winlines - 2; 6541590Srgrimes} 6551590Srgrimes 6561590Srgrimes/* 6571590Srgrimes * Force a header to be prepended to the next output. 6581590Srgrimes */ 659123250Sdesstatic void 660123250Sdesneedhdr(int dummy __unused) 6611590Srgrimes{ 6621590Srgrimes 6631590Srgrimes hdrcnt = 1; 6641590Srgrimes} 6651590Srgrimes 66630180Sdima#ifdef notyet 667123250Sdesstatic void 668123250Sdesdotimes(void) 6691590Srgrimes{ 670123407Sdes unsigned int pgintime, rectime; 6711590Srgrimes 6721590Srgrimes kread(X_REC, &rectime, sizeof(rectime)); 6731590Srgrimes kread(X_PGIN, &pgintime, sizeof(pgintime)); 6741590Srgrimes kread(X_SUM, &sum, sizeof(sum)); 6751590Srgrimes (void)printf("%u reclaims, %u total time (usec)\n", 6761590Srgrimes sum.v_pgrec, rectime); 6771590Srgrimes (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 6781590Srgrimes (void)printf("\n"); 6791590Srgrimes (void)printf("%u page ins, %u total time (msec)\n", 6801590Srgrimes sum.v_pgin, pgintime / 10); 6811590Srgrimes (void)printf("average: %8.1f msec / page in\n", 6821590Srgrimes pgintime / (sum.v_pgin * 10.0)); 6831590Srgrimes} 6841590Srgrimes#endif 6851590Srgrimes 686123250Sdesstatic long 687123250Sdespct(long top, long bot) 6881590Srgrimes{ 6891590Srgrimes long ans; 6901590Srgrimes 6911590Srgrimes if (bot == 0) 6921590Srgrimes return(0); 6931590Srgrimes ans = (quad_t)top * 100 / bot; 6941590Srgrimes return (ans); 6951590Srgrimes} 6961590Srgrimes 6971590Srgrimes#define PCT(top, bot) pct((long)(top), (long)(bot)) 6981590Srgrimes 699123250Sdesstatic void 700123250Sdesdosum(void) 7011590Srgrimes{ 70287690Smarkm struct nchstats lnchstats; 7031590Srgrimes long nchtotal; 7041590Srgrimes 705123250Sdes fill_vmmeter(&sum); 7061590Srgrimes (void)printf("%9u cpu context switches\n", sum.v_swtch); 7071590Srgrimes (void)printf("%9u device interrupts\n", sum.v_intr); 7081590Srgrimes (void)printf("%9u software interrupts\n", sum.v_soft); 7091590Srgrimes (void)printf("%9u traps\n", sum.v_trap); 7101590Srgrimes (void)printf("%9u system calls\n", sum.v_syscall); 71171429Sume (void)printf("%9u kernel threads created\n", sum.v_kthreads); 71271429Sume (void)printf("%9u fork() calls\n", sum.v_forks); 71371429Sume (void)printf("%9u vfork() calls\n", sum.v_vforks); 71471429Sume (void)printf("%9u rfork() calls\n", sum.v_rforks); 7153659Sdg (void)printf("%9u swap pager pageins\n", sum.v_swapin); 7163693Sdg (void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin); 7173659Sdg (void)printf("%9u swap pager pageouts\n", sum.v_swapout); 7183659Sdg (void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout); 7193659Sdg (void)printf("%9u vnode pager pageins\n", sum.v_vnodein); 7203693Sdg (void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin); 7213659Sdg (void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout); 7223659Sdg (void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout); 7233693Sdg (void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups); 7243693Sdg (void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages); 7251590Srgrimes (void)printf("%9u pages reactivated\n", sum.v_reactivated); 7267351Sdg (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 72734214Sdyson (void)printf("%9u copy-on-write optimized faults\n", sum.v_cow_optim); 7287351Sdg (void)printf("%9u zero fill pages zeroed\n", sum.v_zfod); 72934214Sdyson (void)printf("%9u zero fill pages prezeroed\n", sum.v_ozfod); 7301590Srgrimes (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 7311590Srgrimes (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 73271429Sume (void)printf("%9u pages affected by kernel thread creation\n", sum.v_kthreadpages); 73371429Sume (void)printf("%9u pages affected by fork()\n", sum.v_forkpages); 73471429Sume (void)printf("%9u pages affected by vfork()\n", sum.v_vforkpages); 73571429Sume (void)printf("%9u pages affected by rfork()\n", sum.v_rforkpages); 7363693Sdg (void)printf("%9u pages freed\n", sum.v_tfree); 7371590Srgrimes (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 7381590Srgrimes (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 7391590Srgrimes (void)printf("%9u pages active\n", sum.v_active_count); 7401590Srgrimes (void)printf("%9u pages inactive\n", sum.v_inactive_count); 7415463Sdg (void)printf("%9u pages in VM cache\n", sum.v_cache_count); 7423693Sdg (void)printf("%9u pages wired down\n", sum.v_wire_count); 7433693Sdg (void)printf("%9u pages free\n", sum.v_free_count); 7441590Srgrimes (void)printf("%9u bytes per page\n", sum.v_page_size); 745123250Sdes if (kd != NULL) { 746123250Sdes kread(X_NCHSTATS, &lnchstats, sizeof(lnchstats)); 747123250Sdes } else { 748123250Sdes size_t size = sizeof(lnchstats); 749123250Sdes mysysctl("vfs.cache.nchstats", &lnchstats, &size, NULL, 0); 750123250Sdes if (size != sizeof(lnchstats)) 751123250Sdes errx(1, "vfs.cache.nchstats size mismatch"); 752123250Sdes } 75387690Smarkm nchtotal = lnchstats.ncs_goodhits + lnchstats.ncs_neghits + 75487690Smarkm lnchstats.ncs_badhits + lnchstats.ncs_falsehits + 75587690Smarkm lnchstats.ncs_miss + lnchstats.ncs_long; 7561590Srgrimes (void)printf("%9ld total name lookups\n", nchtotal); 7571590Srgrimes (void)printf( 75828693Scharnier "%9s cache hits (%ld%% pos + %ld%% neg) system %ld%% per-directory\n", 75987690Smarkm "", PCT(lnchstats.ncs_goodhits, nchtotal), 76087690Smarkm PCT(lnchstats.ncs_neghits, nchtotal), 76187690Smarkm PCT(lnchstats.ncs_pass2, nchtotal)); 76228693Scharnier (void)printf("%9s deletions %ld%%, falsehits %ld%%, toolong %ld%%\n", "", 76387690Smarkm PCT(lnchstats.ncs_badhits, nchtotal), 76487690Smarkm PCT(lnchstats.ncs_falsehits, nchtotal), 76587690Smarkm PCT(lnchstats.ncs_long, nchtotal)); 7661590Srgrimes} 7671590Srgrimes 768123250Sdesstatic void 769123250Sdesdoforkst(void) 7701590Srgrimes{ 771123250Sdes fill_vmmeter(&sum); 772128573Stjr (void)printf("%u forks, %u pages, average %.2f\n", 773113460Stjr sum.v_forks, sum.v_forkpages, 774113460Stjr sum.v_forks == 0 ? 0.0 : 775113460Stjr (double)sum.v_forkpages / sum.v_forks); 776128573Stjr (void)printf("%u vforks, %u pages, average %.2f\n", 777113460Stjr sum.v_vforks, sum.v_vforkpages, 778113460Stjr sum.v_vforks == 0 ? 0.0 : 779113460Stjr (double)sum.v_vforkpages / sum.v_vforks); 780128573Stjr (void)printf("%u rforks, %u pages, average %.2f\n", 781113460Stjr sum.v_rforks, sum.v_rforkpages, 782113460Stjr sum.v_rforks == 0 ? 0.0 : 783113460Stjr (double)sum.v_rforkpages / sum.v_rforks); 7841590Srgrimes} 7851590Srgrimes 78639230Sgibbsstatic void 787123250Sdesdevstats(void) 7881590Srgrimes{ 78987690Smarkm int dn, state; 79039230Sgibbs long double transfers_per_second; 79139230Sgibbs long double busy_seconds; 7921590Srgrimes long tmp; 793123250Sdes 7941590Srgrimes for (state = 0; state < CPUSTATES; ++state) { 79539230Sgibbs tmp = cur.cp_time[state]; 79639230Sgibbs cur.cp_time[state] -= last.cp_time[state]; 79739230Sgibbs last.cp_time[state] = tmp; 7981590Srgrimes } 79939230Sgibbs 800112288Sphk busy_seconds = cur.snap_time - last.snap_time; 80139230Sgibbs 80239230Sgibbs for (dn = 0; dn < num_devices; dn++) { 80339230Sgibbs int di; 80439230Sgibbs 80539230Sgibbs if ((dev_select[dn].selected == 0) 80639230Sgibbs || (dev_select[dn].selected > maxshowdevs)) 8071590Srgrimes continue; 80839230Sgibbs 80939230Sgibbs di = dev_select[dn].position; 81039230Sgibbs 81181537Sken if (devstat_compute_statistics(&cur.dinfo->devices[di], 81281537Sken &last.dinfo->devices[di], busy_seconds, 81381537Sken DSM_TRANSFERS_PER_SECOND, &transfers_per_second, 81481537Sken DSM_NONE) != 0) 81539230Sgibbs errx(1, "%s", devstat_errbuf); 81639230Sgibbs 81781537Sken (void)printf("%3.0Lf ", transfers_per_second); 8181590Srgrimes } 8191590Srgrimes} 8201590Srgrimes 821123250Sdesstatic void 822123250Sdescpustats(void) 8231590Srgrimes{ 82487690Smarkm int state; 82587690Smarkm double lpct, total; 8261590Srgrimes 8271590Srgrimes total = 0; 8281590Srgrimes for (state = 0; state < CPUSTATES; ++state) 82939230Sgibbs total += cur.cp_time[state]; 8301590Srgrimes if (total) 83187690Smarkm lpct = 100.0 / total; 8321590Srgrimes else 83387690Smarkm lpct = 0.0; 83439230Sgibbs (void)printf("%2.0f ", (cur.cp_time[CP_USER] + 83587690Smarkm cur.cp_time[CP_NICE]) * lpct); 83639230Sgibbs (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + 83787690Smarkm cur.cp_time[CP_INTR]) * lpct); 83887690Smarkm (void)printf("%2.0f", cur.cp_time[CP_IDLE] * lpct); 8391590Srgrimes} 8401590Srgrimes 841123250Sdesstatic void 842123250Sdesdointr(void) 8431590Srgrimes{ 844123407Sdes unsigned long *intrcnt, uptime; 845123409Sdes uint64_t inttotal; 846123409Sdes size_t clen, inamlen, intrcntlen, istrnamlen; 847123409Sdes unsigned int i, nintr; 848121626Sjmg char *intrname, *tintrname; 8491590Srgrimes 8501590Srgrimes uptime = getuptime(); 851123250Sdes if (kd != NULL) { 852123409Sdes intrcntlen = namelist[X_EINTRCNT].n_value - 853123250Sdes namelist[X_INTRCNT].n_value; 854123250Sdes inamlen = namelist[X_EINTRNAMES].n_value - 855123250Sdes namelist[X_INTRNAMES].n_value; 856123409Sdes if ((intrcnt = malloc(intrcntlen)) == NULL || 857123290Smarcel (intrname = malloc(inamlen)) == NULL) 858123250Sdes err(1, "malloc()"); 859123409Sdes kread(X_INTRCNT, intrcnt, intrcntlen); 860123290Smarcel kread(X_INTRNAMES, intrname, inamlen); 861123250Sdes } else { 862123438Sdes for (intrcnt = NULL, intrcntlen = 1024; ; intrcntlen *= 2) { 863123438Sdes if ((intrcnt = reallocf(intrcnt, intrcntlen)) == NULL) 864123438Sdes err(1, "reallocf()"); 865123438Sdes if (mysysctl("hw.intrcnt", 866123438Sdes intrcnt, &intrcntlen, NULL, 0) == 0) 867123438Sdes break; 868123438Sdes } 869123250Sdes for (intrname = NULL, inamlen = 1024; ; inamlen *= 2) { 870123250Sdes if ((intrname = reallocf(intrname, inamlen)) == NULL) 871123250Sdes err(1, "reallocf()"); 872123250Sdes if (mysysctl("hw.intrnames", 873123250Sdes intrname, &inamlen, NULL, 0) == 0) 874123250Sdes break; 875123250Sdes } 876123250Sdes } 877123409Sdes nintr = intrcntlen / sizeof(unsigned long); 878121626Sjmg tintrname = intrname; 879122365Sjmg istrnamlen = strlen("interrupt"); 880121626Sjmg for (i = 0; i < nintr; i++) { 881121626Sjmg clen = strlen(tintrname); 882121626Sjmg if (clen > istrnamlen) 883121626Sjmg istrnamlen = clen; 884121626Sjmg tintrname += clen + 1; 885121626Sjmg } 886121626Sjmg (void)printf("%-*s %20s %10s\n", istrnamlen, "interrupt", "total", 887121626Sjmg "rate"); 8881590Srgrimes inttotal = 0; 889123290Smarcel for (i = 0; i < nintr; i++) { 890123409Sdes if (intrname[0] != '\0' && (*intrcnt != 0 || aflag)) 891121626Sjmg (void)printf("%-*s %20lu %10lu\n", istrnamlen, intrname, 8921590Srgrimes *intrcnt, *intrcnt / uptime); 8931590Srgrimes intrname += strlen(intrname) + 1; 8941590Srgrimes inttotal += *intrcnt++; 8951590Srgrimes } 896123290Smarcel (void)printf("%-*s %20llu %10llu\n", istrnamlen, "Total", 897123290Smarcel (long long)inttotal, (long long)(inttotal / uptime)); 8981590Srgrimes} 8991590Srgrimes 900123250Sdesstatic void 90194729Sjeffdomem(void) 90294729Sjeff{ 903131300Sgreen struct malloc_type type; 904131300Sgreen 905131300Sgreen if (kd == NULL) { 906131300Sgreen dosysctl("kern.malloc"); 907131300Sgreen return; 908131300Sgreen } 909131300Sgreen kread(X_KMEMSTATS, &type.ks_next, sizeof(type.ks_next)); 910131300Sgreen (void)printf("\n Type InUse MemUse HighUse Requests" 911131300Sgreen " Size(s)\n"); 912131300Sgreen do { 913131300Sgreen /* XXX this should be exported in sys/malloc.h */ 914131300Sgreen struct { 915131300Sgreen int kz_size; 916131300Sgreen char *kz_name; 917131300Sgreen /* uma_zone_t */ void *kz_zone; 918131300Sgreen } kz; 919131300Sgreen size_t kmemzonenum; 920131300Sgreen char *str; 921131300Sgreen int first; 922131300Sgreen 923131300Sgreen if (kvm_read(kd, (u_long)type.ks_next, &type, sizeof(type)) != 924131300Sgreen sizeof(type)) 925131300Sgreen errx(1, "%s: %p: %s", __func__, type.ks_next, 926131300Sgreen kvm_geterr(kd)); 927131300Sgreen if (type.ks_calls == 0) 928131300Sgreen continue; 929131300Sgreen str = kgetstr(type.ks_shortdesc); 930131300Sgreen (void)printf("%13s%6lu%6luK%7luK%9llu", 931131300Sgreen str, 932131300Sgreen type.ks_inuse, 933131300Sgreen (type.ks_memuse + 1023) / 1024, 934131300Sgreen (type.ks_maxused + 1023) / 1024, 935131300Sgreen (long long unsigned)type.ks_calls); 936131300Sgreen free(str); 937131300Sgreen for (kmemzonenum = 0, first = 1; ; kmemzonenum++) { 938131300Sgreen kreado(X_KMEMZONES, &kz, sizeof(kz), 939131300Sgreen kmemzonenum * sizeof(kz)); 940131300Sgreen if (kz.kz_name == NULL) { 941131300Sgreen (void)printf("\n"); 942131300Sgreen break; 943131300Sgreen } 944131300Sgreen if (!(type.ks_size & (1 << kmemzonenum))) 945131300Sgreen continue; 946131300Sgreen if (first) 947131300Sgreen (void)printf(" "); 948131300Sgreen else 949131300Sgreen (void)printf(","); 950131300Sgreen first = 0; 951131300Sgreen str = kgetstr(kz.kz_name); 952131300Sgreen (void)printf("%s", str); 953131300Sgreen free(str); 954131300Sgreen } 955131300Sgreen } while (type.ks_next != NULL); 95694729Sjeff} 95746852Simp 958123250Sdesstatic void 95994729Sjeffdozmem(void) 9601590Srgrimes{ 961123250Sdes if (kd != NULL) 962123250Sdes errx(1, "not implemented"); 96394729Sjeff dosysctl("vm.zone"); 9641590Srgrimes} 9651590Srgrimes 966123250Sdesstatic void 967123401Sdwmalonedosysctl(const char *name) 96843962Sdillon{ 96971404Sdes char *buf; 97071404Sdes size_t bufsize; 97143962Sdillon 972123250Sdes for (buf = NULL, bufsize = 1024; ; bufsize *= 2) { 97371404Sdes if ((buf = realloc(buf, bufsize)) == NULL) 97471404Sdes err(1, "realloc()"); 975126842Sbde bufsize--; /* Leave space for the kern.malloc fixup. */ 976126842Sbde if (mysysctl(name, buf, &bufsize, NULL, 0) == 0) 97743962Sdillon break; 97843962Sdillon } 979126842Sbde buf[bufsize] = '\0'; /* Fix up kern.malloc not returning a string. */ 980126842Sbde (void)printf("%s", buf); 98171404Sdes free(buf); 98243962Sdillon} 98343962Sdillon 9841590Srgrimes/* 9851590Srgrimes * kread reads something from the kernel, given its nlist index. 9861590Srgrimes */ 987123250Sdesstatic void 988131300Sgreenkreado(int nlx, void *addr, size_t size, size_t offset) 9891590Srgrimes{ 990123825Sdwmalone const char *sym; 9911590Srgrimes 99240690Sjdp if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { 9931590Srgrimes sym = namelist[nlx].n_name; 9941590Srgrimes if (*sym == '_') 9951590Srgrimes ++sym; 99628693Scharnier errx(1, "symbol %s not defined", sym); 9971590Srgrimes } 998131300Sgreen if ((size_t)kvm_read(kd, namelist[nlx].n_value + offset, addr, 999131300Sgreen size) != size) { 10001590Srgrimes sym = namelist[nlx].n_name; 10011590Srgrimes if (*sym == '_') 10021590Srgrimes ++sym; 100328693Scharnier errx(1, "%s: %s", sym, kvm_geterr(kd)); 10041590Srgrimes } 10051590Srgrimes} 10061590Srgrimes 1007123250Sdesstatic void 1008131300Sgreenkread(int nlx, void *addr, size_t size) 1009131300Sgreen{ 1010131300Sgreen kreado(nlx, addr, size, 0); 1011131300Sgreen} 1012131300Sgreen 1013131300Sgreenstatic char * 1014131300Sgreenkgetstr(const char *strp) 1015131300Sgreen{ 1016131300Sgreen int n = 0, size = 1; 1017131300Sgreen char *ret = NULL; 1018131300Sgreen 1019131300Sgreen do { 1020131300Sgreen if (size == n + 1) { 1021131300Sgreen ret = realloc(ret, size); 1022131300Sgreen if (ret == NULL) 1023131300Sgreen err(1, "%s: realloc", __func__); 1024131300Sgreen size *= 2; 1025131300Sgreen } 1026131300Sgreen if (kvm_read(kd, (u_long)strp + n, &ret[n], 1) != 1) 1027131300Sgreen errx(1, "%s: %s", __func__, kvm_geterr(kd)); 1028131300Sgreen } while (ret[n++] != '\0'); 1029131300Sgreen return (ret); 1030131300Sgreen} 1031131300Sgreen 1032131300Sgreenstatic void 1033123250Sdesusage(void) 10341590Srgrimes{ 103572887Salfred (void)fprintf(stderr, "%s%s", 1036127452Sru "usage: vmstat [-aimsz] [-c count] [-M core [-N system]] [-w wait]\n", 103772887Salfred " [-n devs] [disks]\n"); 10381590Srgrimes exit(1); 10391590Srgrimes} 1040