vmstat.c revision 92922
19313Ssos/* 29313Ssos * Copyright (c) 1980, 1986, 1991, 1993 39313Ssos * The Regents of the University of California. All rights reserved. 49313Ssos * 59313Ssos * Redistribution and use in source and binary forms, with or without 69313Ssos * modification, are permitted provided that the following conditions 79313Ssos * are met: 89313Ssos * 1. Redistributions of source code must retain the above copyright 99313Ssos * notice, this list of conditions and the following disclaimer. 109313Ssos * 2. Redistributions in binary form must reproduce the above copyright 119313Ssos * notice, this list of conditions and the following disclaimer in the 129313Ssos * documentation and/or other materials provided with the distribution. 139313Ssos * 3. All advertising materials mentioning features or use of this software 149313Ssos * must display the following acknowledgement: 1597748Sschweikh * This product includes software developed by the University of 169313Ssos * California, Berkeley and its contributors. 179313Ssos * 4. Neither the name of the University nor the names of its contributors 189313Ssos * may be used to endorse or promote products derived from this software 199313Ssos * without specific prior written permission. 209313Ssos * 219313Ssos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 229313Ssos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239313Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249313Ssos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 259313Ssos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269313Ssos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279313Ssos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289313Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29116173Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30141829Snjl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31116173Sobrien * SUCH DAMAGE. 329313Ssos */ 339313Ssos 3476166Smarkm#include <sys/cdefs.h> 3576166Smarkm 36161461Snetchild__FBSDID("$FreeBSD: head/usr.bin/vmstat/vmstat.c 92922 2002-03-22 01:42:45Z imp $"); 379313Ssos 389313Ssos#ifndef lint 39102814Siedowsestatic const char copyright[] = 4076166Smarkm"@(#) Copyright (c) 1980, 1986, 1991, 1993\n\ 419313Ssos The Regents of the University of California. All rights reserved.\n"; 42184058Skib#endif 43184058Skib 44156874Sru#ifndef lint 45156874Srustatic const char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93"; 46140214Sobrien#endif 47140214Sobrien 48140214Sobrien#include <sys/param.h> 49140214Sobrien#include <sys/time.h> 5064911Smarcel#include <sys/proc.h> 5168583Smarcel#include <sys/dkstat.h> 52133816Stjr#include <sys/uio.h> 5364911Smarcel#include <sys/namei.h> 5464911Smarcel#include <sys/malloc.h> 55161310Snetchild#include <sys/signal.h> 569313Ssos#include <sys/fcntl.h> 5764911Smarcel#include <sys/ioctl.h> 5883221Smarcel#include <sys/sysctl.h> 5951793Smarcel#include <sys/vmmeter.h> 6051793Smarcel 619313Ssos#include <vm/vm_param.h> 6251793Smarcel 6351793Smarcel#include <ctype.h> 6451793Smarcel#include <devstat.h> 6551793Smarcel#include <err.h> 6651793Smarcel#include <errno.h> 6751793Smarcel#include <kvm.h> 6851793Smarcel#include <limits.h> 6951793Smarcel#include <nlist.h> 7051793Smarcel#include <paths.h> 7114331Speter#include <stdio.h> 729313Ssos#include <stdlib.h> 739313Ssos#include <string.h> 7467234Sgallatin#include <sysexits.h> 7583221Smarcel#include <time.h> 7651793Smarcel#include <unistd.h> 7751793Smarcel 789313Ssosstatic char da[] = "da"; 7951793Smarcel 8051793Smarcelstatic struct nlist namelist[] = { 8151793Smarcel#define X_CPTIME 0 8251793Smarcel { "_cp_time" }, 8351793Smarcel#define X_SUM 1 8451793Smarcel { "_cnt" }, 8551793Smarcel#define X_BOOTTIME 2 8651793Smarcel { "_boottime" }, 8751793Smarcel#define X_HZ 3 8814331Speter { "_hz" }, 899313Ssos#define X_STATHZ 4 909313Ssos { "_stathz" }, 9114342Speter#define X_NCHSTATS 5 9283221Smarcel { "_nchstats" }, 9314331Speter#define X_INTRNAMES 6 9451793Smarcel { "_intrnames" }, 9551793Smarcel#define X_EINTRNAMES 7 96133816Stjr { "_eintrnames" }, 9751793Smarcel#define X_INTRCNT 8 9851793Smarcel { "_intrcnt" }, 9951793Smarcel#define X_EINTRCNT 9 10051793Smarcel { "_eintrcnt" }, 10151793Smarcel#define X_KMEMSTATISTICS 10 10251793Smarcel { "_kmemstatistics" }, 10351793Smarcel#ifdef notyet 10451793Smarcel#define X_DEFICIT 12 10551793Smarcel { "_deficit" }, 10651793Smarcel#define X_FORKSTAT 13 10751793Smarcel { "_forkstat" }, 10851793Smarcel#define X_REC 14 10951793Smarcel { "_rectime" }, 11051793Smarcel#define X_PGIN 15 11151793Smarcel { "_pgintime" }, 11214331Speter#define X_XSTATS 16 1139313Ssos { "_xstats" }, 11414342Speter#define X_END 17 11583221Smarcel#else 11614331Speter#define X_END 18 11751793Smarcel#endif 11851793Smarcel { "" }, 119140214Sobrien}; 120133816Stjr 121133816Stjrstruct statinfo cur, last; 12251793Smarcelint num_devices, maxshowdevs; 123133816Stjrlong generation; 124133816Stjrstruct device_selection *dev_select; 12551793Smarcelint num_selected; 12651793Smarcelstruct devstat_match *matches; 12751793Smarcelint num_matches = 0; 12851793Smarcelint num_devices_specified, num_selections; 12951793Smarcellong select_generation; 13051793Smarcelchar **specified_devices; 13151793Smarceldevstat_select_mode select_mode; 13251793Smarcel 13351793Smarcelstruct vmmeter sum, osum; 13451793Smarcel 13551793Smarcelint winlines = 20; 13651793Smarcelint nflag = 0; 13751793Smarcel 13851793Smarcelkvm_t *kd; 13951793Smarcel 14014331Speter#define FORKSTAT 0x01 14114331Speter#define INTRSTAT 0x02 14264911Smarcel#define MEMSTAT 0x04 14383366Sjulian#define SUMSTAT 0x08 14483221Smarcel#define TIMESTAT 0x10 14549786Smarcel#define VMSTAT 0x20 146102814Siedowse#define ZMEMSTAT 0x40 147102814Siedowse 14849786Smarcelstatic void cpustats(void); 149163369Snetchildstatic void devstats(void); 15051793Smarcelstatic void domem(void); 15149786Smarcelstatic void dointr(void); 152102814Siedowsestatic void dosum(void); 15351793Smarcelstatic void dovmstat(u_int, int); 154102814Siedowsestatic void dozmem(void); 15553954Smarcelstatic void kread(int, void *, size_t); 156102814Siedowsestatic void needhdr(int); 15751793Smarcelstatic void printhdr(void); 15849786Smarcelstatic void usage(void); 15951793Smarcel 160102814Siedowsestatic long pct(long, long); 16151793Smarcelstatic long getuptime(void); 162102814Siedowse 16349786Smarcelchar **getdrivedata(char **); 164102814Siedowse 16549786Smarcelint 16651793Smarcelmain(argc, argv) 16749786Smarcel int argc; 16853954Smarcel char **argv; 16953954Smarcel{ 17051793Smarcel int c, todo; 17151793Smarcel u_int interval; 17249786Smarcel int reps; 17349786Smarcel char *memf, *nlistf; 17468201Sobrien char errbuf[_POSIX2_LINE_MAX]; 1759313Ssos 17683366Sjulian memf = nlistf = NULL; 17714331Speter interval = reps = todo = 0; 17883221Smarcel maxshowdevs = 2; 17951793Smarcel while ((c = getopt(argc, argv, "c:fiM:mN:n:p:stw:z")) != -1) { 1809313Ssos switch (c) { 18114331Speter case 'c': 18272543Sjlemon reps = atoi(optarg); 18372543Sjlemon break; 184133850Sobrien case 'f': 18514331Speter errx(EX_USAGE, "sorry, -f is not (re)implemented yet"); 18649786Smarcel break; 18751793Smarcel case 'i': 18851793Smarcel todo |= INTRSTAT; 18951793Smarcel break; 19049786Smarcel case 'M': 19183366Sjulian memf = optarg; 192133816Stjr break; 19349786Smarcel case 'm': 19451793Smarcel todo |= MEMSTAT; 19549786Smarcel break; 19649786Smarcel case 'N': 19749786Smarcel nlistf = optarg; 19883366Sjulian break; 19949786Smarcel case 'n': 20083221Smarcel nflag = 1; 20151793Smarcel maxshowdevs = atoi(optarg); 20249786Smarcel if (maxshowdevs < 0) 20349786Smarcel errx(1, "number of devices %d is < 0", 20472543Sjlemon maxshowdevs); 20572543Sjlemon break; 20672543Sjlemon case 'p': 20772543Sjlemon if (buildmatch(optarg, &matches, &num_matches) != 0) 20849786Smarcel errx(1, "%s", devstat_errbuf); 20949786Smarcel break; 21083221Smarcel case 's': 21151793Smarcel todo |= SUMSTAT; 21214331Speter break; 21351793Smarcel case 't': 21483221Smarcel#ifdef notyet 21551793Smarcel todo |= TIMESTAT; 21651793Smarcel#else 21751793Smarcel errx(EX_USAGE, "sorry, -t is not (re)implemented yet"); 21814331Speter#endif 21983366Sjulian break; 22051793Smarcel case 'w': 22151793Smarcel interval = atoi(optarg); 22214331Speter break; 22351793Smarcel case 'z': 22483221Smarcel todo |= ZMEMSTAT; 22551793Smarcel break; 22649786Smarcel case '?': 22751793Smarcel default: 22814331Speter usage(); 22914331Speter } 23049786Smarcel } 23183366Sjulian argc -= optind; 23283221Smarcel argv += optind; 23349786Smarcel 234113859Sjhb if (todo == 0) 235113859Sjhb todo = VMSTAT; 23670061Sjhb 23714331Speter /* 23883366Sjulian * Discard setgid privileges if not the running kernel so that bad 23949786Smarcel * guys can't print interesting stuff from kernel memory. 240114023Sjhb */ 241114023Sjhb if (nlistf != NULL || memf != NULL) 242114023Sjhb setgid(getgid()); 243114023Sjhb 244114023Sjhb kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); 245114023Sjhb if (kd == 0) 246114023Sjhb errx(1, "kvm_openfiles: %s", errbuf); 247114023Sjhb setgid(getgid()); 248114023Sjhb 249114023Sjhb if ((c = kvm_nlist(kd, namelist)) != 0) { 250114023Sjhb if (c > 0) { 251114023Sjhb warnx("undefined symbols:"); 252114023Sjhb for (c = 0; 25351793Smarcel c < (int)(sizeof(namelist)/sizeof(namelist[0])); 254113859Sjhb c++) 255113859Sjhb if (namelist[c].n_type == 0) 256113859Sjhb (void)fprintf(stderr, " %s", 257113859Sjhb namelist[c].n_name); 258114023Sjhb (void)fputc('\n', stderr); 259114174Sjhb } else 260113859Sjhb warnx("kvm_nlist: %s", kvm_geterr(kd)); 26149786Smarcel exit(1); 26251793Smarcel } 26349786Smarcel 26449786Smarcel if (todo & VMSTAT) { 2659313Ssos struct winsize winsize; 26683366Sjulian 2679313Ssos /* 26883221Smarcel * Make sure that the userland devstat version matches the 26983221Smarcel * kernel devstat version. If not, exit and print a 27051793Smarcel * message informing the user of his mistake. 2719313Ssos */ 2729313Ssos if (checkversion() < 0) 27372543Sjlemon errx(1, "%s", devstat_errbuf); 27472543Sjlemon 2759313Ssos 27614331Speter argv = getdrivedata(argv); 27751793Smarcel winsize.ws_row = 0; 27883221Smarcel (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 27951793Smarcel if (winsize.ws_row > 0) 28051793Smarcel winlines = winsize.ws_row; 28151793Smarcel 28251793Smarcel } 28351793Smarcel 28414331Speter#define BACKWARD_COMPATIBILITY 28583366Sjulian#ifdef BACKWARD_COMPATIBILITY 28651793Smarcel if (*argv) { 28751793Smarcel interval = atoi(*argv); 28849786Smarcel if (*++argv) 28951793Smarcel reps = atoi(*argv); 29051793Smarcel } 29183221Smarcel#endif 29251793Smarcel 29349786Smarcel if (interval) { 29451793Smarcel if (!reps) 29549786Smarcel reps = -1; 29649786Smarcel } else if (reps) 29749786Smarcel interval = 1; 29883366Sjulian 29949786Smarcel#ifdef notyet 30083221Smarcel if (todo & FORKSTAT) 30151793Smarcel doforkst(); 30249786Smarcel#endif 30349786Smarcel if (todo & MEMSTAT) 30472543Sjlemon domem(); 30572543Sjlemon if (todo & ZMEMSTAT) 30672543Sjlemon dozmem(); 30772543Sjlemon if (todo & SUMSTAT) 30849786Smarcel dosum(); 30949786Smarcel#ifdef notyet 31083221Smarcel if (todo & TIMESTAT) 31151793Smarcel dotimes(); 31249786Smarcel#endif 31351793Smarcel if (todo & INTRSTAT) 31483221Smarcel dointr(); 31551793Smarcel if (todo & VMSTAT) 31651793Smarcel dovmstat(interval, reps); 31751793Smarcel exit(0); 31849786Smarcel} 31983366Sjulian 32051793Smarcelchar ** 32151793Smarcelgetdrivedata(argv) 3229313Ssos char **argv; 32351793Smarcel{ 32483221Smarcel if ((num_devices = getnumdevs()) < 0) 32551793Smarcel errx(1, "%s", devstat_errbuf); 32649786Smarcel 32751793Smarcel cur.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); 3289313Ssos last.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); 3299313Ssos bzero(cur.dinfo, sizeof(struct devinfo)); 3309313Ssos bzero(last.dinfo, sizeof(struct devinfo)); 33183366Sjulian 3329313Ssos if (getdevs(&cur) == -1) 33383366Sjulian errx(1, "%s", devstat_errbuf); 33483221Smarcel 33551793Smarcel num_devices = cur.dinfo->numdevs; 3369313Ssos generation = cur.dinfo->generation; 33783221Smarcel 33883221Smarcel specified_devices = (char **)malloc(sizeof(char *)); 3399313Ssos for (num_devices_specified = 0; *argv; ++argv) { 34051793Smarcel if (isdigit(**argv)) 34170061Sjhb break; 342112888Sjeff num_devices_specified++; 34370061Sjhb specified_devices = (char **)realloc(specified_devices, 34483366Sjulian sizeof(char *) * 34551793Smarcel num_devices_specified); 3469313Ssos specified_devices[num_devices_specified - 1] = *argv; 3479313Ssos } 3489313Ssos dev_select = NULL; 34983366Sjulian 3509313Ssos if (nflag == 0 && maxshowdevs < num_devices_specified) 35183366Sjulian maxshowdevs = num_devices_specified; 35283221Smarcel 35351793Smarcel /* 3549313Ssos * People are generally only interested in disk statistics when 3559313Ssos * they're running vmstat. So, that's what we're going to give 35683221Smarcel * them if they don't specify anything by default. We'll also give 35783221Smarcel * them any other random devices in the system so that we get to 3589313Ssos * maxshowdevs devices, if that many devices exist. If the user 35914331Speter * specifies devices on the command line, either through a pattern 36070061Sjhb * match or by naming them explicitly, we will give the user only 361112888Sjeff * those devices. 36283366Sjulian */ 36351793Smarcel if ((num_devices_specified == 0) && (num_matches == 0)) { 36451793Smarcel if (buildmatch(da, &matches, &num_matches) != 0) 36551793Smarcel errx(1, "%s", devstat_errbuf); 366112888Sjeff 367112888Sjeff select_mode = DS_SELECT_ADD; 368112888Sjeff } else 36970061Sjhb select_mode = DS_SELECT_ONLY; 37051793Smarcel 3719313Ssos /* 3729313Ssos * At this point, selectdevs will almost surely indicate that the 373110980Stjr * device list has changed, so we don't look for return values of 0 374110980Stjr * or 1. If we get back -1, though, there is an error. 375110980Stjr */ 3769313Ssos if (selectdevs(&dev_select, &num_selected, &num_selections, 37783366Sjulian &select_generation, generation, cur.dinfo->devices, 3789313Ssos num_devices, matches, num_matches, specified_devices, 37983366Sjulian num_devices_specified, select_mode, 38051793Smarcel maxshowdevs, 0) == -1) 38183221Smarcel errx(1, "%s", devstat_errbuf); 38283221Smarcel 3839313Ssos return(argv); 3849313Ssos} 38572543Sjlemon 38672543Sjlemonlong 3879313Ssosgetuptime() 38851793Smarcel{ 38970061Sjhb static time_t now, boottime; 390104306Sjmallett time_t uptime; 391112888Sjeff 392112888Sjeff if (boottime == 0) 393113615Sjhb kread(X_BOOTTIME, &boottime, sizeof(boottime)); 39451793Smarcel (void)time(&now); 39551793Smarcel uptime = now - boottime; 39651793Smarcel if (uptime <= 0 || uptime > 60*60*24*365*10) 3979313Ssos errx(1, "time makes no sense; namelist must be wrong"); 398158406Snetchild return(uptime); 399158406Snetchild} 400158406Snetchild 401158406Snetchildint hz, hdrcnt; 402158406Snetchild 403158406Snetchildvoid 404158406Snetchilddovmstat(interval, reps) 405158406Snetchild u_int interval; 406158406Snetchild int reps; 407158406Snetchild{ 408158406Snetchild struct vmtotal total; 409158406Snetchild time_t uptime, halfuptime; 410158406Snetchild struct devinfo *tmp_dinfo; 411158406Snetchild int mib[2]; 412158406Snetchild size_t size; 413158406Snetchild 414158406Snetchild uptime = getuptime(); 415158406Snetchild halfuptime = uptime / 2; 416158406Snetchild (void)signal(SIGCONT, needhdr); 417158406Snetchild 418158406Snetchild if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0) 419158406Snetchild kread(X_STATHZ, &hz, sizeof(hz)); 420158406Snetchild if (!hz) 421158406Snetchild kread(X_HZ, &hz, sizeof(hz)); 422158406Snetchild 423158406Snetchild for (hdrcnt = 1;;) { 424158406Snetchild if (!--hdrcnt) 425158406Snetchild printhdr(); 4269313Ssos kread(X_CPTIME, cur.cp_time, sizeof(cur.cp_time)); 427165689Snetchild 428165689Snetchild tmp_dinfo = last.dinfo; 429165689Snetchild last.dinfo = cur.dinfo; 4309313Ssos cur.dinfo = tmp_dinfo; 431165689Snetchild last.busy_time = cur.busy_time; 432165689Snetchild 433165689Snetchild /* 434218719Sdchagin * Here what we want to do is refresh our device stats. 435165689Snetchild * getdevs() returns 1 when the device list has changed. 436165689Snetchild * If the device list has changed, we want to go through 437165689Snetchild * the selection process again, in case a device that we 438165689Snetchild * were previously displaying has gone away. 439165689Snetchild */ 440165689Snetchild switch (getdevs(&cur)) { 441165689Snetchild case -1: 442165689Snetchild errx(1, "%s", devstat_errbuf); 443165689Snetchild break; 444165689Snetchild case 1: { 445165689Snetchild int retval; 446165689Snetchild 447165689Snetchild num_devices = cur.dinfo->numdevs; 448165689Snetchild generation = cur.dinfo->generation; 449165689Snetchild 450165689Snetchild retval = selectdevs(&dev_select, &num_selected, 451165689Snetchild &num_selections, &select_generation, 452165689Snetchild generation, cur.dinfo->devices, 453165689Snetchild num_devices, matches, num_matches, 454165689Snetchild specified_devices, 455165689Snetchild num_devices_specified, select_mode, 456165689Snetchild maxshowdevs, 0); 457165689Snetchild switch (retval) { 458165689Snetchild case -1: 459165689Snetchild errx(1, "%s", devstat_errbuf); 460218718Sdchagin break; 461218718Sdchagin case 1: 462218718Sdchagin printhdr(); 463165689Snetchild break; 464165689Snetchild default: 465165689Snetchild break; 466165689Snetchild } 467165689Snetchild } 468165689Snetchild default: 469165689Snetchild break; 470165689Snetchild } 471165689Snetchild 472165689Snetchild kread(X_SUM, &sum, sizeof(sum)); 473165689Snetchild size = sizeof(total); 474165689Snetchild mib[0] = CTL_VM; 475165689Snetchild mib[1] = VM_METER; 476165689Snetchild if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) { 477165689Snetchild (void)printf("Can't get kerninfo: %s\n", 478165689Snetchild strerror(errno)); 479165689Snetchild bzero(&total, sizeof(total)); 480165689Snetchild } 481218718Sdchagin (void)printf("%2d %1d %1d", 482218718Sdchagin total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); 483218718Sdchagin#define vmstat_pgtok(a) ((a) * sum.v_page_size >> 10) 484165689Snetchild#define rate(x) (((x) + halfuptime) / uptime) /* round */ 485165689Snetchild (void)printf(" %7ld %6ld ", (long)vmstat_pgtok(total.t_avm), 486165689Snetchild (long)vmstat_pgtok(total.t_free)); 487165689Snetchild (void)printf("%4lu ", 488165689Snetchild (u_long)rate(sum.v_vm_faults - osum.v_vm_faults)); 489165689Snetchild (void)printf("%3lu ", 490165689Snetchild (u_long)rate(sum.v_reactivated - osum.v_reactivated)); 491165689Snetchild (void)printf("%3lu ", 492218718Sdchagin (u_long)rate(sum.v_swapin + sum.v_vnodein - 493218718Sdchagin (osum.v_swapin + osum.v_vnodein))); 494165689Snetchild (void)printf("%3lu ", 495165689Snetchild (u_long)rate(sum.v_swapout + sum.v_vnodeout - 496165689Snetchild (osum.v_swapout + osum.v_vnodeout))); 497165689Snetchild (void)printf("%3lu ", 498218719Sdchagin (u_long)rate(sum.v_tfree - osum.v_tfree)); 499218719Sdchagin (void)printf("%3lu ", 500165689Snetchild (u_long)rate(sum.v_pdpages - osum.v_pdpages)); 501165689Snetchild devstats(); 502218719Sdchagin (void)printf("%4lu %4lu %3lu ", 503165689Snetchild (u_long)rate(sum.v_intr - osum.v_intr), 504165689Snetchild (u_long)rate(sum.v_syscall - osum.v_syscall), 505218719Sdchagin (u_long)rate(sum.v_swtch - osum.v_swtch)); 506218719Sdchagin cpustats(); 507165689Snetchild (void)printf("\n"); 508165689Snetchild (void)fflush(stdout); 509165689Snetchild if (reps >= 0 && --reps <= 0) 510165689Snetchild break; 511165689Snetchild osum = sum; 51283366Sjulian uptime = interval; 5139313Ssos /* 51451793Smarcel * We round upward to avoid losing low-frequency events 51551793Smarcel * (i.e., >= 1 per interval but < 1 per second). 51651793Smarcel */ 51751793Smarcel if (interval != 1) 5189313Ssos halfuptime = (uptime + 1) / 2; 5199313Ssos else 52072543Sjlemon halfuptime = 0; 52172543Sjlemon (void)sleep(interval); 5229313Ssos } 52351793Smarcel} 52451793Smarcel 52551793Smarcelvoid 52651793Smarcelprinthdr() 527163381Snetchild{ 528217743Sdchagin int i, num_shown; 52951793Smarcel 53051793Smarcel num_shown = (num_selected < maxshowdevs) ? num_selected : maxshowdevs; 53151793Smarcel (void)printf(" procs memory page%*s", 19, ""); 53251793Smarcel if (num_shown > 1) 53351793Smarcel (void)printf(" disks %*s", num_shown * 4 - 7, ""); 53451793Smarcel else if (num_shown == 1) 53551793Smarcel (void)printf("disk"); 536225617Skmacy (void)printf(" faults cpu\n"); 5379313Ssos (void)printf(" r b w avm fre flt re pi po fr sr "); 538161310Snetchild for (i = 0; i < num_devices; i++) 539184058Skib if ((dev_select[i].selected) 540184058Skib && (dev_select[i].selected <= maxshowdevs)) 541161310Snetchild (void)printf("%c%c%d ", dev_select[i].device_name[0], 542184058Skib dev_select[i].device_name[1], 543184058Skib dev_select[i].unit_number); 544161310Snetchild (void)printf(" in sy cs us sy id\n"); 545184058Skib hdrcnt = winlines - 2; 546184058Skib} 547161310Snetchild 548195104Srwatson/* 549195104Srwatson * Force a header to be prepended to the next output. 550161310Snetchild */ 551184058Skibvoid 552184058Skibneedhdr(dummy) 553184058Skib int dummy __unused; 554184058Skib{ 555184058Skib 556161310Snetchild hdrcnt = 1; 557184058Skib} 558184058Skib 559161310Snetchild#ifdef notyet 560184058Skibvoid 561184058Skibdotimes() 562184058Skib{ 563184058Skib u_int pgintime, rectime; 564161310Snetchild 565195104Srwatson kread(X_REC, &rectime, sizeof(rectime)); 566184058Skib kread(X_PGIN, &pgintime, sizeof(pgintime)); 567200667Skib kread(X_SUM, &sum, sizeof(sum)); 568184058Skib (void)printf("%u reclaims, %u total time (usec)\n", 569161310Snetchild sum.v_pgrec, rectime); 570184058Skib (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 571165869Snetchild (void)printf("\n"); 572161310Snetchild (void)printf("%u page ins, %u total time (msec)\n", 573161310Snetchild sum.v_pgin, pgintime / 10); 574161310Snetchild (void)printf("average: %8.1f msec / page in\n", 575184058Skib pgintime / (sum.v_pgin * 10.0)); 576161310Snetchild} 577184058Skib#endif 578161310Snetchild 579184058Skiblong 580184058Skibpct(top, bot) 581161310Snetchild long top, bot; 582184058Skib{ 583184058Skib long ans; 584184058Skib 585184058Skib if (bot == 0) 586184058Skib return(0); 587184058Skib ans = (quad_t)top * 100 / bot; 588161310Snetchild return (ans); 589209592Sjhb} 590184058Skib 591184058Skib#define PCT(top, bot) pct((long)(top), (long)(bot)) 592184058Skib 593184058Skibvoid 594161310Snetchilddosum() 595161310Snetchild{ 596161310Snetchild struct nchstats lnchstats; 597184058Skib long nchtotal; 598184058Skib 599184058Skib kread(X_SUM, &sum, sizeof(sum)); 600184058Skib (void)printf("%9u cpu context switches\n", sum.v_swtch); 601184058Skib (void)printf("%9u device interrupts\n", sum.v_intr); 602184058Skib (void)printf("%9u software interrupts\n", sum.v_soft); 603184058Skib (void)printf("%9u traps\n", sum.v_trap); 604184058Skib (void)printf("%9u system calls\n", sum.v_syscall); 605184058Skib (void)printf("%9u kernel threads created\n", sum.v_kthreads); 606184058Skib (void)printf("%9u fork() calls\n", sum.v_forks); 607184058Skib (void)printf("%9u vfork() calls\n", sum.v_vforks); 608184058Skib (void)printf("%9u rfork() calls\n", sum.v_rforks); 609184058Skib (void)printf("%9u swap pager pageins\n", sum.v_swapin); 610184058Skib (void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin); 611161310Snetchild (void)printf("%9u swap pager pageouts\n", sum.v_swapout); 612161310Snetchild (void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout); 613161310Snetchild (void)printf("%9u vnode pager pageins\n", sum.v_vnodein); 614161310Snetchild (void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin); 615161310Snetchild (void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout); 616161310Snetchild (void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout); 617184058Skib (void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups); 618184058Skib (void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages); 619161310Snetchild (void)printf("%9u pages reactivated\n", sum.v_reactivated); 620184058Skib (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 621161310Snetchild (void)printf("%9u copy-on-write optimized faults\n", sum.v_cow_optim); 622184058Skib (void)printf("%9u zero fill pages zeroed\n", sum.v_zfod); 623184058Skib (void)printf("%9u zero fill pages prezeroed\n", sum.v_ozfod); 624184058Skib (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 625184058Skib (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 626184058Skib (void)printf("%9u pages affected by kernel thread creation\n", sum.v_kthreadpages); 627184058Skib (void)printf("%9u pages affected by fork()\n", sum.v_forkpages); 628184058Skib (void)printf("%9u pages affected by vfork()\n", sum.v_vforkpages); 629184058Skib (void)printf("%9u pages affected by rfork()\n", sum.v_rforkpages); 630184058Skib (void)printf("%9u pages freed\n", sum.v_tfree); 631184058Skib (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 632184058Skib (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 633184058Skib (void)printf("%9u pages active\n", sum.v_active_count); 634184058Skib (void)printf("%9u pages inactive\n", sum.v_inactive_count); 635184058Skib (void)printf("%9u pages in VM cache\n", sum.v_cache_count); 636184058Skib (void)printf("%9u pages wired down\n", sum.v_wire_count); 637184058Skib (void)printf("%9u pages free\n", sum.v_free_count); 638184058Skib (void)printf("%9u bytes per page\n", sum.v_page_size); 639184058Skib kread(X_NCHSTATS, &lnchstats, sizeof(lnchstats)); 640184058Skib nchtotal = lnchstats.ncs_goodhits + lnchstats.ncs_neghits + 641184058Skib lnchstats.ncs_badhits + lnchstats.ncs_falsehits + 642184058Skib lnchstats.ncs_miss + lnchstats.ncs_long; 643184058Skib (void)printf("%9ld total name lookups\n", nchtotal); 644184058Skib (void)printf( 645184058Skib "%9s cache hits (%ld%% pos + %ld%% neg) system %ld%% per-directory\n", 646184058Skib "", PCT(lnchstats.ncs_goodhits, nchtotal), 647184058Skib PCT(lnchstats.ncs_neghits, nchtotal), 648184058Skib PCT(lnchstats.ncs_pass2, nchtotal)); 649184058Skib (void)printf("%9s deletions %ld%%, falsehits %ld%%, toolong %ld%%\n", "", 650184058Skib PCT(lnchstats.ncs_badhits, nchtotal), 651184058Skib PCT(lnchstats.ncs_falsehits, nchtotal), 652218720Sdchagin PCT(lnchstats.ncs_long, nchtotal)); 653218720Sdchagin} 654218720Sdchagin 655218720Sdchagin#ifdef notyet 656184058Skibvoid 657doforkst() 658{ 659 struct forkstat fks; 660 661 kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 662 (void)printf("%d forks, %d pages, average %.2f\n", 663 fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 664 (void)printf("%d vforks, %d pages, average %.2f\n", 665 fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 666} 667#endif 668 669static void 670devstats() 671{ 672 int dn, state; 673 long double transfers_per_second; 674 long double busy_seconds; 675 long tmp; 676 677 for (state = 0; state < CPUSTATES; ++state) { 678 tmp = cur.cp_time[state]; 679 cur.cp_time[state] -= last.cp_time[state]; 680 last.cp_time[state] = tmp; 681 } 682 683 busy_seconds = compute_etime(cur.busy_time, last.busy_time); 684 685 for (dn = 0; dn < num_devices; dn++) { 686 int di; 687 688 if ((dev_select[dn].selected == 0) 689 || (dev_select[dn].selected > maxshowdevs)) 690 continue; 691 692 di = dev_select[dn].position; 693 694 if (devstat_compute_statistics(&cur.dinfo->devices[di], 695 &last.dinfo->devices[di], busy_seconds, 696 DSM_TRANSFERS_PER_SECOND, &transfers_per_second, 697 DSM_NONE) != 0) 698 errx(1, "%s", devstat_errbuf); 699 700 (void)printf("%3.0Lf ", transfers_per_second); 701 } 702} 703 704void 705cpustats() 706{ 707 int state; 708 double lpct, total; 709 710 total = 0; 711 for (state = 0; state < CPUSTATES; ++state) 712 total += cur.cp_time[state]; 713 if (total) 714 lpct = 100.0 / total; 715 else 716 lpct = 0.0; 717 (void)printf("%2.0f ", (cur.cp_time[CP_USER] + 718 cur.cp_time[CP_NICE]) * lpct); 719 (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + 720 cur.cp_time[CP_INTR]) * lpct); 721 (void)printf("%2.0f", cur.cp_time[CP_IDLE] * lpct); 722} 723 724void 725dointr() 726{ 727 u_long *intrcnt, uptime; 728 u_int64_t inttotal; 729 int nintr, inamlen; 730 char *intrname; 731 732 uptime = getuptime(); 733 nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value; 734 inamlen = 735 namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value; 736 intrcnt = malloc((size_t)nintr); 737 intrname = malloc((size_t)inamlen); 738 if (intrcnt == NULL || intrname == NULL) 739 errx(1, "malloc"); 740 kread(X_INTRCNT, intrcnt, (size_t)nintr); 741 kread(X_INTRNAMES, intrname, (size_t)inamlen); 742 (void)printf("interrupt total rate\n"); 743 inttotal = 0; 744 nintr /= sizeof(long); 745 while (--nintr >= 0) { 746 if (*intrcnt) 747 (void)printf("%-12s %20lu %10lu\n", intrname, 748 *intrcnt, *intrcnt / uptime); 749 intrname += strlen(intrname) + 1; 750 inttotal += *intrcnt++; 751 } 752 (void)printf("Total %20llu %10llu\n", inttotal, 753 inttotal / (u_int64_t) uptime); 754} 755 756#define MAX_KMSTATS 200 757 758void 759domem() 760{ 761 struct malloc_type *ks; 762 int i, j; 763 int first, nkms; 764 long totuse = 0, totfree = 0, totreq = 0; 765 struct malloc_type kmemstats[MAX_KMSTATS], *kmsp; 766 char buf[1024]; 767 768 kread(X_KMEMSTATISTICS, &kmsp, sizeof(kmsp)); 769 for (nkms = 0; nkms < MAX_KMSTATS && kmsp != NULL; nkms++) { 770 if (sizeof(kmemstats[0]) != kvm_read(kd, (u_long)kmsp, 771 &kmemstats[nkms], sizeof(kmemstats[0]))) 772 err(1, "kvm_read(%p)", (void *)kmsp); 773 if (sizeof(buf) != kvm_read(kd, 774 (u_long)kmemstats[nkms].ks_shortdesc, buf, sizeof(buf))) 775 err(1, "kvm_read(%p)", 776 (const void *)kmemstats[nkms].ks_shortdesc); 777 buf[sizeof(buf) - 1] = '\0'; 778 kmemstats[nkms].ks_shortdesc = strdup(buf); 779 kmsp = kmemstats[nkms].ks_next; 780 } 781 782 (void)printf( 783 "\nMemory statistics by type Type Kern\n"); 784 (void)printf( 785" Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n"); 786 for (i = 0, ks = &kmemstats[0]; i < nkms; i++, ks++) { 787 if (ks->ks_calls == 0) 788 continue; 789 (void)printf("%13s%6ld%6ldK%7ldK%6ldK%9lld%5u%6u", 790 ks->ks_shortdesc, 791 ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 792 (ks->ks_maxused + 1023) / 1024, 793 (ks->ks_limit + 1023) / 1024, (long long)ks->ks_calls, 794 ks->ks_limblocks, ks->ks_mapblocks); 795 first = 1; 796 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) { 797 if ((ks->ks_size & j) == 0) 798 continue; 799 if (first) 800 (void)printf(" "); 801 else 802 (void)printf(","); 803 if(j<1024) 804 (void)printf("%d",j); 805 else 806 (void)printf("%dK",j>>10); 807 first = 0; 808 } 809 (void)printf("\n"); 810 totuse += ks->ks_memuse; 811 totreq += ks->ks_calls; 812 } 813 (void)printf("\nMemory Totals: In Use Free Requests\n"); 814 (void)printf(" %7ldK %6ldK %8ld\n", 815 (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 816} 817 818void 819dozmem() 820{ 821 char *buf; 822 size_t bufsize; 823 824 buf = NULL; 825 bufsize = 1024; 826 for (;;) { 827 if ((buf = realloc(buf, bufsize)) == NULL) 828 err(1, "realloc()"); 829 if (sysctlbyname("vm.zone", buf, &bufsize, 0, NULL) == 0) 830 break; 831 if (errno != ENOMEM) 832 err(1, "sysctl()"); 833 bufsize *= 2; 834 } 835 buf[bufsize] = '\0'; /* play it safe */ 836 (void)printf("%s\n\n", buf); 837 free(buf); 838} 839 840/* 841 * kread reads something from the kernel, given its nlist index. 842 */ 843void 844kread(nlx, addr, size) 845 int nlx; 846 void *addr; 847 size_t size; 848{ 849 char *sym; 850 851 if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { 852 sym = namelist[nlx].n_name; 853 if (*sym == '_') 854 ++sym; 855 errx(1, "symbol %s not defined", sym); 856 } 857 if (kvm_read(kd, namelist[nlx].n_value, addr, size) != (int)size) { 858 sym = namelist[nlx].n_name; 859 if (*sym == '_') 860 ++sym; 861 errx(1, "%s: %s", sym, kvm_geterr(kd)); 862 } 863} 864 865void 866usage() 867{ 868 (void)fprintf(stderr, "%s%s", 869 "usage: vmstat [-imsz] [-c count] [-M core] [-N system] [-w wait]\n", 870 " [-n devs] [disks]\n"); 871 exit(1); 872} 873