Home | History | Annotate | Line # | Download | only in vmstat
vmstat.c revision 1.55
      1  1.55    kleink /*	$NetBSD: vmstat.c,v 1.55 1999/02/12 15:04:00 kleink Exp $	*/
      2  1.45   thorpej 
      3  1.45   thorpej /*-
      4  1.45   thorpej  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  1.45   thorpej  * All rights reserved.
      6  1.45   thorpej  *
      7  1.45   thorpej  * This code is derived from software contributed to The NetBSD Foundation
      8  1.45   thorpej  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  1.45   thorpej  * NASA Ames Research Center.
     10  1.45   thorpej  *
     11  1.45   thorpej  * Redistribution and use in source and binary forms, with or without
     12  1.45   thorpej  * modification, are permitted provided that the following conditions
     13  1.45   thorpej  * are met:
     14  1.45   thorpej  * 1. Redistributions of source code must retain the above copyright
     15  1.45   thorpej  *    notice, this list of conditions and the following disclaimer.
     16  1.45   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.45   thorpej  *    notice, this list of conditions and the following disclaimer in the
     18  1.45   thorpej  *    documentation and/or other materials provided with the distribution.
     19  1.45   thorpej  * 3. All advertising materials mentioning features or use of this software
     20  1.45   thorpej  *    must display the following acknowledgement:
     21  1.45   thorpej  *	This product includes software developed by the NetBSD
     22  1.45   thorpej  *	Foundation, Inc. and its contributors.
     23  1.45   thorpej  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  1.45   thorpej  *    contributors may be used to endorse or promote products derived
     25  1.45   thorpej  *    from this software without specific prior written permission.
     26  1.45   thorpej  *
     27  1.45   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  1.45   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  1.45   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  1.45   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  1.45   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  1.45   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  1.45   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  1.45   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  1.45   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  1.45   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  1.45   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     38  1.45   thorpej  */
     39  1.21       cgd 
     40   1.1       cgd /*
     41  1.13       cgd  * Copyright (c) 1980, 1986, 1991, 1993
     42  1.13       cgd  *	The Regents of the University of California.  All rights reserved.
     43   1.1       cgd  *
     44   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     45   1.1       cgd  * modification, are permitted provided that the following conditions
     46   1.1       cgd  * are met:
     47   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     48   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     49   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     50   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     51   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     52   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     53   1.1       cgd  *    must display the following acknowledgement:
     54   1.1       cgd  *	This product includes software developed by the University of
     55   1.1       cgd  *	California, Berkeley and its contributors.
     56   1.1       cgd  * 4. Neither the name of the University nor the names of its contributors
     57   1.1       cgd  *    may be used to endorse or promote products derived from this software
     58   1.1       cgd  *    without specific prior written permission.
     59   1.1       cgd  *
     60   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     61   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     62   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     63   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     64   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     65   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     66   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     67   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     68   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     69   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     70   1.1       cgd  * SUCH DAMAGE.
     71   1.1       cgd  */
     72   1.1       cgd 
     73  1.38       mrg #include <sys/cdefs.h>
     74   1.1       cgd #ifndef lint
     75  1.38       mrg __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
     76  1.38       mrg 	The Regents of the University of California.  All rights reserved.\n");
     77   1.1       cgd #endif /* not lint */
     78   1.1       cgd 
     79   1.1       cgd #ifndef lint
     80  1.21       cgd #if 0
     81  1.37       mrg static char sccsid[] = "@(#)vmstat.c	8.2 (Berkeley) 3/1/95";
     82  1.21       cgd #else
     83  1.55    kleink __RCSID("$NetBSD: vmstat.c,v 1.55 1999/02/12 15:04:00 kleink Exp $");
     84  1.21       cgd #endif
     85   1.1       cgd #endif /* not lint */
     86   1.1       cgd 
     87   1.1       cgd #include <sys/param.h>
     88   1.1       cgd #include <sys/time.h>
     89   1.1       cgd #include <sys/proc.h>
     90   1.1       cgd #include <sys/user.h>
     91   1.1       cgd #include <sys/dkstat.h>
     92   1.1       cgd #include <sys/buf.h>
     93   1.1       cgd #include <sys/namei.h>
     94   1.1       cgd #include <sys/malloc.h>
     95   1.1       cgd #include <sys/ioctl.h>
     96  1.13       cgd #include <sys/sysctl.h>
     97  1.18        pk #include <sys/device.h>
     98  1.51        pk #include <sys/pool.h>
     99  1.13       cgd #include <vm/vm.h>
    100  1.45   thorpej #include <err.h>
    101  1.55    kleink #include <fcntl.h>
    102   1.1       cgd #include <time.h>
    103   1.1       cgd #include <nlist.h>
    104   1.1       cgd #include <kvm.h>
    105   1.1       cgd #include <errno.h>
    106   1.1       cgd #include <unistd.h>
    107  1.22       jtc #include <signal.h>
    108   1.1       cgd #include <stdio.h>
    109   1.1       cgd #include <ctype.h>
    110   1.1       cgd #include <stdlib.h>
    111   1.1       cgd #include <string.h>
    112   1.1       cgd #include <paths.h>
    113  1.13       cgd #include <limits.h>
    114  1.29   thorpej #include "dkstats.h"
    115   1.1       cgd 
    116  1.45   thorpej #if defined(UVM)
    117  1.45   thorpej #include <uvm/uvm_stat.h>
    118  1.45   thorpej #endif
    119  1.45   thorpej 
    120  1.13       cgd struct nlist namelist[] = {
    121   1.1       cgd #define	X_CPTIME	0
    122   1.1       cgd 	{ "_cp_time" },
    123  1.41       mrg #define	X_BOOTTIME	1
    124   1.1       cgd 	{ "_boottime" },
    125  1.41       mrg #define X_HZ		2
    126   1.1       cgd 	{ "_hz" },
    127  1.41       mrg #define X_STATHZ	3
    128  1.13       cgd 	{ "_stathz" },
    129  1.41       mrg #define X_NCHSTATS	4
    130   1.1       cgd 	{ "_nchstats" },
    131  1.41       mrg #define	X_INTRNAMES	5
    132   1.1       cgd 	{ "_intrnames" },
    133  1.41       mrg #define	X_EINTRNAMES	6
    134   1.1       cgd 	{ "_eintrnames" },
    135  1.41       mrg #define	X_INTRCNT	7
    136   1.1       cgd 	{ "_intrcnt" },
    137  1.41       mrg #define	X_EINTRCNT	8
    138   1.1       cgd 	{ "_eintrcnt" },
    139  1.41       mrg #define	X_KMEMSTAT	9
    140   1.1       cgd 	{ "_kmemstats" },
    141  1.41       mrg #define	X_KMEMBUCKETS	10
    142   1.1       cgd 	{ "_bucket" },
    143  1.41       mrg #define X_ALLEVENTS	11
    144  1.18        pk 	{ "_allevents" },
    145  1.51        pk #define X_POOLHEAD	12
    146  1.51        pk 	{ "_pool_head" },
    147  1.41       mrg #if defined(UVM)
    148  1.51        pk #define X_END		13
    149   1.1       cgd #else
    150  1.51        pk #define X_SUM		13
    151  1.41       mrg 	{ "_cnt" },
    152  1.51        pk #define X_END		14
    153   1.1       cgd #endif
    154  1.23      phil #if defined(pc532)
    155  1.23      phil #define	X_IVT		(X_END)
    156  1.23      phil 	{ "_ivt" },
    157  1.23      phil #endif
    158   1.1       cgd 	{ "" },
    159   1.1       cgd };
    160   1.1       cgd 
    161  1.29   thorpej /* Objects defined in dkstats.c */
    162  1.29   thorpej extern struct _disk	cur;
    163  1.29   thorpej extern char	**dr_name;
    164  1.29   thorpej extern int	*dk_select, dk_ndrive;
    165   1.1       cgd 
    166  1.41       mrg #if defined(UVM)
    167  1.41       mrg struct	uvmexp uvmexp, ouvmexp;
    168  1.41       mrg #else
    169  1.13       cgd struct	vmmeter sum, osum;
    170  1.41       mrg #endif
    171  1.29   thorpej int		ndrives;
    172   1.1       cgd 
    173   1.1       cgd int	winlines = 20;
    174   1.1       cgd 
    175  1.13       cgd kvm_t *kd;
    176  1.13       cgd 
    177   1.1       cgd #define	FORKSTAT	0x01
    178   1.1       cgd #define	INTRSTAT	0x02
    179   1.1       cgd #define	MEMSTAT		0x04
    180   1.1       cgd #define	SUMSTAT		0x08
    181   1.1       cgd #define	VMSTAT		0x20
    182  1.45   thorpej #if defined(UVM)
    183  1.45   thorpej #define	HISTLIST	0x40
    184  1.45   thorpej #define	HISTDUMP	0x80
    185  1.45   thorpej #endif
    186   1.1       cgd 
    187  1.29   thorpej void	cpustats __P((void));
    188  1.29   thorpej void	dkstats __P((void));
    189  1.29   thorpej void	dointr __P((void));
    190  1.29   thorpej void	domem __P((void));
    191  1.51        pk void	dopool __P((void));
    192  1.29   thorpej void	dosum __P((void));
    193  1.29   thorpej void	dovmstat __P((u_int, int));
    194  1.29   thorpej void	kread __P((int, void *, size_t));
    195  1.38       mrg void	needhdr __P((int));
    196  1.38       mrg long	getuptime __P((void));
    197  1.38       mrg void	printhdr __P((void));
    198  1.38       mrg long	pct __P((long, long));
    199  1.29   thorpej void	usage __P((void));
    200  1.40   thorpej void	doforkst __P((void));
    201   1.1       cgd 
    202  1.45   thorpej #if defined(UVM)
    203  1.45   thorpej void	hist_traverse __P((int, const char *));
    204  1.45   thorpej void	hist_dodump __P((struct uvm_history *));
    205  1.45   thorpej #endif
    206  1.45   thorpej 
    207  1.38       mrg int	main __P((int, char **));
    208  1.29   thorpej char	**choosedrives __P((char **));
    209  1.29   thorpej 
    210  1.49  drochner extern int dkinit __P((int, gid_t));
    211  1.38       mrg extern void dkreadstats __P((void));
    212  1.38       mrg extern void dkswap __P((void));
    213  1.38       mrg 
    214  1.29   thorpej /* Namelist and memory file names. */
    215  1.29   thorpej char	*nlistf, *memf;
    216  1.29   thorpej 
    217  1.47       mrg /* allow old usage [vmstat 1] */
    218  1.47       mrg #define	BACKWARD_COMPATIBILITY
    219  1.47       mrg 
    220  1.38       mrg int
    221   1.1       cgd main(argc, argv)
    222  1.38       mrg 	int argc;
    223  1.38       mrg 	char **argv;
    224   1.1       cgd {
    225   1.1       cgd 	extern int optind;
    226   1.1       cgd 	extern char *optarg;
    227  1.38       mrg 	int c, todo;
    228   1.1       cgd 	u_int interval;
    229   1.1       cgd 	int reps;
    230  1.13       cgd         char errbuf[_POSIX2_LINE_MAX];
    231  1.48       mrg 	gid_t	egid = getegid();
    232  1.45   thorpej #if defined(UVM)
    233  1.45   thorpej 	const char *histname = NULL;
    234  1.45   thorpej #endif
    235   1.1       cgd 
    236  1.48       mrg 	(void)setegid(getgid());
    237  1.13       cgd 	memf = nlistf = NULL;
    238   1.1       cgd 	interval = reps = todo = 0;
    239  1.45   thorpej #if defined(UVM)
    240  1.54   thorpej 	while ((c = getopt(argc, argv, "c:fh:HilM:mN:sw:")) != -1) {
    241  1.45   thorpej #else
    242  1.54   thorpej 	while ((c = getopt(argc, argv, "c:fiM:mN:sw:")) != -1) {
    243  1.45   thorpej #endif
    244   1.1       cgd 		switch (c) {
    245   1.1       cgd 		case 'c':
    246   1.1       cgd 			reps = atoi(optarg);
    247   1.1       cgd 			break;
    248   1.1       cgd 		case 'f':
    249   1.1       cgd 			todo |= FORKSTAT;
    250   1.1       cgd 			break;
    251  1.45   thorpej #if defined(UVM)
    252  1.45   thorpej 		case 'h':
    253  1.45   thorpej 			histname = optarg;
    254  1.45   thorpej 			/* FALLTHROUGH */
    255  1.45   thorpej 		case 'H':
    256  1.45   thorpej 			todo |= HISTDUMP;
    257  1.45   thorpej 			break;
    258  1.45   thorpej #endif
    259   1.1       cgd 		case 'i':
    260   1.1       cgd 			todo |= INTRSTAT;
    261   1.1       cgd 			break;
    262  1.45   thorpej #if defined(UVM)
    263  1.45   thorpej 		case 'l':
    264  1.45   thorpej 			todo |= HISTLIST;
    265  1.45   thorpej 			break;
    266  1.45   thorpej #endif
    267   1.1       cgd 		case 'M':
    268  1.13       cgd 			memf = optarg;
    269   1.1       cgd 			break;
    270   1.1       cgd 		case 'm':
    271   1.1       cgd 			todo |= MEMSTAT;
    272   1.1       cgd 			break;
    273   1.1       cgd 		case 'N':
    274  1.13       cgd 			nlistf = optarg;
    275   1.1       cgd 			break;
    276   1.1       cgd 		case 's':
    277   1.1       cgd 			todo |= SUMSTAT;
    278   1.1       cgd 			break;
    279   1.1       cgd 		case 'w':
    280   1.1       cgd 			interval = atoi(optarg);
    281   1.1       cgd 			break;
    282   1.1       cgd 		case '?':
    283   1.1       cgd 		default:
    284   1.1       cgd 			usage();
    285   1.1       cgd 		}
    286   1.1       cgd 	}
    287   1.1       cgd 	argc -= optind;
    288   1.1       cgd 	argv += optind;
    289   1.1       cgd 
    290   1.1       cgd 	if (todo == 0)
    291   1.1       cgd 		todo = VMSTAT;
    292   1.1       cgd 
    293  1.13       cgd 	/*
    294  1.48       mrg 	 * Discard setgid privileges.  If not the running kernel, we toss
    295  1.48       mrg 	 * them away totally so that bad guys can't print interesting stuff
    296  1.48       mrg 	 * from kernel memory, otherwise switch back to kmem for the
    297  1.48       mrg 	 * duration of the kvm_openfiles() call.
    298  1.13       cgd 	 */
    299  1.13       cgd 	if (nlistf != NULL || memf != NULL)
    300  1.48       mrg 		(void)setgid(getgid());
    301  1.48       mrg 	else
    302  1.48       mrg 		(void)setegid(egid);
    303  1.13       cgd 
    304  1.13       cgd         kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
    305  1.48       mrg 	if (kd == 0)
    306  1.48       mrg 		errx(1, "kvm_openfiles: %s\n", errbuf);
    307  1.48       mrg 
    308  1.48       mrg 	if (nlistf == NULL && memf == NULL) {
    309  1.48       mrg 		if (todo & VMSTAT)
    310  1.48       mrg 			(void)setegid(getgid());	/* XXX: dkinit */
    311  1.48       mrg 		else
    312  1.48       mrg 			(void)setgid(getgid());
    313   1.1       cgd 	}
    314   1.1       cgd 
    315  1.13       cgd 	if ((c = kvm_nlist(kd, namelist)) != 0) {
    316   1.1       cgd 		if (c > 0) {
    317   1.1       cgd 			(void)fprintf(stderr,
    318  1.13       cgd 			    "vmstat: undefined symbols:");
    319  1.13       cgd 			for (c = 0;
    320  1.13       cgd 			    c < sizeof(namelist)/sizeof(namelist[0]); c++)
    321  1.13       cgd 				if (namelist[c].n_type == 0)
    322  1.13       cgd 					fprintf(stderr, " %s",
    323  1.13       cgd 					    namelist[c].n_name);
    324   1.1       cgd 			(void)fputc('\n', stderr);
    325   1.1       cgd 		} else
    326   1.1       cgd 			(void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
    327  1.13       cgd 			    kvm_geterr(kd));
    328   1.1       cgd 		exit(1);
    329   1.1       cgd 	}
    330   1.1       cgd 
    331   1.1       cgd 	if (todo & VMSTAT) {
    332   1.1       cgd 		struct winsize winsize;
    333   1.1       cgd 
    334  1.49  drochner 		dkinit(0, egid); /* Initialize disk stats, no disks selected. */
    335  1.49  drochner 
    336  1.49  drochner 		(void)setgid(getgid()); /* don't need privs anymore */
    337  1.49  drochner 
    338  1.29   thorpej 		argv = choosedrives(argv);	/* Select disks. */
    339   1.1       cgd 		winsize.ws_row = 0;
    340  1.47       mrg 		(void)ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
    341   1.1       cgd 		if (winsize.ws_row > 0)
    342   1.1       cgd 			winlines = winsize.ws_row;
    343   1.1       cgd 
    344   1.1       cgd 	}
    345   1.1       cgd 
    346   1.1       cgd #ifdef	BACKWARD_COMPATIBILITY
    347   1.1       cgd 	if (*argv) {
    348   1.1       cgd 		interval = atoi(*argv);
    349   1.1       cgd 		if (*++argv)
    350   1.1       cgd 			reps = atoi(*argv);
    351   1.1       cgd 	}
    352   1.1       cgd #endif
    353   1.1       cgd 
    354   1.1       cgd 	if (interval) {
    355   1.1       cgd 		if (!reps)
    356   1.1       cgd 			reps = -1;
    357   1.1       cgd 	} else if (reps)
    358   1.1       cgd 		interval = 1;
    359   1.1       cgd 
    360  1.45   thorpej #if defined(UVM)
    361  1.45   thorpej 	if (todo & (HISTLIST|HISTDUMP)) {
    362  1.45   thorpej 		if ((todo & (HISTLIST|HISTDUMP)) == (HISTLIST|HISTDUMP))
    363  1.45   thorpej 			errx(1, "you may list or dump, but not both!");
    364  1.45   thorpej 		hist_traverse(todo, histname);
    365  1.45   thorpej 	}
    366  1.45   thorpej #endif
    367   1.1       cgd 	if (todo & FORKSTAT)
    368   1.1       cgd 		doforkst();
    369  1.51        pk 	if (todo & MEMSTAT) {
    370   1.1       cgd 		domem();
    371  1.51        pk 		dopool();
    372  1.51        pk 	}
    373   1.1       cgd 	if (todo & SUMSTAT)
    374  1.13       cgd 		dosum();
    375   1.1       cgd 	if (todo & INTRSTAT)
    376   1.1       cgd 		dointr();
    377   1.1       cgd 	if (todo & VMSTAT)
    378   1.1       cgd 		dovmstat(interval, reps);
    379   1.1       cgd 	exit(0);
    380   1.1       cgd }
    381   1.1       cgd 
    382   1.1       cgd char **
    383  1.29   thorpej choosedrives(argv)
    384   1.1       cgd 	char **argv;
    385   1.1       cgd {
    386  1.38       mrg 	int i;
    387   1.1       cgd 
    388   1.1       cgd 	/*
    389   1.1       cgd 	 * Choose drives to be displayed.  Priority goes to (in order) drives
    390   1.1       cgd 	 * supplied as arguments, default drives.  If everything isn't filled
    391   1.1       cgd 	 * in and there are drives not taken care of, display the first few
    392   1.1       cgd 	 * that fit.
    393   1.1       cgd 	 */
    394   1.1       cgd #define BACKWARD_COMPATIBILITY
    395   1.1       cgd 	for (ndrives = 0; *argv; ++argv) {
    396   1.1       cgd #ifdef	BACKWARD_COMPATIBILITY
    397   1.1       cgd 		if (isdigit(**argv))
    398   1.1       cgd 			break;
    399   1.1       cgd #endif
    400   1.1       cgd 		for (i = 0; i < dk_ndrive; i++) {
    401   1.1       cgd 			if (strcmp(dr_name[i], *argv))
    402   1.1       cgd 				continue;
    403  1.29   thorpej 			dk_select[i] = 1;
    404   1.1       cgd 			++ndrives;
    405   1.1       cgd 			break;
    406   1.1       cgd 		}
    407   1.1       cgd 	}
    408   1.1       cgd 	for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
    409  1.29   thorpej 		if (dk_select[i])
    410   1.1       cgd 			continue;
    411  1.29   thorpej 		dk_select[i] = 1;
    412   1.1       cgd 		++ndrives;
    413   1.1       cgd 	}
    414   1.1       cgd 	return(argv);
    415   1.1       cgd }
    416   1.1       cgd 
    417   1.1       cgd long
    418   1.1       cgd getuptime()
    419   1.1       cgd {
    420  1.30       cgd 	static time_t now;
    421  1.30       cgd 	static struct timeval boottime;
    422   1.1       cgd 	time_t uptime;
    423   1.1       cgd 
    424  1.30       cgd 	if (boottime.tv_sec == 0)
    425   1.1       cgd 		kread(X_BOOTTIME, &boottime, sizeof(boottime));
    426   1.1       cgd 	(void)time(&now);
    427  1.30       cgd 	uptime = now - boottime.tv_sec;
    428   1.1       cgd 	if (uptime <= 0 || uptime > 60*60*24*365*10) {
    429   1.1       cgd 		(void)fprintf(stderr,
    430   1.1       cgd 		    "vmstat: time makes no sense; namelist must be wrong.\n");
    431   1.1       cgd 		exit(1);
    432   1.1       cgd 	}
    433   1.1       cgd 	return(uptime);
    434   1.1       cgd }
    435   1.1       cgd 
    436   1.1       cgd int	hz, hdrcnt;
    437   1.1       cgd 
    438   1.1       cgd void
    439   1.1       cgd dovmstat(interval, reps)
    440   1.1       cgd 	u_int interval;
    441   1.1       cgd 	int reps;
    442   1.1       cgd {
    443   1.1       cgd 	struct vmtotal total;
    444   1.1       cgd 	time_t uptime, halfuptime;
    445  1.17       cgd 	int mib[2];
    446  1.17       cgd 	size_t size;
    447  1.41       mrg 	int pagesize = getpagesize();
    448   1.1       cgd 
    449   1.1       cgd 	uptime = getuptime();
    450   1.1       cgd 	halfuptime = uptime / 2;
    451   1.1       cgd 	(void)signal(SIGCONT, needhdr);
    452   1.1       cgd 
    453  1.13       cgd 	if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
    454  1.13       cgd 		kread(X_STATHZ, &hz, sizeof(hz));
    455   1.1       cgd 	if (!hz)
    456   1.1       cgd 		kread(X_HZ, &hz, sizeof(hz));
    457   1.1       cgd 
    458   1.1       cgd 	for (hdrcnt = 1;;) {
    459   1.1       cgd 		if (!--hdrcnt)
    460   1.1       cgd 			printhdr();
    461  1.29   thorpej 		/* Read new disk statistics */
    462  1.29   thorpej 		dkreadstats();
    463  1.41       mrg #if defined(UVM)
    464  1.41       mrg 		size = sizeof(uvmexp);
    465  1.41       mrg 		mib[0] = CTL_VM;
    466  1.41       mrg 		mib[1] = VM_UVMEXP;
    467  1.41       mrg 		if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
    468  1.41       mrg 			printf("can't get uvmexp: %s\n", strerror(errno));
    469  1.53     perry 			memset(&uvmexp, 0, sizeof(uvmexp));
    470  1.41       mrg 		}
    471  1.41       mrg #else
    472  1.13       cgd 		kread(X_SUM, &sum, sizeof(sum));
    473  1.41       mrg #endif
    474  1.13       cgd 		size = sizeof(total);
    475  1.13       cgd 		mib[0] = CTL_VM;
    476  1.13       cgd 		mib[1] = VM_METER;
    477  1.13       cgd 		if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
    478  1.13       cgd 			printf("Can't get kerninfo: %s\n", strerror(errno));
    479  1.53     perry 			memset(&total, 0, sizeof(total));
    480  1.13       cgd 		}
    481  1.13       cgd 		(void)printf("%2d%2d%2d",
    482  1.13       cgd 		    total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
    483  1.41       mrg #define pgtok(a) (long)((a) * (pagesize >> 10))
    484  1.38       mrg #define	rate(x)	(u_long)(((x) + halfuptime) / uptime)	/* round */
    485  1.13       cgd 		(void)printf("%6ld%6ld ",
    486   1.1       cgd 		    pgtok(total.t_avm), pgtok(total.t_free));
    487  1.41       mrg #if defined(UVM)
    488  1.42       mrg 		(void)printf("%4lu ", rate(uvmexp.faults - ouvmexp.faults));
    489  1.42       mrg 		(void)printf("%3lu ", rate(uvmexp.pdreact - ouvmexp.pdreact));
    490  1.46       mrg 		(void)printf("%3lu ", rate(uvmexp.pageins - ouvmexp.pageins));
    491  1.44       mrg 		(void)printf("%4lu ",
    492  1.44       mrg 		    rate(uvmexp.pgswapout - ouvmexp.pgswapout));
    493  1.44       mrg 		(void)printf("%4lu ", rate(uvmexp.pdfreed - ouvmexp.pdfreed));
    494  1.44       mrg 		(void)printf("%4lu ", rate(uvmexp.pdscans - ouvmexp.pdscans));
    495  1.42       mrg 		dkstats();
    496  1.42       mrg 		(void)printf("%4lu %4lu %3lu ",
    497  1.42       mrg 		    rate(uvmexp.intrs - ouvmexp.intrs),
    498  1.42       mrg 		    rate(uvmexp.syscalls - ouvmexp.syscalls),
    499  1.42       mrg 		    rate(uvmexp.swtch - ouvmexp.swtch));
    500  1.42       mrg 		cpustats();
    501  1.42       mrg 		(void)printf("\n");
    502  1.42       mrg 		(void)fflush(stdout);
    503  1.42       mrg 		if (reps >= 0 && --reps <= 0)
    504  1.42       mrg 			break;
    505  1.42       mrg 		ouvmexp = uvmexp;
    506  1.41       mrg #else
    507  1.13       cgd 		(void)printf("%4lu ", rate(sum.v_faults - osum.v_faults));
    508   1.1       cgd 		(void)printf("%3lu ",
    509  1.13       cgd 		    rate(sum.v_reactivated - osum.v_reactivated));
    510  1.13       cgd 		(void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins));
    511   1.1       cgd 		(void)printf("%3lu %3lu ",
    512  1.38       mrg 		    rate(sum.v_pageouts - osum.v_pageouts), (u_long)0);
    513  1.13       cgd 		(void)printf("%3lu ", rate(sum.v_scan - osum.v_scan));
    514   1.1       cgd 		dkstats();
    515   1.1       cgd 		(void)printf("%4lu %4lu %3lu ",
    516  1.13       cgd 		    rate(sum.v_intr - osum.v_intr),
    517  1.13       cgd 		    rate(sum.v_syscall - osum.v_syscall),
    518  1.13       cgd 		    rate(sum.v_swtch - osum.v_swtch));
    519   1.1       cgd 		cpustats();
    520   1.1       cgd 		(void)printf("\n");
    521   1.1       cgd 		(void)fflush(stdout);
    522   1.1       cgd 		if (reps >= 0 && --reps <= 0)
    523   1.1       cgd 			break;
    524  1.13       cgd 		osum = sum;
    525  1.41       mrg #endif
    526   1.1       cgd 		uptime = interval;
    527   1.1       cgd 		/*
    528   1.1       cgd 		 * We round upward to avoid losing low-frequency events
    529   1.1       cgd 		 * (i.e., >= 1 per interval but < 1 per second).
    530   1.1       cgd 		 */
    531  1.33   thorpej 		halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
    532   1.1       cgd 		(void)sleep(interval);
    533   1.1       cgd 	}
    534   1.1       cgd }
    535   1.1       cgd 
    536  1.38       mrg void
    537   1.1       cgd printhdr()
    538   1.1       cgd {
    539  1.38       mrg 	int i;
    540   1.1       cgd 
    541  1.44       mrg #if defined(UVM)
    542  1.44       mrg 	(void)printf(" procs   memory     page%*s", 23, "");
    543  1.44       mrg #else
    544   1.1       cgd 	(void)printf(" procs   memory     page%*s", 20, "");
    545  1.44       mrg #endif
    546  1.29   thorpej 	if (ndrives > 0)
    547  1.29   thorpej 		(void)printf("%s %*sfaults   cpu\n",
    548  1.29   thorpej 		   ((ndrives > 1) ? "disks" : "disk"),
    549  1.29   thorpej 		   ((ndrives > 1) ? ndrives * 3 - 4 : 0), "");
    550   1.1       cgd 	else
    551  1.29   thorpej 		(void)printf("%*s  faults   cpu\n",
    552  1.29   thorpej 		   ndrives * 3, "");
    553  1.29   thorpej 
    554  1.44       mrg #if defined(UVM)
    555  1.44       mrg 	(void)printf(" r b w   avm   fre  flt  re  pi   po   fr   sr ");
    556  1.44       mrg #else
    557   1.1       cgd 	(void)printf(" r b w   avm   fre  flt  re  pi  po  fr  sr ");
    558  1.44       mrg #endif
    559   1.1       cgd 	for (i = 0; i < dk_ndrive; i++)
    560  1.29   thorpej 		if (dk_select[i])
    561   1.1       cgd 			(void)printf("%c%c ", dr_name[i][0],
    562   1.1       cgd 			    dr_name[i][strlen(dr_name[i]) - 1]);
    563   1.1       cgd 	(void)printf("  in   sy  cs us sy id\n");
    564   1.1       cgd 	hdrcnt = winlines - 2;
    565   1.1       cgd }
    566   1.1       cgd 
    567   1.1       cgd /*
    568   1.1       cgd  * Force a header to be prepended to the next output.
    569   1.1       cgd  */
    570   1.1       cgd void
    571  1.38       mrg needhdr(dummy)
    572  1.38       mrg 	int dummy;
    573   1.1       cgd {
    574   1.1       cgd 
    575   1.1       cgd 	hdrcnt = 1;
    576   1.1       cgd }
    577   1.1       cgd 
    578  1.38       mrg long
    579   1.1       cgd pct(top, bot)
    580   1.1       cgd 	long top, bot;
    581   1.1       cgd {
    582  1.13       cgd 	long ans;
    583  1.13       cgd 
    584   1.1       cgd 	if (bot == 0)
    585   1.1       cgd 		return(0);
    586  1.13       cgd 	ans = (quad_t)top * 100 / bot;
    587  1.13       cgd 	return (ans);
    588   1.1       cgd }
    589   1.1       cgd 
    590  1.38       mrg #define	PCT(top, bot) (int)pct((long)(top), (long)(bot))
    591   1.1       cgd 
    592   1.1       cgd void
    593  1.13       cgd dosum()
    594   1.1       cgd {
    595   1.1       cgd 	struct nchstats nchstats;
    596   1.1       cgd 	long nchtotal;
    597   1.1       cgd 
    598  1.41       mrg #if defined(UVM)
    599  1.41       mrg 	int	mib[2];
    600  1.41       mrg 	size_t	size;
    601  1.41       mrg 
    602  1.41       mrg 	size = sizeof(uvmexp);
    603  1.41       mrg 	mib[0] = CTL_VM;
    604  1.41       mrg 	mib[1] = VM_UVMEXP;
    605  1.41       mrg 	if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
    606  1.41       mrg 		printf("can't get uvmexp: %s\n", strerror(errno));
    607  1.53     perry 		memset(&uvmexp, 0, sizeof(uvmexp));
    608  1.41       mrg 	}
    609  1.41       mrg 
    610  1.44       mrg 	(void)printf("%9u bytes per page\n", uvmexp.pagesize);
    611  1.44       mrg 
    612  1.44       mrg 	(void)printf("%9u pages managed\n", uvmexp.npages);
    613  1.44       mrg 	(void)printf("%9u pages free\n", uvmexp.free);
    614  1.44       mrg 	(void)printf("%9u pages active\n", uvmexp.active);
    615  1.44       mrg 	(void)printf("%9u pages inactive\n", uvmexp.inactive);
    616  1.44       mrg 	(void)printf("%9u pages paging\n", uvmexp.paging);
    617  1.44       mrg 	(void)printf("%9u pages wired\n", uvmexp.wired);
    618  1.44       mrg 	(void)printf("%9u reserve pagedaemon pages\n",
    619  1.44       mrg 	    uvmexp.reserve_pagedaemon);
    620  1.44       mrg 	(void)printf("%9u reserve kernel pages\n", uvmexp.reserve_kernel);
    621  1.44       mrg 
    622  1.44       mrg 	(void)printf("%9u minimum free pages\n", uvmexp.freemin);
    623  1.44       mrg 	(void)printf("%9u target free pages\n", uvmexp.freetarg);
    624  1.44       mrg 	(void)printf("%9u target inactive pages\n", uvmexp.inactarg);
    625  1.44       mrg 	(void)printf("%9u maximum wired pages\n", uvmexp.wiredmax);
    626  1.44       mrg 
    627  1.44       mrg 	(void)printf("%9u swap devices\n", uvmexp.nswapdev);
    628  1.44       mrg 	(void)printf("%9u swap pages\n", uvmexp.swpages);
    629  1.44       mrg 	(void)printf("%9u swap pages in use\n", uvmexp.swpginuse);
    630  1.44       mrg 	(void)printf("%9u swap allocations\n", uvmexp.nswget);
    631  1.44       mrg 	(void)printf("%9u anons\n", uvmexp.nanon);
    632  1.44       mrg 	(void)printf("%9u free anons\n", uvmexp.nfreeanon);
    633  1.44       mrg 
    634  1.43       mrg 	(void)printf("%9u total faults taken\n", uvmexp.faults);
    635  1.43       mrg 	(void)printf("%9u traps\n", uvmexp.traps);
    636  1.43       mrg 	(void)printf("%9u device interrupts\n", uvmexp.intrs);
    637  1.43       mrg 	(void)printf("%9u cpu context switches\n", uvmexp.swtch);
    638  1.43       mrg 	(void)printf("%9u software interrupts\n", uvmexp.softs);
    639  1.43       mrg 	(void)printf("%9u system calls\n", uvmexp.syscalls);
    640  1.44       mrg 	(void)printf("%9u pagein requests\n", uvmexp.pageins / CLSIZE);
    641  1.44       mrg 	(void)printf("%9u pageout requests\n", uvmexp.pdpageouts / CLSIZE);
    642  1.43       mrg 	(void)printf("%9u swap ins\n", uvmexp.swapins);
    643  1.43       mrg 	(void)printf("%9u swap outs\n", uvmexp.swapouts);
    644  1.44       mrg 	(void)printf("%9u pages swapped in\n", uvmexp.pgswapin / CLSIZE);
    645  1.44       mrg 	(void)printf("%9u pages swapped out\n", uvmexp.pgswapout / CLSIZE);
    646  1.43       mrg 	(void)printf("%9u forks total\n", uvmexp.forks);
    647  1.43       mrg 	(void)printf("%9u forks blocked parent\n", uvmexp.forks_ppwait);
    648  1.43       mrg 	(void)printf("%9u forks shared address space with parent\n",
    649  1.43       mrg 	    uvmexp.forks_sharevm);
    650  1.44       mrg 
    651  1.44       mrg 	(void)printf("%9u faults with no memory\n", uvmexp.fltnoram);
    652  1.44       mrg 	(void)printf("%9u faults with no anons\n", uvmexp.fltnoanon);
    653  1.43       mrg 	(void)printf("%9u faults had to wait on pages\n", uvmexp.fltpgwait);
    654  1.43       mrg 	(void)printf("%9u faults found released page\n", uvmexp.fltpgrele);
    655  1.43       mrg 	(void)printf("%9u faults relock (%u ok)\n", uvmexp.fltrelck,
    656  1.43       mrg 	    uvmexp.fltrelckok);
    657  1.43       mrg 	(void)printf("%9u anon page faults\n", uvmexp.fltanget);
    658  1.43       mrg 	(void)printf("%9u anon retry faults\n", uvmexp.fltanretry);
    659  1.43       mrg 	(void)printf("%9u amap copy faults\n", uvmexp.fltamcopy);
    660  1.43       mrg 	(void)printf("%9u neighbour anon page faults\n", uvmexp.fltnamap);
    661  1.43       mrg 	(void)printf("%9u neighbour object page faults\n", uvmexp.fltnomap);
    662  1.43       mrg 	(void)printf("%9u locked pager get faults\n", uvmexp.fltlget);
    663  1.43       mrg 	(void)printf("%9u unlocked pager get faults\n", uvmexp.fltget);
    664  1.43       mrg 	(void)printf("%9u anon faults\n", uvmexp.flt_anon);
    665  1.43       mrg 	(void)printf("%9u anon copy on write faults\n", uvmexp.flt_acow);
    666  1.43       mrg 	(void)printf("%9u object faults\n", uvmexp.flt_obj);
    667  1.43       mrg 	(void)printf("%9u promote copy faults\n", uvmexp.flt_prcopy);
    668  1.43       mrg 	(void)printf("%9u promote zero fill faults\n", uvmexp.flt_przero);
    669  1.44       mrg 
    670  1.44       mrg 	(void)printf("%9u times daemon wokeup\n",uvmexp.pdwoke);
    671  1.44       mrg 	(void)printf("%9u revolutions of the clock hand\n", uvmexp.pdrevs);
    672  1.44       mrg 	(void)printf("%9u times daemon attempted swapout\n", uvmexp.pdswout);
    673  1.44       mrg 	(void)printf("%9u pages freed by daemon\n", uvmexp.pdfreed);
    674  1.44       mrg 	(void)printf("%9u pages scanned by daemon\n", uvmexp.pdscans);
    675  1.44       mrg 	(void)printf("%9u anonymous pages scanned by daemon\n", uvmexp.pdanscan);
    676  1.44       mrg 	(void)printf("%9u object pages scanned by daemon\n", uvmexp.pdobscan);
    677  1.44       mrg 	(void)printf("%9u pages reactivated\n", uvmexp.pdreact);
    678  1.44       mrg 	(void)printf("%9u pages found busy by daemon\n", uvmexp.pdbusy);
    679  1.44       mrg 	(void)printf("%9u total pending pageouts\n", uvmexp.pdpending);
    680  1.44       mrg 	(void)printf("%9u pages deactivated\n", uvmexp.pddeact);
    681  1.41       mrg #else
    682  1.13       cgd 	kread(X_SUM, &sum, sizeof(sum));
    683  1.13       cgd 	(void)printf("%9u cpu context switches\n", sum.v_swtch);
    684  1.13       cgd 	(void)printf("%9u device interrupts\n", sum.v_intr);
    685  1.13       cgd 	(void)printf("%9u software interrupts\n", sum.v_soft);
    686  1.13       cgd 	(void)printf("%9u traps\n", sum.v_trap);
    687  1.13       cgd 	(void)printf("%9u system calls\n", sum.v_syscall);
    688  1.13       cgd 	(void)printf("%9u total faults taken\n", sum.v_faults);
    689  1.13       cgd 	(void)printf("%9u swap ins\n", sum.v_swpin);
    690  1.13       cgd 	(void)printf("%9u swap outs\n", sum.v_swpout);
    691  1.13       cgd 	(void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
    692  1.13       cgd 	(void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
    693  1.13       cgd 	(void)printf("%9u page ins\n", sum.v_pageins);
    694  1.13       cgd 	(void)printf("%9u page outs\n", sum.v_pageouts);
    695  1.13       cgd 	(void)printf("%9u pages paged in\n", sum.v_pgpgin);
    696  1.13       cgd 	(void)printf("%9u pages paged out\n", sum.v_pgpgout);
    697  1.13       cgd 	(void)printf("%9u pages reactivated\n", sum.v_reactivated);
    698  1.13       cgd 	(void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
    699  1.13       cgd 	(void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
    700  1.13       cgd 	(void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
    701  1.13       cgd 	(void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
    702  1.13       cgd 	(void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
    703  1.13       cgd 	(void)printf("%9u VM object cache lookups\n", sum.v_lookups);
    704  1.13       cgd 	(void)printf("%9u VM object hits\n", sum.v_hits);
    705  1.13       cgd 	(void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
    706  1.13       cgd 	(void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
    707  1.13       cgd 	(void)printf("%9u pages freed by daemon\n", sum.v_dfree);
    708  1.13       cgd 	(void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
    709  1.13       cgd 	(void)printf("%9u pages free\n", sum.v_free_count);
    710  1.13       cgd 	(void)printf("%9u pages wired down\n", sum.v_wire_count);
    711  1.13       cgd 	(void)printf("%9u pages active\n", sum.v_active_count);
    712  1.13       cgd 	(void)printf("%9u pages inactive\n", sum.v_inactive_count);
    713  1.13       cgd 	(void)printf("%9u bytes per page\n", sum.v_page_size);
    714  1.37       mrg 	(void)printf("%9u target inactive pages\n", sum.v_inactive_target);
    715  1.37       mrg 	(void)printf("%9u target free pages\n", sum.v_free_target);
    716  1.37       mrg 	(void)printf("%9u minimum free pages\n", sum.v_free_min);
    717   1.1       cgd #endif
    718   1.1       cgd 	kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
    719   1.1       cgd 	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
    720   1.1       cgd 	    nchstats.ncs_badhits + nchstats.ncs_falsehits +
    721   1.1       cgd 	    nchstats.ncs_miss + nchstats.ncs_long;
    722   1.1       cgd 	(void)printf("%9ld total name lookups\n", nchtotal);
    723   1.1       cgd 	(void)printf(
    724   1.1       cgd 	    "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
    725   1.1       cgd 	    "", PCT(nchstats.ncs_goodhits, nchtotal),
    726   1.1       cgd 	    PCT(nchstats.ncs_neghits, nchtotal),
    727   1.1       cgd 	    PCT(nchstats.ncs_pass2, nchtotal));
    728   1.1       cgd 	(void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
    729   1.1       cgd 	    PCT(nchstats.ncs_badhits, nchtotal),
    730   1.1       cgd 	    PCT(nchstats.ncs_falsehits, nchtotal),
    731   1.1       cgd 	    PCT(nchstats.ncs_long, nchtotal));
    732   1.1       cgd }
    733   1.1       cgd 
    734   1.1       cgd void
    735   1.1       cgd doforkst()
    736   1.1       cgd {
    737  1.41       mrg #if defined(UVM)
    738  1.41       mrg 	int	mib[2];
    739  1.41       mrg 	size_t	size;
    740  1.41       mrg 
    741  1.41       mrg 	size = sizeof(uvmexp);
    742  1.41       mrg 	mib[0] = CTL_VM;
    743  1.41       mrg 	mib[1] = VM_UVMEXP;
    744  1.41       mrg 	if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
    745  1.41       mrg 		printf("can't get uvmexp: %s\n", strerror(errno));
    746  1.53     perry 		memset(&uvmexp, 0, sizeof(uvmexp));
    747  1.41       mrg 	}
    748  1.41       mrg 	(void)printf("%u forks total\n", uvmexp.forks);
    749  1.41       mrg 	(void)printf("%u forks blocked parent\n", uvmexp.forks_ppwait);
    750  1.41       mrg 	(void)printf("%u forks shared address space with parent\n",
    751  1.41       mrg 	    uvmexp.forks_sharevm);
    752  1.41       mrg #else
    753   1.1       cgd 
    754  1.40   thorpej 	kread(X_SUM, &sum, sizeof(sum));
    755  1.40   thorpej 	(void)printf("%u forks total\n", sum.v_forks);
    756  1.40   thorpej 	(void)printf("%u forks blocked parent\n", sum.v_forks_ppwait);
    757  1.40   thorpej 	(void)printf("%u forks shared address space with parent\n",
    758  1.40   thorpej 	    sum.v_forks_sharevm);
    759  1.41       mrg #endif
    760   1.1       cgd }
    761   1.1       cgd 
    762   1.1       cgd void
    763   1.1       cgd dkstats()
    764   1.1       cgd {
    765  1.38       mrg 	int dn, state;
    766   1.1       cgd 	double etime;
    767   1.1       cgd 
    768  1.29   thorpej 	/* Calculate disk stat deltas. */
    769  1.29   thorpej 	dkswap();
    770   1.1       cgd 	etime = 0;
    771   1.1       cgd 	for (state = 0; state < CPUSTATES; ++state) {
    772  1.29   thorpej 		etime += cur.cp_time[state];
    773   1.1       cgd 	}
    774   1.1       cgd 	if (etime == 0)
    775   1.1       cgd 		etime = 1;
    776   1.1       cgd 	etime /= hz;
    777   1.1       cgd 	for (dn = 0; dn < dk_ndrive; ++dn) {
    778  1.29   thorpej 		if (!dk_select[dn])
    779   1.1       cgd 			continue;
    780  1.29   thorpej 		(void)printf("%2.0f ", cur.dk_xfer[dn] / etime);
    781   1.1       cgd 	}
    782   1.1       cgd }
    783   1.1       cgd 
    784   1.1       cgd void
    785   1.1       cgd cpustats()
    786   1.1       cgd {
    787  1.38       mrg 	int state;
    788   1.1       cgd 	double pct, total;
    789   1.1       cgd 
    790   1.1       cgd 	total = 0;
    791   1.1       cgd 	for (state = 0; state < CPUSTATES; ++state)
    792  1.29   thorpej 		total += cur.cp_time[state];
    793   1.1       cgd 	if (total)
    794   1.1       cgd 		pct = 100 / total;
    795   1.1       cgd 	else
    796   1.1       cgd 		pct = 0;
    797  1.29   thorpej 	(void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct);
    798  1.29   thorpej 	(void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct);
    799  1.29   thorpej 	(void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
    800   1.1       cgd }
    801   1.1       cgd 
    802  1.23      phil #if defined(pc532)
    803  1.24      phil /* To get struct iv ...*/
    804  1.24      phil #define _KERNEL
    805  1.23      phil #include <machine/psl.h>
    806  1.24      phil #undef _KERNEL
    807  1.23      phil void
    808  1.23      phil dointr()
    809  1.23      phil {
    810  1.38       mrg 	long i, j, inttotal, uptime;
    811  1.23      phil 	static char iname[64];
    812  1.23      phil 	struct iv ivt[32], *ivp = ivt;
    813  1.23      phil 
    814  1.23      phil 	iname[63] = '\0';
    815  1.23      phil 	uptime = getuptime();
    816  1.23      phil 	kread(X_IVT, ivp, sizeof(ivt));
    817  1.23      phil 
    818  1.23      phil 	for (i = 0; i < 2; i++) {
    819  1.23      phil 		(void)printf("%sware interrupts:\n", i ? "\nsoft" : "hard");
    820  1.23      phil 		(void)printf("interrupt       total     rate\n");
    821  1.23      phil 		inttotal = 0;
    822  1.23      phil 		for (j = 0; j < 16; j++, ivp++) {
    823  1.23      phil 			if (ivp->iv_vec && ivp->iv_use && ivp->iv_cnt) {
    824  1.23      phil 				if (kvm_read(kd, (u_long)ivp->iv_use, iname, 63) != 63) {
    825  1.23      phil 					(void)fprintf(stderr, "vmstat: iv_use: %s\n",
    826  1.23      phil 					    kvm_geterr(kd));
    827  1.23      phil 					exit(1);
    828  1.23      phil 				}
    829  1.23      phil 				(void)printf("%-12s %8ld %8ld\n", iname,
    830  1.23      phil 				    ivp->iv_cnt, ivp->iv_cnt / uptime);
    831  1.23      phil 				inttotal += ivp->iv_cnt;
    832  1.23      phil 			}
    833  1.23      phil 		}
    834  1.23      phil 		(void)printf("Total        %8ld %8ld\n",
    835  1.23      phil 		    inttotal, inttotal / uptime);
    836  1.23      phil 	}
    837  1.23      phil }
    838  1.23      phil #else
    839   1.1       cgd void
    840   1.1       cgd dointr()
    841   1.1       cgd {
    842  1.38       mrg 	long *intrcnt, inttotal, uptime;
    843  1.38       mrg 	int nintr, inamlen;
    844  1.38       mrg 	char *intrname;
    845  1.28       cgd 	struct evcntlist allevents;
    846  1.28       cgd 	struct evcnt evcnt, *evptr;
    847  1.18        pk 	struct device dev;
    848   1.1       cgd 
    849   1.1       cgd 	uptime = getuptime();
    850  1.13       cgd 	nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
    851  1.13       cgd 	inamlen =
    852  1.13       cgd 	    namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
    853   1.1       cgd 	intrcnt = malloc((size_t)nintr);
    854   1.1       cgd 	intrname = malloc((size_t)inamlen);
    855   1.1       cgd 	if (intrcnt == NULL || intrname == NULL) {
    856   1.1       cgd 		(void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
    857   1.1       cgd 		exit(1);
    858   1.1       cgd 	}
    859   1.1       cgd 	kread(X_INTRCNT, intrcnt, (size_t)nintr);
    860   1.1       cgd 	kread(X_INTRNAMES, intrname, (size_t)inamlen);
    861  1.27       cgd 	(void)printf("interrupt         total     rate\n");
    862   1.1       cgd 	inttotal = 0;
    863   1.1       cgd 	nintr /= sizeof(long);
    864   1.1       cgd 	while (--nintr >= 0) {
    865   1.1       cgd 		if (*intrcnt)
    866  1.27       cgd 			(void)printf("%-14s %8ld %8ld\n", intrname,
    867   1.1       cgd 			    *intrcnt, *intrcnt / uptime);
    868   1.1       cgd 		intrname += strlen(intrname) + 1;
    869   1.1       cgd 		inttotal += *intrcnt++;
    870   1.1       cgd 	}
    871  1.18        pk 	kread(X_ALLEVENTS, &allevents, sizeof allevents);
    872  1.28       cgd 	evptr = allevents.tqh_first;
    873  1.28       cgd 	while (evptr) {
    874  1.28       cgd 		if (kvm_read(kd, (long)evptr, (void *)&evcnt,
    875  1.18        pk 		    sizeof evcnt) != sizeof evcnt) {
    876  1.38       mrg 			(void)fprintf(stderr, "vmstat: event chain trashed: %s\n",
    877  1.18        pk 			    kvm_geterr(kd));
    878  1.18        pk 			exit(1);
    879  1.18        pk 		}
    880  1.32       cgd 		if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev,
    881  1.32       cgd 		    sizeof dev) != sizeof dev) {
    882  1.38       mrg 			(void)fprintf(stderr, "vmstat: event chain trashed: %s\n",
    883  1.32       cgd 			    kvm_geterr(kd));
    884  1.32       cgd 			exit(1);
    885  1.18        pk 		}
    886  1.32       cgd 		if (evcnt.ev_count)
    887  1.32       cgd 			(void)printf("%-14s %8ld %8ld\n", dev.dv_xname,
    888  1.38       mrg 			    (long)evcnt.ev_count, evcnt.ev_count / uptime);
    889  1.32       cgd 		inttotal += evcnt.ev_count++;
    890  1.32       cgd 
    891  1.28       cgd 		evptr = evcnt.ev_list.tqe_next;
    892  1.18        pk 	}
    893  1.27       cgd 	(void)printf("Total          %8ld %8ld\n", inttotal, inttotal / uptime);
    894   1.1       cgd }
    895  1.23      phil #endif
    896   1.1       cgd 
    897   1.1       cgd /*
    898   1.1       cgd  * These names are defined in <sys/malloc.h>.
    899   1.1       cgd  */
    900   1.1       cgd char *kmemnames[] = INITKMEMNAMES;
    901   1.1       cgd 
    902   1.1       cgd void
    903   1.1       cgd domem()
    904   1.1       cgd {
    905  1.38       mrg 	struct kmembuckets *kp;
    906  1.38       mrg 	struct kmemstats *ks;
    907  1.38       mrg 	int i, j;
    908  1.13       cgd 	int len, size, first;
    909  1.13       cgd 	long totuse = 0, totfree = 0, totreq = 0;
    910  1.13       cgd 	char *name;
    911  1.13       cgd 	struct kmemstats kmemstats[M_LAST];
    912   1.1       cgd 	struct kmembuckets buckets[MINBUCKET + 16];
    913   1.1       cgd 
    914   1.1       cgd 	kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
    915  1.34   thorpej 	for (first = 1, i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16;
    916  1.34   thorpej 	    i++, kp++) {
    917   1.1       cgd 		if (kp->kb_calls == 0)
    918   1.1       cgd 			continue;
    919  1.34   thorpej 		if (first) {
    920  1.34   thorpej 			(void)printf("Memory statistics by bucket size\n");
    921  1.34   thorpej 			(void)printf(
    922  1.34   thorpej 		 "    Size   In Use   Free   Requests  HighWater  Couldfree\n");
    923  1.34   thorpej 			first = 0;
    924  1.34   thorpej 		}
    925   1.1       cgd 		size = 1 << i;
    926   1.1       cgd 		(void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
    927   1.1       cgd 			kp->kb_total - kp->kb_totalfree,
    928   1.1       cgd 			kp->kb_totalfree, kp->kb_calls,
    929   1.1       cgd 			kp->kb_highwat, kp->kb_couldfree);
    930   1.1       cgd 		totfree += size * kp->kb_totalfree;
    931  1.34   thorpej 	}
    932  1.34   thorpej 
    933  1.34   thorpej 	/*
    934  1.34   thorpej 	 * If kmem statistics are not being gathered by the kernel,
    935  1.34   thorpej 	 * first will still be 1.
    936  1.34   thorpej 	 */
    937  1.34   thorpej 	if (first) {
    938  1.34   thorpej 		printf(
    939  1.34   thorpej 		    "Kmem statistics are not being gathered by the kernel.\n");
    940  1.34   thorpej 		return;
    941   1.1       cgd 	}
    942   1.1       cgd 
    943   1.1       cgd 	kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
    944  1.13       cgd 	(void)printf("\nMemory usage type by bucket size\n");
    945  1.13       cgd 	(void)printf("    Size  Type(s)\n");
    946  1.13       cgd 	kp = &buckets[MINBUCKET];
    947  1.13       cgd 	for (j =  1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
    948  1.13       cgd 		if (kp->kb_calls == 0)
    949  1.13       cgd 			continue;
    950  1.13       cgd 		first = 1;
    951  1.13       cgd 		len = 8;
    952  1.13       cgd 		for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
    953  1.13       cgd 			if (ks->ks_calls == 0)
    954  1.13       cgd 				continue;
    955  1.13       cgd 			if ((ks->ks_size & j) == 0)
    956  1.13       cgd 				continue;
    957  1.35        is 			if (kmemnames[i] == 0) {
    958  1.35        is 				kmemnames[i] = malloc(10);
    959  1.35        is 						/* strlen("undef/")+3+1);*/
    960  1.35        is 				snprintf(kmemnames[i], 10, "undef/%d", i);
    961  1.35        is 						/* same 10 as above!!! */
    962  1.35        is 			}
    963  1.35        is 			name = kmemnames[i];
    964  1.13       cgd 			len += 2 + strlen(name);
    965  1.13       cgd 			if (first)
    966  1.13       cgd 				printf("%8d  %s", j, name);
    967  1.13       cgd 			else
    968  1.13       cgd 				printf(",");
    969  1.13       cgd 			if (len >= 80) {
    970  1.13       cgd 				printf("\n\t ");
    971  1.13       cgd 				len = 10 + strlen(name);
    972  1.13       cgd 			}
    973  1.13       cgd 			if (!first)
    974  1.13       cgd 				printf(" %s", name);
    975  1.13       cgd 			first = 0;
    976  1.13       cgd 		}
    977  1.13       cgd 		printf("\n");
    978  1.13       cgd 	}
    979  1.13       cgd 
    980   1.1       cgd 	(void)printf(
    981  1.13       cgd 	    "\nMemory statistics by type                        Type  Kern\n");
    982  1.13       cgd 	(void)printf(
    983  1.36        is "         Type  InUse MemUse HighUse  Limit Requests Limit Limit Size(s)\n");
    984  1.13       cgd 	for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
    985   1.1       cgd 		if (ks->ks_calls == 0)
    986   1.1       cgd 			continue;
    987  1.36        is 		(void)printf("%14s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
    988   1.1       cgd 		    kmemnames[i] ? kmemnames[i] : "undefined",
    989   1.1       cgd 		    ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
    990   1.1       cgd 		    (ks->ks_maxused + 1023) / 1024,
    991   1.1       cgd 		    (ks->ks_limit + 1023) / 1024, ks->ks_calls,
    992   1.1       cgd 		    ks->ks_limblocks, ks->ks_mapblocks);
    993  1.13       cgd 		first = 1;
    994  1.13       cgd 		for (j =  1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
    995  1.13       cgd 			if ((ks->ks_size & j) == 0)
    996  1.13       cgd 				continue;
    997  1.13       cgd 			if (first)
    998  1.13       cgd 				printf("  %d", j);
    999  1.13       cgd 			else
   1000  1.13       cgd 				printf(",%d", j);
   1001  1.13       cgd 			first = 0;
   1002  1.13       cgd 		}
   1003  1.13       cgd 		printf("\n");
   1004   1.1       cgd 		totuse += ks->ks_memuse;
   1005   1.1       cgd 		totreq += ks->ks_calls;
   1006   1.1       cgd 	}
   1007  1.13       cgd 	(void)printf("\nMemory Totals:  In Use    Free    Requests\n");
   1008  1.13       cgd 	(void)printf("              %7ldK %6ldK    %8ld\n",
   1009  1.13       cgd 	     (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
   1010  1.51        pk }
   1011  1.51        pk 
   1012  1.51        pk void
   1013  1.51        pk dopool()
   1014  1.51        pk {
   1015  1.51        pk 	int first;
   1016  1.51        pk 	long addr;
   1017  1.51        pk 	long total = 0, inuse = 0;
   1018  1.51        pk 	TAILQ_HEAD(,pool) pool_head;
   1019  1.51        pk 	struct pool pool, *pp = &pool;
   1020  1.51        pk 
   1021  1.51        pk 	kread(X_POOLHEAD, &pool_head, sizeof(pool_head));
   1022  1.51        pk 	addr = (long)TAILQ_FIRST(&pool_head);
   1023  1.51        pk 
   1024  1.51        pk 	for (first = 1; addr != 0; ) {
   1025  1.51        pk 		char name[32], maxp[32];
   1026  1.51        pk 		if (kvm_read(kd, addr, (void *)pp, sizeof *pp) != sizeof *pp) {
   1027  1.51        pk 			(void)fprintf(stderr, "vmstat: pool chain trashed: %s\n",
   1028  1.51        pk 			    kvm_geterr(kd));
   1029  1.51        pk 			exit(1);
   1030  1.51        pk 		}
   1031  1.51        pk 		if (kvm_read(kd, (long)pp->pr_wchan, name, sizeof name) < 0) {
   1032  1.51        pk 			(void)fprintf(stderr, "vmstat: pool name trashed: %s\n",
   1033  1.51        pk 			    kvm_geterr(kd));
   1034  1.51        pk 			exit(1);
   1035  1.51        pk 		}
   1036  1.51        pk 		name[31]='\0';
   1037  1.51        pk 
   1038  1.51        pk 		if (first) {
   1039  1.51        pk 			(void)printf("Memory resource pool statistics\n");
   1040  1.51        pk 			(void)printf(
   1041  1.52   thorpej 			"%16s %6s %8s %8s %8s %7s %7s %6s %6s %6s %6s %6s\n",
   1042  1.51        pk 		 		"Name",
   1043  1.51        pk 				"Size",
   1044  1.51        pk 				"Requests",
   1045  1.51        pk 				"Failed",
   1046  1.51        pk 				"Releases",
   1047  1.51        pk 				"Pagereq",
   1048  1.51        pk 				"Pagerel",
   1049  1.51        pk 				"Npage",
   1050  1.51        pk 				"Hiwat",
   1051  1.51        pk 				"Minpage",
   1052  1.52   thorpej 				"Maxpage",
   1053  1.52   thorpej 				"Idle");
   1054  1.51        pk 			first = 0;
   1055  1.51        pk 		}
   1056  1.51        pk 		if (pp->pr_maxpages == UINT_MAX)
   1057  1.51        pk 			sprintf(maxp, "inf");
   1058  1.51        pk 		else
   1059  1.51        pk 			sprintf(maxp, "%6u", pp->pr_maxpages);
   1060  1.51        pk 		(void)printf(
   1061  1.52   thorpej 		    "%16s %6u %8lu %8lu %8lu %7lu %7lu %6u %6u %6u %6s %6lu\n",
   1062  1.51        pk 			name,
   1063  1.51        pk 			pp->pr_size,
   1064  1.51        pk 			pp->pr_nget,
   1065  1.51        pk 			pp->pr_nfail,
   1066  1.51        pk 			pp->pr_nput,
   1067  1.51        pk 			pp->pr_npagealloc,
   1068  1.51        pk 			pp->pr_npagefree,
   1069  1.51        pk 			pp->pr_npages,
   1070  1.51        pk 			pp->pr_hiwat,
   1071  1.51        pk 			pp->pr_minpages,
   1072  1.52   thorpej 			maxp,
   1073  1.52   thorpej 			pp->pr_nidle);
   1074  1.51        pk 
   1075  1.51        pk 		inuse += (pp->pr_nget - pp->pr_nput) * pp->pr_size;
   1076  1.51        pk 		total += pp->pr_npages * pp->pr_pagesz;
   1077  1.51        pk 		addr = (long)TAILQ_NEXT(pp, pr_poollist);
   1078  1.51        pk 	}
   1079  1.51        pk 
   1080  1.51        pk 	printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n",
   1081  1.51        pk 		inuse/1024, total/1024, (double)(100 * inuse) / total);
   1082  1.51        pk 
   1083   1.1       cgd }
   1084   1.1       cgd 
   1085   1.1       cgd /*
   1086   1.1       cgd  * kread reads something from the kernel, given its nlist index.
   1087   1.1       cgd  */
   1088   1.1       cgd void
   1089   1.1       cgd kread(nlx, addr, size)
   1090   1.1       cgd 	int nlx;
   1091   1.1       cgd 	void *addr;
   1092   1.1       cgd 	size_t size;
   1093   1.1       cgd {
   1094  1.50   mycroft 	const char *sym;
   1095   1.1       cgd 
   1096  1.13       cgd 	if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
   1097  1.13       cgd 		sym = namelist[nlx].n_name;
   1098   1.1       cgd 		if (*sym == '_')
   1099   1.1       cgd 			++sym;
   1100   1.1       cgd 		(void)fprintf(stderr,
   1101  1.13       cgd 		    "vmstat: symbol %s not defined\n", sym);
   1102   1.1       cgd 		exit(1);
   1103   1.1       cgd 	}
   1104  1.13       cgd 	if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
   1105  1.13       cgd 		sym = namelist[nlx].n_name;
   1106   1.1       cgd 		if (*sym == '_')
   1107   1.1       cgd 			++sym;
   1108  1.13       cgd 		(void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd));
   1109   1.1       cgd 		exit(1);
   1110   1.1       cgd 	}
   1111   1.1       cgd }
   1112   1.1       cgd 
   1113  1.45   thorpej #if defined(UVM)
   1114  1.45   thorpej struct nlist histnl[] = {
   1115  1.45   thorpej 	{ "_uvm_histories" },
   1116  1.45   thorpej #define	X_UVM_HISTORIES		0
   1117  1.45   thorpej 	{ NULL },
   1118  1.45   thorpej };
   1119  1.45   thorpej 
   1120  1.45   thorpej /*
   1121  1.45   thorpej  * Traverse the UVM history buffers, performing the requested action.
   1122  1.45   thorpej  *
   1123  1.45   thorpej  * Note, we assume that if we're not listing, we're dumping.
   1124  1.45   thorpej  */
   1125  1.45   thorpej void
   1126  1.45   thorpej hist_traverse(todo, histname)
   1127  1.45   thorpej 	int todo;
   1128  1.45   thorpej 	const char *histname;
   1129  1.45   thorpej {
   1130  1.45   thorpej 	struct uvm_history_head histhead;
   1131  1.45   thorpej 	struct uvm_history hist, *histkva;
   1132  1.45   thorpej 	char *name = NULL;
   1133  1.45   thorpej 	size_t namelen = 0;
   1134  1.45   thorpej 
   1135  1.45   thorpej 	if (kvm_nlist(kd, histnl) != 0) {
   1136  1.45   thorpej 		printf("UVM history is not compiled into the kernel.\n");
   1137  1.45   thorpej 		return;
   1138  1.45   thorpej 	}
   1139  1.45   thorpej 
   1140  1.45   thorpej 	if (kvm_read(kd, histnl[X_UVM_HISTORIES].n_value, &histhead,
   1141  1.45   thorpej 	    sizeof(histhead)) != sizeof(histhead)) {
   1142  1.45   thorpej 		warnx("unable to read %s: %s",
   1143  1.45   thorpej 		    histnl[X_UVM_HISTORIES].n_name, kvm_geterr(kd));
   1144  1.45   thorpej 		return;
   1145  1.45   thorpej 	}
   1146  1.45   thorpej 
   1147  1.45   thorpej 	if (histhead.lh_first == NULL) {
   1148  1.45   thorpej 		printf("No active UVM history logs.\n");
   1149  1.45   thorpej 		return;
   1150  1.45   thorpej 	}
   1151  1.45   thorpej 
   1152  1.45   thorpej 	if (todo & HISTLIST)
   1153  1.45   thorpej 		printf("Active UVM histories:");
   1154  1.45   thorpej 
   1155  1.45   thorpej 	for (histkva = histhead.lh_first; histkva != NULL;
   1156  1.45   thorpej 	    histkva = hist.list.le_next) {
   1157  1.45   thorpej 		if (kvm_read(kd, (u_long)histkva, &hist, sizeof(hist)) !=
   1158  1.45   thorpej 		    sizeof(hist)) {
   1159  1.45   thorpej 			warnx("unable to read history at %p: %s",
   1160  1.45   thorpej 			    histkva, kvm_geterr(kd));
   1161  1.45   thorpej 			goto out;
   1162  1.45   thorpej 		}
   1163  1.45   thorpej 
   1164  1.45   thorpej 		if (hist.namelen > namelen) {
   1165  1.45   thorpej 			if (name != NULL)
   1166  1.45   thorpej 				free(name);
   1167  1.45   thorpej 			namelen = hist.namelen;
   1168  1.45   thorpej 			if ((name = malloc(namelen + 1)) == NULL)
   1169  1.45   thorpej 				err(1, "malloc history name");
   1170  1.45   thorpej 		}
   1171  1.45   thorpej 
   1172  1.45   thorpej 		if (kvm_read(kd, (u_long)hist.name, name, namelen) !=
   1173  1.45   thorpej 		    namelen) {
   1174  1.45   thorpej 			warnx("unable to read history name at %p: %s",
   1175  1.45   thorpej 			    hist.name, kvm_geterr(kd));
   1176  1.45   thorpej 			goto out;
   1177  1.45   thorpej 		}
   1178  1.45   thorpej 		name[namelen] = '\0';
   1179  1.45   thorpej 		if (todo & HISTLIST)
   1180  1.45   thorpej 			printf(" %s", name);
   1181  1.45   thorpej 		else {
   1182  1.45   thorpej 			/*
   1183  1.45   thorpej 			 * If we're dumping all histories, do it, else
   1184  1.45   thorpej 			 * check to see if this is the one we want.
   1185  1.45   thorpej 			 */
   1186  1.45   thorpej 			if (histname == NULL || strcmp(histname, name) == 0) {
   1187  1.45   thorpej 				if (histname == NULL)
   1188  1.45   thorpej 					printf("\nUVM history `%s':\n", name);
   1189  1.45   thorpej 				hist_dodump(&hist);
   1190  1.45   thorpej 			}
   1191  1.45   thorpej 		}
   1192  1.45   thorpej 	}
   1193  1.45   thorpej 
   1194  1.45   thorpej 	if (todo & HISTLIST)
   1195  1.45   thorpej 		printf("\n");
   1196  1.45   thorpej 
   1197  1.45   thorpej  out:
   1198  1.45   thorpej 	if (name != NULL)
   1199  1.45   thorpej 		free(name);
   1200  1.45   thorpej }
   1201  1.45   thorpej 
   1202  1.45   thorpej /*
   1203  1.45   thorpej  * Actually dump the history buffer at the specified KVA.
   1204  1.45   thorpej  */
   1205  1.45   thorpej void
   1206  1.45   thorpej hist_dodump(histp)
   1207  1.45   thorpej 	struct uvm_history *histp;
   1208  1.45   thorpej {
   1209  1.45   thorpej 	struct uvm_history_ent *histents, *e;
   1210  1.45   thorpej 	size_t histsize;
   1211  1.45   thorpej 	char *fmt = NULL, *fn = NULL;
   1212  1.45   thorpej 	size_t fmtlen = 0, fnlen = 0;
   1213  1.45   thorpej 	int i;
   1214  1.45   thorpej 
   1215  1.45   thorpej 	histsize = sizeof(struct uvm_history_ent) * histp->n;
   1216  1.45   thorpej 
   1217  1.45   thorpej 	if ((histents = malloc(histsize)) == NULL)
   1218  1.45   thorpej 		err(1, "malloc history entries");
   1219  1.45   thorpej 
   1220  1.45   thorpej 	memset(histents, 0, histsize);
   1221  1.45   thorpej 
   1222  1.45   thorpej 	if (kvm_read(kd, (u_long)histp->e, histents, histsize) != histsize) {
   1223  1.45   thorpej 		warnx("unable to read history entries at %p: %s",
   1224  1.45   thorpej 		    histp->e, kvm_geterr(kd));
   1225  1.45   thorpej 		goto out;
   1226  1.45   thorpej 	}
   1227  1.45   thorpej 
   1228  1.45   thorpej 	i = histp->f;
   1229  1.45   thorpej 	do {
   1230  1.45   thorpej 		e = &histents[i];
   1231  1.45   thorpej 		if (e->fmt != NULL) {
   1232  1.45   thorpej 			if (e->fmtlen > fmtlen) {
   1233  1.45   thorpej 				if (fmt != NULL)
   1234  1.45   thorpej 					free(fmt);
   1235  1.45   thorpej 				fmtlen = e->fmtlen;
   1236  1.45   thorpej 				if ((fmt = malloc(fmtlen + 1)) == NULL)
   1237  1.45   thorpej 					err(1, "malloc printf format");
   1238  1.45   thorpej 			}
   1239  1.45   thorpej 			if (e->fnlen > fnlen) {
   1240  1.45   thorpej 				if (fn != NULL)
   1241  1.45   thorpej 					free(fn);
   1242  1.45   thorpej 				fnlen = e->fnlen;
   1243  1.45   thorpej 				if ((fn = malloc(fnlen + 1)) == NULL)
   1244  1.45   thorpej 					err(1, "malloc function name");
   1245  1.45   thorpej 			}
   1246  1.45   thorpej 
   1247  1.45   thorpej 			if (kvm_read(kd, (u_long)e->fmt, fmt, fmtlen)
   1248  1.45   thorpej 			    != fmtlen) {
   1249  1.45   thorpej 				warnx("unable to read printf format "
   1250  1.45   thorpej 				    "at %p: %s", e->fmt, kvm_geterr(kd));
   1251  1.45   thorpej 				goto out;
   1252  1.45   thorpej 			}
   1253  1.45   thorpej 			fmt[fmtlen] = '\0';
   1254  1.45   thorpej 
   1255  1.45   thorpej 			if (kvm_read(kd, (u_long)e->fn, fn, fnlen) != fnlen) {
   1256  1.45   thorpej 				warnx("unable to read function name "
   1257  1.45   thorpej 				    "at %p: %s", e->fn, kvm_geterr(kd));
   1258  1.45   thorpej 				goto out;
   1259  1.45   thorpej 			}
   1260  1.45   thorpej 			fn[fnlen] = '\0';
   1261  1.45   thorpej 
   1262  1.45   thorpej 			printf("%06ld.%06ld ", e->tv.tv_sec, e->tv.tv_usec);
   1263  1.45   thorpej 			printf("%s#%ld: ", fn, e->call);
   1264  1.45   thorpej 			printf(fmt, e->v[0], e->v[1], e->v[2], e->v[3]);
   1265  1.45   thorpej 			printf("\n");
   1266  1.45   thorpej 		}
   1267  1.45   thorpej 		i = (i + 1) % histp->n;
   1268  1.45   thorpej 	} while (i != histp->f);
   1269  1.45   thorpej 
   1270  1.45   thorpej  out:
   1271  1.45   thorpej 	free(histents);
   1272  1.45   thorpej 	if (fmt != NULL)
   1273  1.45   thorpej 		free(fmt);
   1274  1.45   thorpej 	if (fn != NULL)
   1275  1.45   thorpej 		free(fn);
   1276  1.45   thorpej }
   1277  1.45   thorpej #endif /* UVM */
   1278  1.45   thorpej 
   1279   1.1       cgd void
   1280   1.1       cgd usage()
   1281   1.1       cgd {
   1282  1.47       mrg 
   1283  1.45   thorpej #if defined(UVM)
   1284   1.1       cgd 	(void)fprintf(stderr,
   1285  1.45   thorpej 	    "usage: vmstat [-fHilms] [-h histname] [-c count] [-M core] \
   1286   1.1       cgd [-N system] [-w wait] [disks]\n");
   1287  1.45   thorpej #else
   1288  1.45   thorpej 	(void)fprintf(stderr,
   1289  1.45   thorpej 	    "usage: vmstat [-fims] [-c count] [-M core] \
   1290  1.45   thorpej [-N system] [-w wait] [disks]\n");
   1291  1.45   thorpej #endif /* UVM */
   1292   1.1       cgd 	exit(1);
   1293   1.1       cgd }
   1294