vmstat.c revision 151417
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 151417 2005-10-17 15:37:22Z andre $"); 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> 70148413Srwatson#include <memstat.h> 711590Srgrimes#include <nlist.h> 7228693Scharnier#include <paths.h> 731590Srgrimes#include <stdio.h> 741590Srgrimes#include <stdlib.h> 751590Srgrimes#include <string.h> 7630180Sdima#include <sysexits.h> 7728693Scharnier#include <time.h> 7828693Scharnier#include <unistd.h> 791590Srgrimes 8087690Smarkmstatic char da[] = "da"; 8187690Smarkm 8287690Smarkmstatic struct nlist namelist[] = { 831590Srgrimes#define X_CPTIME 0 841590Srgrimes { "_cp_time" }, 8539230Sgibbs#define X_SUM 1 861590Srgrimes { "_cnt" }, 8739230Sgibbs#define X_BOOTTIME 2 881590Srgrimes { "_boottime" }, 8939230Sgibbs#define X_HZ 3 901590Srgrimes { "_hz" }, 9139230Sgibbs#define X_STATHZ 4 921590Srgrimes { "_stathz" }, 9339230Sgibbs#define X_NCHSTATS 5 941590Srgrimes { "_nchstats" }, 9539230Sgibbs#define X_INTRNAMES 6 961590Srgrimes { "_intrnames" }, 9739230Sgibbs#define X_EINTRNAMES 7 981590Srgrimes { "_eintrnames" }, 9939230Sgibbs#define X_INTRCNT 8 1001590Srgrimes { "_intrcnt" }, 10139230Sgibbs#define X_EINTRCNT 9 1021590Srgrimes { "_eintrcnt" }, 103131300Sgreen#define X_KMEMSTATS 10 104131300Sgreen { "_kmemstatistics" }, 105131300Sgreen#define X_KMEMZONES 11 106131300Sgreen { "_kmemzones" }, 10730180Sdima#ifdef notyet 108131300Sgreen#define X_DEFICIT XXX 1091590Srgrimes { "_deficit" }, 110131300Sgreen#define X_REC XXX 1111590Srgrimes { "_rectime" }, 112131300Sgreen#define X_PGIN XXX 1131590Srgrimes { "_pgintime" }, 114131300Sgreen#define X_XSTATS XXX 1151590Srgrimes { "_xstats" }, 116131300Sgreen#define X_END XXX 11792653Sjeff#else 118131300Sgreen#define X_END 12 1191590Srgrimes#endif 1201590Srgrimes { "" }, 1211590Srgrimes}; 1221590Srgrimes 123123250Sdesstatic struct statinfo cur, last; 124123250Sdesstatic int num_devices, maxshowdevs; 125123250Sdesstatic long generation; 126123250Sdesstatic struct device_selection *dev_select; 127123250Sdesstatic int num_selected; 128123250Sdesstatic struct devstat_match *matches; 129123250Sdesstatic int num_matches = 0; 130123250Sdesstatic int num_devices_specified, num_selections; 131123250Sdesstatic long select_generation; 132123250Sdesstatic char **specified_devices; 133123250Sdesstatic devstat_select_mode select_mode; 1341590Srgrimes 135123250Sdesstatic struct vmmeter sum, osum; 1361590Srgrimes 137123250Sdesstatic int winlines = 20; 138123250Sdesstatic int aflag; 139123250Sdesstatic int nflag; 1401590Srgrimes 141123250Sdesstatic kvm_t *kd; 1421590Srgrimes 1431590Srgrimes#define FORKSTAT 0x01 1441590Srgrimes#define INTRSTAT 0x02 1451590Srgrimes#define MEMSTAT 0x04 1461590Srgrimes#define SUMSTAT 0x08 1471590Srgrimes#define TIMESTAT 0x10 1481590Srgrimes#define VMSTAT 0x20 14943962Sdillon#define ZMEMSTAT 0x40 1501590Srgrimes 15192922Simpstatic void cpustats(void); 15292922Simpstatic void devstats(void); 153122300Sjmgstatic void doforkst(void); 15492922Simpstatic void dointr(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); 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) 303148790Srwatson domemstat_malloc(); 30443962Sdillon if (todo & ZMEMSTAT) 305148630Srwatson domemstat_zone(); 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{ 399151417Sandre struct timespec sp; 4001590Srgrimes time_t uptime; 4011590Srgrimes 402151417Sandre (void)clock_gettime(CLOCK_MONOTONIC, &sp); 403151417Sandre uptime = sp.tv_sec; 40428693Scharnier if (uptime <= 0 || uptime > 60*60*24*365*10) 40528693Scharnier errx(1, "time makes no sense; namelist must be wrong"); 406151417Sandre 4071590Srgrimes return(uptime); 4081590Srgrimes} 4091590Srgrimes 410123250Sdesstatic void 411123250Sdesfill_vmmeter(struct vmmeter *vmmp) 412123250Sdes{ 413123250Sdes if (kd != NULL) { 414123250Sdes kread(X_SUM, vmmp, sizeof(*vmmp)); 415123250Sdes } else { 416123250Sdes size_t size = sizeof(unsigned int); 417123250Sdes#define GET_VM_STATS(cat, name) \ 418123250Sdes mysysctl("vm.stats." #cat "." #name, &vmmp->name, &size, NULL, 0) 419123250Sdes /* sys */ 420123250Sdes GET_VM_STATS(sys, v_swtch); 421123250Sdes GET_VM_STATS(sys, v_trap); 422123250Sdes GET_VM_STATS(sys, v_syscall); 423123250Sdes GET_VM_STATS(sys, v_intr); 424123250Sdes GET_VM_STATS(sys, v_soft); 4251590Srgrimes 426123250Sdes /* vm */ 427123414Sdes GET_VM_STATS(vm, v_vm_faults); 428123414Sdes GET_VM_STATS(vm, v_cow_faults); 429123414Sdes GET_VM_STATS(vm, v_cow_optim); 430123414Sdes GET_VM_STATS(vm, v_zfod); 431123414Sdes GET_VM_STATS(vm, v_ozfod); 432123414Sdes GET_VM_STATS(vm, v_swapin); 433123414Sdes GET_VM_STATS(vm, v_swapout); 434123414Sdes GET_VM_STATS(vm, v_swappgsin); 435123414Sdes GET_VM_STATS(vm, v_swappgsout); 436123414Sdes GET_VM_STATS(vm, v_vnodein); 437123414Sdes GET_VM_STATS(vm, v_vnodeout); 438123414Sdes GET_VM_STATS(vm, v_vnodepgsin); 439123414Sdes GET_VM_STATS(vm, v_vnodepgsout); 440123414Sdes GET_VM_STATS(vm, v_intrans); 441123414Sdes GET_VM_STATS(vm, v_reactivated); 442123414Sdes GET_VM_STATS(vm, v_pdwakeups); 443123414Sdes GET_VM_STATS(vm, v_pdpages); 444123414Sdes GET_VM_STATS(vm, v_dfree); 445123414Sdes GET_VM_STATS(vm, v_pfree); 446123414Sdes GET_VM_STATS(vm, v_tfree); 447123414Sdes GET_VM_STATS(vm, v_page_size); 448123414Sdes GET_VM_STATS(vm, v_page_count); 449123414Sdes GET_VM_STATS(vm, v_free_reserved); 450123414Sdes GET_VM_STATS(vm, v_free_target); 451123414Sdes GET_VM_STATS(vm, v_free_min); 452123414Sdes GET_VM_STATS(vm, v_free_count); 453123414Sdes GET_VM_STATS(vm, v_wire_count); 454123414Sdes GET_VM_STATS(vm, v_active_count); 455123414Sdes GET_VM_STATS(vm, v_inactive_target); 456123414Sdes GET_VM_STATS(vm, v_inactive_count); 457123414Sdes GET_VM_STATS(vm, v_cache_count); 458123414Sdes GET_VM_STATS(vm, v_cache_min); 459123414Sdes GET_VM_STATS(vm, v_cache_max); 460123414Sdes GET_VM_STATS(vm, v_pageout_free_min); 461123414Sdes GET_VM_STATS(vm, v_interrupt_free_min); 462123414Sdes /*GET_VM_STATS(vm, v_free_severe);*/ 463123250Sdes GET_VM_STATS(vm, v_forks); 464123250Sdes GET_VM_STATS(vm, v_vforks); 465123250Sdes GET_VM_STATS(vm, v_rforks); 466123250Sdes GET_VM_STATS(vm, v_kthreads); 467123250Sdes GET_VM_STATS(vm, v_forkpages); 468123250Sdes GET_VM_STATS(vm, v_vforkpages); 469123250Sdes GET_VM_STATS(vm, v_rforkpages); 470123250Sdes GET_VM_STATS(vm, v_kthreadpages); 471123250Sdes#undef GET_VM_STATS 472123250Sdes } 473123250Sdes} 474123250Sdes 475123250Sdesstatic void 476123250Sdesfill_vmtotal(struct vmtotal *vmtp) 4771590Srgrimes{ 478123250Sdes if (kd != NULL) { 479123250Sdes /* XXX fill vmtp */ 480123250Sdes errx(1, "not implemented"); 481123250Sdes } else { 482123250Sdes size_t size = sizeof(*vmtp); 483123250Sdes mysysctl("vm.vmtotal", vmtp, &size, NULL, 0); 484123250Sdes if (size != sizeof(*vmtp)) 485123250Sdes errx(1, "vm.total size mismatch"); 486123250Sdes } 487123250Sdes} 488123250Sdes 489123250Sdesstatic int hz, hdrcnt; 490123250Sdes 491123250Sdesstatic void 492123407Sdesdovmstat(unsigned int interval, int reps) 493123250Sdes{ 4941590Srgrimes struct vmtotal total; 4951590Srgrimes time_t uptime, halfuptime; 49639230Sgibbs struct devinfo *tmp_dinfo; 49780551Stmm size_t size; 4981590Srgrimes 4991590Srgrimes uptime = getuptime(); 5001590Srgrimes halfuptime = uptime / 2; 5011590Srgrimes (void)signal(SIGCONT, needhdr); 5021590Srgrimes 503123250Sdes if (kd != NULL) { 504123250Sdes if (namelist[X_STATHZ].n_type != 0 && 505123250Sdes namelist[X_STATHZ].n_value != 0) 506123250Sdes kread(X_STATHZ, &hz, sizeof(hz)); 507123250Sdes if (!hz) 508123250Sdes kread(X_HZ, &hz, sizeof(hz)); 509123250Sdes } else { 510123250Sdes struct clockinfo clockrate; 5111590Srgrimes 512123250Sdes size = sizeof(clockrate); 513123250Sdes mysysctl("kern.clockrate", &clockrate, &size, NULL, 0); 514123250Sdes if (size != sizeof(clockrate)) 515123250Sdes errx(1, "clockrate size mismatch"); 516123250Sdes hz = clockrate.hz; 517123250Sdes } 518123250Sdes 5191590Srgrimes for (hdrcnt = 1;;) { 5201590Srgrimes if (!--hdrcnt) 5211590Srgrimes printhdr(); 522123250Sdes if (kd != NULL) { 523123250Sdes kread(X_CPTIME, cur.cp_time, sizeof(cur.cp_time)); 524123250Sdes } else { 525123250Sdes size = sizeof(cur.cp_time); 526123250Sdes mysysctl("kern.cp_time", &cur.cp_time, &size, NULL, 0); 527123250Sdes if (size != sizeof(cur.cp_time)) 528123250Sdes errx(1, "cp_time size mismatch"); 529123250Sdes } 53039230Sgibbs 53139230Sgibbs tmp_dinfo = last.dinfo; 53239230Sgibbs last.dinfo = cur.dinfo; 53339230Sgibbs cur.dinfo = tmp_dinfo; 534112288Sphk last.snap_time = cur.snap_time; 53539230Sgibbs 53639230Sgibbs /* 53739230Sgibbs * Here what we want to do is refresh our device stats. 53839230Sgibbs * getdevs() returns 1 when the device list has changed. 53939230Sgibbs * If the device list has changed, we want to go through 54039230Sgibbs * the selection process again, in case a device that we 54139230Sgibbs * were previously displaying has gone away. 54239230Sgibbs */ 543112284Sphk switch (devstat_getdevs(NULL, &cur)) { 54439230Sgibbs case -1: 54539230Sgibbs errx(1, "%s", devstat_errbuf); 54639230Sgibbs break; 54739230Sgibbs case 1: { 54839230Sgibbs int retval; 54939230Sgibbs 55039230Sgibbs num_devices = cur.dinfo->numdevs; 55139230Sgibbs generation = cur.dinfo->generation; 55239230Sgibbs 553112284Sphk retval = devstat_selectdevs(&dev_select, &num_selected, 55439230Sgibbs &num_selections, &select_generation, 55539230Sgibbs generation, cur.dinfo->devices, 55639230Sgibbs num_devices, matches, num_matches, 55739230Sgibbs specified_devices, 55839230Sgibbs num_devices_specified, select_mode, 55939230Sgibbs maxshowdevs, 0); 56039230Sgibbs switch (retval) { 56139230Sgibbs case -1: 56239230Sgibbs errx(1, "%s", devstat_errbuf); 56339230Sgibbs break; 56439230Sgibbs case 1: 56539230Sgibbs printhdr(); 56639230Sgibbs break; 56739230Sgibbs default: 56839230Sgibbs break; 56939230Sgibbs } 57039230Sgibbs } 57139230Sgibbs default: 57239230Sgibbs break; 57339230Sgibbs } 57439230Sgibbs 575123250Sdes fill_vmmeter(&sum); 576123250Sdes fill_vmtotal(&total); 57778672Sschweikh (void)printf("%2d %1d %1d", 5781590Srgrimes total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); 579142175Sps#define vmstat_pgtok(a) ((a) * (sum.v_page_size >> 10)) 5801590Srgrimes#define rate(x) (((x) + halfuptime) / uptime) /* round */ 58181537Sken (void)printf(" %7ld %6ld ", (long)vmstat_pgtok(total.t_avm), 58281537Sken (long)vmstat_pgtok(total.t_free)); 58337453Sbde (void)printf("%4lu ", 584123407Sdes (unsigned long)rate(sum.v_vm_faults - osum.v_vm_faults)); 5851590Srgrimes (void)printf("%3lu ", 586123407Sdes (unsigned long)rate(sum.v_reactivated - osum.v_reactivated)); 58737453Sbde (void)printf("%3lu ", 588123407Sdes (unsigned long)rate(sum.v_swapin + sum.v_vnodein - 5893659Sdg (osum.v_swapin + osum.v_vnodein))); 59037453Sbde (void)printf("%3lu ", 591123407Sdes (unsigned long)rate(sum.v_swapout + sum.v_vnodeout - 5923693Sdg (osum.v_swapout + osum.v_vnodeout))); 59337453Sbde (void)printf("%3lu ", 594123407Sdes (unsigned long)rate(sum.v_tfree - osum.v_tfree)); 59537453Sbde (void)printf("%3lu ", 596123407Sdes (unsigned long)rate(sum.v_pdpages - osum.v_pdpages)); 59739230Sgibbs devstats(); 5981590Srgrimes (void)printf("%4lu %4lu %3lu ", 599123407Sdes (unsigned long)rate(sum.v_intr - osum.v_intr), 600123407Sdes (unsigned long)rate(sum.v_syscall - osum.v_syscall), 601123407Sdes (unsigned long)rate(sum.v_swtch - osum.v_swtch)); 6021590Srgrimes cpustats(); 6031590Srgrimes (void)printf("\n"); 6041590Srgrimes (void)fflush(stdout); 6051590Srgrimes if (reps >= 0 && --reps <= 0) 6061590Srgrimes break; 6071590Srgrimes osum = sum; 6081590Srgrimes uptime = interval; 6091590Srgrimes /* 6101590Srgrimes * We round upward to avoid losing low-frequency events 6111590Srgrimes * (i.e., >= 1 per interval but < 1 per second). 6121590Srgrimes */ 6133659Sdg if (interval != 1) 6143659Sdg halfuptime = (uptime + 1) / 2; 6153659Sdg else 6163659Sdg halfuptime = 0; 6171590Srgrimes (void)sleep(interval); 6181590Srgrimes } 6191590Srgrimes} 6201590Srgrimes 621123250Sdesstatic void 622123250Sdesprinthdr(void) 6231590Srgrimes{ 62443822Sken int i, num_shown; 6251590Srgrimes 62643822Sken num_shown = (num_selected < maxshowdevs) ? num_selected : maxshowdevs; 62778672Sschweikh (void)printf(" procs memory page%*s", 19, ""); 62843822Sken if (num_shown > 1) 62943822Sken (void)printf(" disks %*s", num_shown * 4 - 7, ""); 63043822Sken else if (num_shown == 1) 63143822Sken (void)printf("disk"); 63243822Sken (void)printf(" faults cpu\n"); 63378672Sschweikh (void)printf(" r b w avm fre flt re pi po fr sr "); 63439230Sgibbs for (i = 0; i < num_devices; i++) 63539230Sgibbs if ((dev_select[i].selected) 63639230Sgibbs && (dev_select[i].selected <= maxshowdevs)) 63739230Sgibbs (void)printf("%c%c%d ", dev_select[i].device_name[0], 63839230Sgibbs dev_select[i].device_name[1], 63939230Sgibbs dev_select[i].unit_number); 6401590Srgrimes (void)printf(" in sy cs us sy id\n"); 6411590Srgrimes hdrcnt = winlines - 2; 6421590Srgrimes} 6431590Srgrimes 6441590Srgrimes/* 6451590Srgrimes * Force a header to be prepended to the next output. 6461590Srgrimes */ 647123250Sdesstatic void 648123250Sdesneedhdr(int dummy __unused) 6491590Srgrimes{ 6501590Srgrimes 6511590Srgrimes hdrcnt = 1; 6521590Srgrimes} 6531590Srgrimes 65430180Sdima#ifdef notyet 655123250Sdesstatic void 656123250Sdesdotimes(void) 6571590Srgrimes{ 658123407Sdes unsigned int pgintime, rectime; 6591590Srgrimes 6601590Srgrimes kread(X_REC, &rectime, sizeof(rectime)); 6611590Srgrimes kread(X_PGIN, &pgintime, sizeof(pgintime)); 6621590Srgrimes kread(X_SUM, &sum, sizeof(sum)); 6631590Srgrimes (void)printf("%u reclaims, %u total time (usec)\n", 6641590Srgrimes sum.v_pgrec, rectime); 6651590Srgrimes (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 6661590Srgrimes (void)printf("\n"); 6671590Srgrimes (void)printf("%u page ins, %u total time (msec)\n", 6681590Srgrimes sum.v_pgin, pgintime / 10); 6691590Srgrimes (void)printf("average: %8.1f msec / page in\n", 6701590Srgrimes pgintime / (sum.v_pgin * 10.0)); 6711590Srgrimes} 6721590Srgrimes#endif 6731590Srgrimes 674123250Sdesstatic long 675123250Sdespct(long top, long bot) 6761590Srgrimes{ 6771590Srgrimes long ans; 6781590Srgrimes 6791590Srgrimes if (bot == 0) 6801590Srgrimes return(0); 6811590Srgrimes ans = (quad_t)top * 100 / bot; 6821590Srgrimes return (ans); 6831590Srgrimes} 6841590Srgrimes 6851590Srgrimes#define PCT(top, bot) pct((long)(top), (long)(bot)) 6861590Srgrimes 687123250Sdesstatic void 688123250Sdesdosum(void) 6891590Srgrimes{ 69087690Smarkm struct nchstats lnchstats; 6911590Srgrimes long nchtotal; 6921590Srgrimes 693123250Sdes fill_vmmeter(&sum); 6941590Srgrimes (void)printf("%9u cpu context switches\n", sum.v_swtch); 6951590Srgrimes (void)printf("%9u device interrupts\n", sum.v_intr); 6961590Srgrimes (void)printf("%9u software interrupts\n", sum.v_soft); 6971590Srgrimes (void)printf("%9u traps\n", sum.v_trap); 6981590Srgrimes (void)printf("%9u system calls\n", sum.v_syscall); 69971429Sume (void)printf("%9u kernel threads created\n", sum.v_kthreads); 70071429Sume (void)printf("%9u fork() calls\n", sum.v_forks); 70171429Sume (void)printf("%9u vfork() calls\n", sum.v_vforks); 70271429Sume (void)printf("%9u rfork() calls\n", sum.v_rforks); 7033659Sdg (void)printf("%9u swap pager pageins\n", sum.v_swapin); 7043693Sdg (void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin); 7053659Sdg (void)printf("%9u swap pager pageouts\n", sum.v_swapout); 7063659Sdg (void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout); 7073659Sdg (void)printf("%9u vnode pager pageins\n", sum.v_vnodein); 7083693Sdg (void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin); 7093659Sdg (void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout); 7103659Sdg (void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout); 7113693Sdg (void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups); 7123693Sdg (void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages); 7131590Srgrimes (void)printf("%9u pages reactivated\n", sum.v_reactivated); 7147351Sdg (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 71534214Sdyson (void)printf("%9u copy-on-write optimized faults\n", sum.v_cow_optim); 7167351Sdg (void)printf("%9u zero fill pages zeroed\n", sum.v_zfod); 71734214Sdyson (void)printf("%9u zero fill pages prezeroed\n", sum.v_ozfod); 7181590Srgrimes (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 7191590Srgrimes (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 72071429Sume (void)printf("%9u pages affected by kernel thread creation\n", sum.v_kthreadpages); 72171429Sume (void)printf("%9u pages affected by fork()\n", sum.v_forkpages); 72271429Sume (void)printf("%9u pages affected by vfork()\n", sum.v_vforkpages); 72371429Sume (void)printf("%9u pages affected by rfork()\n", sum.v_rforkpages); 7243693Sdg (void)printf("%9u pages freed\n", sum.v_tfree); 7251590Srgrimes (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 7261590Srgrimes (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 7271590Srgrimes (void)printf("%9u pages active\n", sum.v_active_count); 7281590Srgrimes (void)printf("%9u pages inactive\n", sum.v_inactive_count); 7295463Sdg (void)printf("%9u pages in VM cache\n", sum.v_cache_count); 7303693Sdg (void)printf("%9u pages wired down\n", sum.v_wire_count); 7313693Sdg (void)printf("%9u pages free\n", sum.v_free_count); 7321590Srgrimes (void)printf("%9u bytes per page\n", sum.v_page_size); 733123250Sdes if (kd != NULL) { 734123250Sdes kread(X_NCHSTATS, &lnchstats, sizeof(lnchstats)); 735123250Sdes } else { 736123250Sdes size_t size = sizeof(lnchstats); 737123250Sdes mysysctl("vfs.cache.nchstats", &lnchstats, &size, NULL, 0); 738123250Sdes if (size != sizeof(lnchstats)) 739123250Sdes errx(1, "vfs.cache.nchstats size mismatch"); 740123250Sdes } 74187690Smarkm nchtotal = lnchstats.ncs_goodhits + lnchstats.ncs_neghits + 74287690Smarkm lnchstats.ncs_badhits + lnchstats.ncs_falsehits + 74387690Smarkm lnchstats.ncs_miss + lnchstats.ncs_long; 7441590Srgrimes (void)printf("%9ld total name lookups\n", nchtotal); 7451590Srgrimes (void)printf( 74628693Scharnier "%9s cache hits (%ld%% pos + %ld%% neg) system %ld%% per-directory\n", 74787690Smarkm "", PCT(lnchstats.ncs_goodhits, nchtotal), 74887690Smarkm PCT(lnchstats.ncs_neghits, nchtotal), 74987690Smarkm PCT(lnchstats.ncs_pass2, nchtotal)); 75028693Scharnier (void)printf("%9s deletions %ld%%, falsehits %ld%%, toolong %ld%%\n", "", 75187690Smarkm PCT(lnchstats.ncs_badhits, nchtotal), 75287690Smarkm PCT(lnchstats.ncs_falsehits, nchtotal), 75387690Smarkm PCT(lnchstats.ncs_long, nchtotal)); 7541590Srgrimes} 7551590Srgrimes 756123250Sdesstatic void 757123250Sdesdoforkst(void) 7581590Srgrimes{ 759123250Sdes fill_vmmeter(&sum); 760128573Stjr (void)printf("%u forks, %u pages, average %.2f\n", 761113460Stjr sum.v_forks, sum.v_forkpages, 762113460Stjr sum.v_forks == 0 ? 0.0 : 763113460Stjr (double)sum.v_forkpages / sum.v_forks); 764128573Stjr (void)printf("%u vforks, %u pages, average %.2f\n", 765113460Stjr sum.v_vforks, sum.v_vforkpages, 766113460Stjr sum.v_vforks == 0 ? 0.0 : 767113460Stjr (double)sum.v_vforkpages / sum.v_vforks); 768128573Stjr (void)printf("%u rforks, %u pages, average %.2f\n", 769113460Stjr sum.v_rforks, sum.v_rforkpages, 770113460Stjr sum.v_rforks == 0 ? 0.0 : 771113460Stjr (double)sum.v_rforkpages / sum.v_rforks); 7721590Srgrimes} 7731590Srgrimes 77439230Sgibbsstatic void 775123250Sdesdevstats(void) 7761590Srgrimes{ 77787690Smarkm int dn, state; 77839230Sgibbs long double transfers_per_second; 77939230Sgibbs long double busy_seconds; 7801590Srgrimes long tmp; 781123250Sdes 7821590Srgrimes for (state = 0; state < CPUSTATES; ++state) { 78339230Sgibbs tmp = cur.cp_time[state]; 78439230Sgibbs cur.cp_time[state] -= last.cp_time[state]; 78539230Sgibbs last.cp_time[state] = tmp; 7861590Srgrimes } 78739230Sgibbs 788112288Sphk busy_seconds = cur.snap_time - last.snap_time; 78939230Sgibbs 79039230Sgibbs for (dn = 0; dn < num_devices; dn++) { 79139230Sgibbs int di; 79239230Sgibbs 79339230Sgibbs if ((dev_select[dn].selected == 0) 79439230Sgibbs || (dev_select[dn].selected > maxshowdevs)) 7951590Srgrimes continue; 79639230Sgibbs 79739230Sgibbs di = dev_select[dn].position; 79839230Sgibbs 79981537Sken if (devstat_compute_statistics(&cur.dinfo->devices[di], 80081537Sken &last.dinfo->devices[di], busy_seconds, 80181537Sken DSM_TRANSFERS_PER_SECOND, &transfers_per_second, 80281537Sken DSM_NONE) != 0) 80339230Sgibbs errx(1, "%s", devstat_errbuf); 80439230Sgibbs 80581537Sken (void)printf("%3.0Lf ", transfers_per_second); 8061590Srgrimes } 8071590Srgrimes} 8081590Srgrimes 809123250Sdesstatic void 810123250Sdescpustats(void) 8111590Srgrimes{ 81287690Smarkm int state; 81387690Smarkm double lpct, total; 8141590Srgrimes 8151590Srgrimes total = 0; 8161590Srgrimes for (state = 0; state < CPUSTATES; ++state) 81739230Sgibbs total += cur.cp_time[state]; 8181590Srgrimes if (total) 81987690Smarkm lpct = 100.0 / total; 8201590Srgrimes else 82187690Smarkm lpct = 0.0; 82239230Sgibbs (void)printf("%2.0f ", (cur.cp_time[CP_USER] + 82387690Smarkm cur.cp_time[CP_NICE]) * lpct); 82439230Sgibbs (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + 82587690Smarkm cur.cp_time[CP_INTR]) * lpct); 82687690Smarkm (void)printf("%2.0f", cur.cp_time[CP_IDLE] * lpct); 8271590Srgrimes} 8281590Srgrimes 829123250Sdesstatic void 830123250Sdesdointr(void) 8311590Srgrimes{ 832123407Sdes unsigned long *intrcnt, uptime; 833123409Sdes uint64_t inttotal; 834123409Sdes size_t clen, inamlen, intrcntlen, istrnamlen; 835123409Sdes unsigned int i, nintr; 836121626Sjmg char *intrname, *tintrname; 8371590Srgrimes 8381590Srgrimes uptime = getuptime(); 839123250Sdes if (kd != NULL) { 840123409Sdes intrcntlen = namelist[X_EINTRCNT].n_value - 841123250Sdes namelist[X_INTRCNT].n_value; 842123250Sdes inamlen = namelist[X_EINTRNAMES].n_value - 843123250Sdes namelist[X_INTRNAMES].n_value; 844123409Sdes if ((intrcnt = malloc(intrcntlen)) == NULL || 845123290Smarcel (intrname = malloc(inamlen)) == NULL) 846123250Sdes err(1, "malloc()"); 847123409Sdes kread(X_INTRCNT, intrcnt, intrcntlen); 848123290Smarcel kread(X_INTRNAMES, intrname, inamlen); 849123250Sdes } else { 850123438Sdes for (intrcnt = NULL, intrcntlen = 1024; ; intrcntlen *= 2) { 851123438Sdes if ((intrcnt = reallocf(intrcnt, intrcntlen)) == NULL) 852123438Sdes err(1, "reallocf()"); 853123438Sdes if (mysysctl("hw.intrcnt", 854123438Sdes intrcnt, &intrcntlen, NULL, 0) == 0) 855123438Sdes break; 856123438Sdes } 857123250Sdes for (intrname = NULL, inamlen = 1024; ; inamlen *= 2) { 858123250Sdes if ((intrname = reallocf(intrname, inamlen)) == NULL) 859123250Sdes err(1, "reallocf()"); 860123250Sdes if (mysysctl("hw.intrnames", 861123250Sdes intrname, &inamlen, NULL, 0) == 0) 862123250Sdes break; 863123250Sdes } 864123250Sdes } 865123409Sdes nintr = intrcntlen / sizeof(unsigned long); 866121626Sjmg tintrname = intrname; 867122365Sjmg istrnamlen = strlen("interrupt"); 868121626Sjmg for (i = 0; i < nintr; i++) { 869121626Sjmg clen = strlen(tintrname); 870121626Sjmg if (clen > istrnamlen) 871121626Sjmg istrnamlen = clen; 872121626Sjmg tintrname += clen + 1; 873121626Sjmg } 874121626Sjmg (void)printf("%-*s %20s %10s\n", istrnamlen, "interrupt", "total", 875121626Sjmg "rate"); 8761590Srgrimes inttotal = 0; 877123290Smarcel for (i = 0; i < nintr; i++) { 878123409Sdes if (intrname[0] != '\0' && (*intrcnt != 0 || aflag)) 879121626Sjmg (void)printf("%-*s %20lu %10lu\n", istrnamlen, intrname, 8801590Srgrimes *intrcnt, *intrcnt / uptime); 8811590Srgrimes intrname += strlen(intrname) + 1; 8821590Srgrimes inttotal += *intrcnt++; 8831590Srgrimes } 884123290Smarcel (void)printf("%-*s %20llu %10llu\n", istrnamlen, "Total", 885123290Smarcel (long long)inttotal, (long long)(inttotal / uptime)); 8861590Srgrimes} 8871590Srgrimes 888148413Srwatsonstatic void 889148413Srwatsondomemstat_malloc(void) 890148413Srwatson{ 891148413Srwatson struct memory_type_list *mtlp; 892148413Srwatson struct memory_type *mtp; 893148790Srwatson int error, first, i; 894148413Srwatson 895148413Srwatson mtlp = memstat_mtl_alloc(); 896148413Srwatson if (mtlp == NULL) { 897148413Srwatson warn("memstat_mtl_alloc"); 898148413Srwatson return; 899148413Srwatson } 900148790Srwatson if (kd == NULL) { 901148790Srwatson if (memstat_sysctl_malloc(mtlp, 0) < 0) { 902148790Srwatson warnx("memstat_sysctl_malloc: %s", 903148790Srwatson memstat_strerror(memstat_mtl_geterror(mtlp))); 904148790Srwatson return; 905148790Srwatson } 906148790Srwatson } else { 907148790Srwatson if (memstat_kvm_malloc(mtlp, kd) < 0) { 908148790Srwatson error = memstat_mtl_geterror(mtlp); 909148790Srwatson if (error == MEMSTAT_ERROR_KVM) 910148790Srwatson warnx("memstat_kvm_malloc: %s", 911148790Srwatson kvm_geterr(kd)); 912148790Srwatson else 913148790Srwatson warnx("memstat_kvm_malloc: %s", 914148790Srwatson memstat_strerror(error)); 915148790Srwatson } 916148413Srwatson } 917148413Srwatson printf("%13s %5s %6s %7s %8s Size(s)\n", "Type", "InUse", "MemUse", 918148413Srwatson "HighUse", "Requests"); 919148413Srwatson for (mtp = memstat_mtl_first(mtlp); mtp != NULL; 920148413Srwatson mtp = memstat_mtl_next(mtp)) { 921148413Srwatson if (memstat_get_numallocs(mtp) == 0 && 922148413Srwatson memstat_get_count(mtp) == 0) 923148413Srwatson continue; 924148413Srwatson printf("%13s %5lld %5lldK %7s %8lld ", 925148413Srwatson memstat_get_name(mtp), memstat_get_count(mtp), 926148413Srwatson ((int64_t)memstat_get_bytes(mtp) + 1023) / 1024, "-", 927148413Srwatson memstat_get_numallocs(mtp)); 928148413Srwatson first = 1; 929148413Srwatson for (i = 0; i < 32; i++) { 930148413Srwatson if (memstat_get_sizemask(mtp) & (1 << i)) { 931148413Srwatson if (!first) 932148413Srwatson printf(","); 933148413Srwatson printf("%d", 1 << (i + 4)); 934148413Srwatson first = 0; 935148413Srwatson } 936148413Srwatson } 937148413Srwatson printf("\n"); 938148413Srwatson } 939148413Srwatson memstat_mtl_free(mtlp); 940148413Srwatson} 941148413Srwatson 942148413Srwatsonstatic void 943148413Srwatsondomemstat_zone(void) 944148413Srwatson{ 945148413Srwatson struct memory_type_list *mtlp; 946148413Srwatson struct memory_type *mtp; 947148413Srwatson char name[MEMTYPE_MAXNAME + 1]; 948148630Srwatson int error; 949148413Srwatson 950148413Srwatson mtlp = memstat_mtl_alloc(); 951148413Srwatson if (mtlp == NULL) { 952148413Srwatson warn("memstat_mtl_alloc"); 953148413Srwatson return; 954148413Srwatson } 955148630Srwatson if (kd == NULL) { 956148630Srwatson if (memstat_sysctl_uma(mtlp, 0) < 0) { 957148630Srwatson warnx("memstat_sysctl_uma: %s", 958148630Srwatson memstat_strerror(memstat_mtl_geterror(mtlp))); 959148630Srwatson return; 960148630Srwatson } 961148630Srwatson } else { 962148630Srwatson if (memstat_kvm_uma(mtlp, kd) < 0) { 963148630Srwatson error = memstat_mtl_geterror(mtlp); 964148630Srwatson if (error == MEMSTAT_ERROR_KVM) 965148630Srwatson warnx("memstat_kvm_uma: %s", 966148630Srwatson kvm_geterr(kd)); 967148630Srwatson else 968148630Srwatson warnx("memstat_kvm_uma: %s", 969148630Srwatson memstat_strerror(error)); 970148630Srwatson } 971148413Srwatson } 972148413Srwatson printf("%-15s %-8s %-9s %-7s %-5s %-8s\n\n", "ITEM", "SIZE", "LIMIT", 973148413Srwatson "USED", "FREE", "REQUESTS"); 974148413Srwatson for (mtp = memstat_mtl_first(mtlp); mtp != NULL; 975148413Srwatson mtp = memstat_mtl_next(mtp)) { 976148413Srwatson strlcpy(name, memstat_get_name(mtp), MEMTYPE_MAXNAME); 977148413Srwatson strcat(name, ":"); 978148413Srwatson printf("%-15s %4llu, %8llu, %7llu, %6llu, %8llu\n", name, 979148413Srwatson memstat_get_size(mtp), memstat_get_countlimit(mtp), 980148413Srwatson memstat_get_count(mtp), memstat_get_free(mtp), 981148413Srwatson memstat_get_numallocs(mtp)); 982148413Srwatson } 983148413Srwatson memstat_mtl_free(mtlp); 984148413Srwatson printf("\n"); 985148413Srwatson} 986148413Srwatson 987148413Srwatson/* 9881590Srgrimes * kread reads something from the kernel, given its nlist index. 9891590Srgrimes */ 990123250Sdesstatic void 991131300Sgreenkreado(int nlx, void *addr, size_t size, size_t offset) 9921590Srgrimes{ 993123825Sdwmalone const char *sym; 9941590Srgrimes 99540690Sjdp if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { 9961590Srgrimes sym = namelist[nlx].n_name; 9971590Srgrimes if (*sym == '_') 9981590Srgrimes ++sym; 99928693Scharnier errx(1, "symbol %s not defined", sym); 10001590Srgrimes } 1001131300Sgreen if ((size_t)kvm_read(kd, namelist[nlx].n_value + offset, addr, 1002131300Sgreen size) != size) { 10031590Srgrimes sym = namelist[nlx].n_name; 10041590Srgrimes if (*sym == '_') 10051590Srgrimes ++sym; 100628693Scharnier errx(1, "%s: %s", sym, kvm_geterr(kd)); 10071590Srgrimes } 10081590Srgrimes} 10091590Srgrimes 1010123250Sdesstatic void 1011131300Sgreenkread(int nlx, void *addr, size_t size) 1012131300Sgreen{ 1013131300Sgreen kreado(nlx, addr, size, 0); 1014131300Sgreen} 1015131300Sgreen 1016131300Sgreenstatic char * 1017131300Sgreenkgetstr(const char *strp) 1018131300Sgreen{ 1019131300Sgreen int n = 0, size = 1; 1020131300Sgreen char *ret = NULL; 1021131300Sgreen 1022131300Sgreen do { 1023131300Sgreen if (size == n + 1) { 1024131300Sgreen ret = realloc(ret, size); 1025131300Sgreen if (ret == NULL) 1026131300Sgreen err(1, "%s: realloc", __func__); 1027131300Sgreen size *= 2; 1028131300Sgreen } 1029131300Sgreen if (kvm_read(kd, (u_long)strp + n, &ret[n], 1) != 1) 1030131300Sgreen errx(1, "%s: %s", __func__, kvm_geterr(kd)); 1031131300Sgreen } while (ret[n++] != '\0'); 1032131300Sgreen return (ret); 1033131300Sgreen} 1034131300Sgreen 1035131300Sgreenstatic void 1036123250Sdesusage(void) 10371590Srgrimes{ 103872887Salfred (void)fprintf(stderr, "%s%s", 1039146466Sru "usage: vmstat [-afimsz] [-c count] [-M core [-N system]] [-w wait]\n", 1040146466Sru " [-n devs] [-p type,if,pass] [disks]\n"); 10411590Srgrimes exit(1); 10421590Srgrimes} 1043