Home | History | Annotate | Line # | Download | only in vmstat
vmstat.c revision 1.169
      1  1.169     pooka /* $NetBSD: vmstat.c,v 1.169 2010/07/07 11:42:18 pooka Exp $ */
      2   1.45   thorpej 
      3   1.45   thorpej /*-
      4  1.154        ad  * Copyright (c) 1998, 2000, 2001, 2007 The NetBSD Foundation, Inc.
      5   1.45   thorpej  * All rights reserved.
      6   1.45   thorpej  *
      7   1.87     lukem  * This code is derived from software contributed to The NetBSD Foundation by:
      8   1.87     lukem  *	- Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9   1.87     lukem  *	  NASA Ames Research Center.
     10   1.87     lukem  *	- Simon Burge and Luke Mewburn of Wasabi Systems, Inc.
     11   1.45   thorpej  *
     12   1.45   thorpej  * Redistribution and use in source and binary forms, with or without
     13   1.45   thorpej  * modification, are permitted provided that the following conditions
     14   1.45   thorpej  * are met:
     15   1.45   thorpej  * 1. Redistributions of source code must retain the above copyright
     16   1.45   thorpej  *    notice, this list of conditions and the following disclaimer.
     17   1.45   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     18   1.45   thorpej  *    notice, this list of conditions and the following disclaimer in the
     19   1.45   thorpej  *    documentation and/or other materials provided with the distribution.
     20   1.45   thorpej  *
     21   1.45   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22   1.45   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23   1.45   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24   1.45   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25   1.45   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26   1.45   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27   1.45   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28   1.45   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29   1.45   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30   1.45   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31   1.45   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     32   1.45   thorpej  */
     33   1.21       cgd 
     34    1.1       cgd /*
     35   1.13       cgd  * Copyright (c) 1980, 1986, 1991, 1993
     36   1.13       cgd  *	The Regents of the University of California.  All rights reserved.
     37    1.1       cgd  *
     38    1.1       cgd  * Redistribution and use in source and binary forms, with or without
     39    1.1       cgd  * modification, are permitted provided that the following conditions
     40    1.1       cgd  * are met:
     41    1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     42    1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     43    1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     44    1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     45    1.1       cgd  *    documentation and/or other materials provided with the distribution.
     46  1.117       agc  * 3. Neither the name of the University nor the names of its contributors
     47    1.1       cgd  *    may be used to endorse or promote products derived from this software
     48    1.1       cgd  *    without specific prior written permission.
     49    1.1       cgd  *
     50    1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     51    1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     52    1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     53    1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     54    1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     55    1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     56    1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     57    1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     58    1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     59    1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     60    1.1       cgd  * SUCH DAMAGE.
     61    1.1       cgd  */
     62    1.1       cgd 
     63   1.38       mrg #include <sys/cdefs.h>
     64    1.1       cgd #ifndef lint
     65  1.161     lukem __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\
     66  1.161     lukem  The Regents of the University of California.  All rights reserved.");
     67    1.1       cgd #endif /* not lint */
     68    1.1       cgd 
     69    1.1       cgd #ifndef lint
     70   1.21       cgd #if 0
     71   1.37       mrg static char sccsid[] = "@(#)vmstat.c	8.2 (Berkeley) 3/1/95";
     72   1.21       cgd #else
     73  1.169     pooka __RCSID("$NetBSD: vmstat.c,v 1.169 2010/07/07 11:42:18 pooka Exp $");
     74   1.21       cgd #endif
     75    1.1       cgd #endif /* not lint */
     76   1.57   thorpej 
     77   1.57   thorpej #define	__POOL_EXPOSE
     78    1.1       cgd 
     79    1.1       cgd #include <sys/param.h>
     80   1.87     lukem #include <sys/mount.h>
     81   1.87     lukem #include <sys/uio.h>
     82   1.87     lukem 
     83   1.87     lukem #include <sys/buf.h>
     84  1.146      yamt #include <sys/evcnt.h>
     85   1.87     lukem #include <sys/ioctl.h>
     86   1.87     lukem #include <sys/malloc.h>
     87  1.109   thorpej #include <sys/mallocvar.h>
     88    1.1       cgd #include <sys/namei.h>
     89   1.87     lukem #include <sys/pool.h>
     90   1.87     lukem #include <sys/proc.h>
     91   1.64     perry #include <sys/sched.h>
     92   1.87     lukem #include <sys/socket.h>
     93   1.13       cgd #include <sys/sysctl.h>
     94   1.87     lukem #include <sys/time.h>
     95   1.87     lukem #include <sys/user.h>
     96   1.67       mrg 
     97   1.67       mrg #include <uvm/uvm_extern.h>
     98   1.67       mrg #include <uvm/uvm_stat.h>
     99   1.67       mrg 
    100   1.87     lukem #include <net/if.h>
    101   1.87     lukem #include <netinet/in.h>
    102   1.87     lukem #include <netinet/in_var.h>
    103   1.87     lukem 
    104   1.87     lukem #include <ufs/ufs/inode.h>
    105   1.87     lukem 
    106   1.87     lukem #include <nfs/rpcv2.h>
    107   1.87     lukem #include <nfs/nfsproto.h>
    108   1.87     lukem #include <nfs/nfsnode.h>
    109   1.87     lukem 
    110   1.87     lukem #include <ctype.h>
    111   1.45   thorpej #include <err.h>
    112   1.87     lukem #include <errno.h>
    113   1.55    kleink #include <fcntl.h>
    114   1.87     lukem #include <kvm.h>
    115   1.87     lukem #include <limits.h>
    116    1.1       cgd #include <nlist.h>
    117   1.87     lukem #undef n_hash
    118   1.87     lukem #include <paths.h>
    119   1.22       jtc #include <signal.h>
    120    1.1       cgd #include <stdio.h>
    121   1.87     lukem #include <stddef.h>
    122    1.1       cgd #include <stdlib.h>
    123    1.1       cgd #include <string.h>
    124   1.87     lukem #include <time.h>
    125   1.87     lukem #include <unistd.h>
    126  1.104       mrg #include <util.h>
    127   1.87     lukem 
    128  1.140     blymn #include "drvstats.h"
    129   1.45   thorpej 
    130   1.90     lukem /*
    131   1.90     lukem  * General namelist
    132   1.90     lukem  */
    133   1.87     lukem struct nlist namelist[] =
    134   1.87     lukem {
    135   1.65    itojun #define	X_BOOTTIME	0
    136  1.153  christos 	{ .n_name = "_boottime" },
    137   1.75     enami #define	X_HZ		1
    138  1.153  christos 	{ .n_name = "_hz" },
    139   1.75     enami #define	X_STATHZ	2
    140  1.153  christos 	{ .n_name = "_stathz" },
    141   1.75     enami #define	X_NCHSTATS	3
    142  1.153  christos 	{ .n_name = "_nchstats" },
    143  1.133       chs #define	X_KMEMSTAT	4
    144  1.153  christos 	{ .n_name = "_kmemstatistics" },
    145  1.133       chs #define	X_KMEMBUCKETS	5
    146  1.153  christos 	{ .n_name = "_kmembuckets" },
    147  1.133       chs #define	X_ALLEVENTS	6
    148  1.153  christos 	{ .n_name = "_allevents" },
    149  1.133       chs #define	X_POOLHEAD	7
    150  1.153  christos 	{ .n_name = "_pool_head" },
    151  1.133       chs #define	X_UVMEXP	8
    152  1.153  christos 	{ .n_name = "_uvmexp" },
    153  1.145    kardel #define	X_TIME_SECOND	9
    154  1.153  christos 	{ .n_name = "_time_second" },
    155  1.147    kardel #define X_TIME		10
    156  1.153  christos 	{ .n_name = "_time" },
    157  1.147    kardel #define	X_NL_SIZE	11
    158  1.153  christos 	{ .n_name = NULL },
    159   1.90     lukem };
    160   1.90     lukem 
    161   1.90     lukem /*
    162  1.133       chs  * Namelist for pre-evcnt interrupt counters.
    163  1.133       chs  */
    164  1.133       chs struct nlist intrnl[] =
    165  1.133       chs {
    166  1.133       chs #define	X_INTRNAMES	0
    167  1.153  christos 	{ .n_name = "_intrnames" },
    168  1.133       chs #define	X_EINTRNAMES	1
    169  1.153  christos 	{ .n_name = "_eintrnames" },
    170  1.133       chs #define	X_INTRCNT	2
    171  1.153  christos 	{ .n_name = "_intrcnt" },
    172  1.133       chs #define	X_EINTRCNT	3
    173  1.153  christos 	{ .n_name = "_eintrcnt" },
    174  1.133       chs #define	X_INTRNL_SIZE	4
    175  1.153  christos 	{ .n_name = NULL },
    176  1.133       chs };
    177  1.133       chs 
    178  1.133       chs 
    179  1.133       chs /*
    180   1.90     lukem  * Namelist for hash statistics
    181   1.90     lukem  */
    182   1.90     lukem struct nlist hashnl[] =
    183   1.90     lukem {
    184   1.90     lukem #define	X_NFSNODE	0
    185  1.153  christos 	{ .n_name = "_nfsnodehash" },
    186   1.90     lukem #define	X_NFSNODETBL	1
    187  1.153  christos 	{ .n_name = "_nfsnodehashtbl" },
    188   1.90     lukem #define	X_IHASH		2
    189  1.153  christos 	{ .n_name = "_ihash" },
    190   1.90     lukem #define	X_IHASHTBL	3
    191  1.153  christos 	{ .n_name = "_ihashtbl" },
    192   1.90     lukem #define	X_BUFHASH	4
    193  1.153  christos 	{ .n_name = "_bufhash" },
    194   1.90     lukem #define	X_BUFHASHTBL	5
    195  1.153  christos 	{ .n_name = "_bufhashtbl" },
    196  1.122  junyoung #define	X_UIHASH	6
    197  1.153  christos 	{ .n_name = "_uihash" },
    198  1.122  junyoung #define	X_UIHASHTBL	7
    199  1.153  christos 	{ .n_name = "_uihashtbl" },
    200  1.122  junyoung #define	X_IFADDRHASH	8
    201  1.153  christos 	{ .n_name = "_in_ifaddrhash" },
    202  1.122  junyoung #define	X_IFADDRHASHTBL	9
    203  1.153  christos 	{ .n_name = "_in_ifaddrhashtbl" },
    204  1.122  junyoung #define	X_NCHASH	10
    205  1.153  christos 	{ .n_name = "_nchash" },
    206  1.122  junyoung #define	X_NCHASHTBL	11
    207  1.153  christos 	{ .n_name = "_nchashtbl" },
    208  1.122  junyoung #define	X_NCVHASH	12
    209  1.153  christos 	{ .n_name = "_ncvhash" },
    210  1.122  junyoung #define	X_NCVHASHTBL	13
    211  1.153  christos 	{ .n_name = "_ncvhashtbl" },
    212  1.122  junyoung #define X_HASHNL_SIZE	14	/* must be last */
    213  1.153  christos 	{ .n_name = NULL },
    214   1.90     lukem };
    215   1.87     lukem 
    216   1.90     lukem /*
    217   1.90     lukem  * Namelist for UVM histories
    218   1.90     lukem  */
    219   1.90     lukem struct nlist histnl[] =
    220   1.90     lukem {
    221  1.153  christos 	{ .n_name = "_uvm_histories" },
    222   1.90     lukem #define	X_UVM_HISTORIES		0
    223  1.153  christos 	{ .n_name = NULL },
    224    1.1       cgd };
    225    1.1       cgd 
    226   1.87     lukem 
    227  1.152  christos #define KILO	1024
    228   1.90     lukem 
    229   1.41       mrg struct	uvmexp uvmexp, ouvmexp;
    230   1.73    simonb int	ndrives;
    231    1.1       cgd 
    232    1.1       cgd int	winlines = 20;
    233    1.1       cgd 
    234   1.13       cgd kvm_t *kd;
    235   1.13       cgd 
    236   1.87     lukem #define	FORKSTAT	1<<0
    237   1.87     lukem #define	INTRSTAT	1<<1
    238   1.87     lukem #define	MEMSTAT		1<<2
    239   1.87     lukem #define	SUMSTAT		1<<3
    240   1.87     lukem #define	EVCNTSTAT	1<<4
    241   1.87     lukem #define	VMSTAT		1<<5
    242   1.87     lukem #define	HISTLIST	1<<6
    243   1.87     lukem #define	HISTDUMP	1<<7
    244   1.87     lukem #define	HASHSTAT	1<<8
    245   1.88     lukem #define	HASHLIST	1<<9
    246  1.130        he #define	VMTOTAL		1<<10
    247  1.154        ad #define	POOLCACHESTAT	1<<11
    248    1.1       cgd 
    249  1.151      yamt /*
    250  1.151      yamt  * Print single word.  `ovflow' is number of characters didn't fit
    251  1.151      yamt  * on the last word.  `fmt' is a format string to print this word.
    252  1.151      yamt  * It must contain asterisk for field width.  `width' is a width
    253  1.151      yamt  * occupied by this word.  `fixed' is a number of constant chars in
    254  1.151      yamt  * `fmt'.  `val' is a value to be printed using format string `fmt'.
    255  1.151      yamt  */
    256  1.151      yamt #define	PRWORD(ovflw, fmt, width, fixed, val) do {	\
    257  1.151      yamt 	(ovflw) += printf((fmt),			\
    258  1.151      yamt 	    (width) - (fixed) - (ovflw) > 0 ?		\
    259  1.151      yamt 	    (width) - (fixed) - (ovflw) : 0,		\
    260  1.151      yamt 	    (val)) - (width);				\
    261  1.151      yamt 	if ((ovflw) < 0)				\
    262  1.151      yamt 		(ovflw) = 0;				\
    263  1.151      yamt } while (/* CONSTCOND */0)
    264  1.151      yamt 
    265  1.151      yamt void	cpustats(int *);
    266   1.87     lukem void	deref_kptr(const void *, void *, size_t, const char *);
    267  1.151      yamt void	drvstats(int *);
    268   1.73    simonb void	doevcnt(int verbose);
    269   1.88     lukem void	dohashstat(int, int, const char *);
    270   1.73    simonb void	dointr(int verbose);
    271   1.73    simonb void	domem(void);
    272  1.126    simonb void	dopool(int, int);
    273  1.154        ad void	dopoolcache(void);
    274   1.73    simonb void	dosum(void);
    275  1.103   mycroft void	dovmstat(struct timespec *, int);
    276  1.130        he void	print_total_hdr(void);
    277  1.130        he void	dovmtotal(struct timespec *, int);
    278  1.133       chs void	kread(struct nlist *, int, void *, size_t);
    279  1.147    kardel int	kreadc(struct nlist *, int, void *, size_t);
    280   1.73    simonb void	needhdr(int);
    281   1.73    simonb long	getuptime(void);
    282   1.73    simonb void	printhdr(void);
    283   1.73    simonb long	pct(long, long);
    284   1.73    simonb void	usage(void);
    285   1.73    simonb void	doforkst(void);
    286   1.73    simonb 
    287   1.73    simonb void	hist_traverse(int, const char *);
    288   1.73    simonb void	hist_dodump(struct uvm_history *);
    289   1.73    simonb 
    290   1.73    simonb int	main(int, char **);
    291   1.73    simonb char	**choosedrives(char **);
    292   1.38       mrg 
    293   1.29   thorpej /* Namelist and memory file names. */
    294   1.29   thorpej char	*nlistf, *memf;
    295   1.29   thorpej 
    296   1.47       mrg /* allow old usage [vmstat 1] */
    297   1.47       mrg #define	BACKWARD_COMPATIBILITY
    298   1.47       mrg 
    299   1.38       mrg int
    300   1.75     enami main(int argc, char *argv[])
    301    1.1       cgd {
    302  1.126    simonb 	int c, todo, verbose, wide;
    303  1.103   mycroft 	struct timespec interval;
    304    1.1       cgd 	int reps;
    305   1.75     enami 	char errbuf[_POSIX2_LINE_MAX];
    306   1.75     enami 	gid_t egid = getegid();
    307   1.88     lukem 	const char *histname, *hashname;
    308  1.165     lukem 	size_t i;
    309    1.1       cgd 
    310   1.88     lukem 	histname = hashname = NULL;
    311   1.48       mrg 	(void)setegid(getgid());
    312   1.13       cgd 	memf = nlistf = NULL;
    313  1.126    simonb 	reps = todo = verbose = wide = 0;
    314  1.103   mycroft 	interval.tv_sec = 0;
    315  1.103   mycroft 	interval.tv_nsec = 0;
    316  1.154        ad 	while ((c = getopt(argc, argv, "Cc:efh:HilLM:mN:stu:UvWw:")) != -1) {
    317    1.1       cgd 		switch (c) {
    318    1.1       cgd 		case 'c':
    319    1.1       cgd 			reps = atoi(optarg);
    320    1.1       cgd 			break;
    321  1.154        ad 		case 'C':
    322  1.154        ad 			todo |= POOLCACHESTAT;
    323  1.154        ad 			break;
    324   1.66       cgd 		case 'e':
    325   1.66       cgd 			todo |= EVCNTSTAT;
    326   1.66       cgd 			break;
    327    1.1       cgd 		case 'f':
    328    1.1       cgd 			todo |= FORKSTAT;
    329    1.1       cgd 			break;
    330   1.45   thorpej 		case 'h':
    331   1.88     lukem 			hashname = optarg;
    332   1.88     lukem 			/* FALLTHROUGH */
    333   1.88     lukem 		case 'H':
    334   1.87     lukem 			todo |= HASHSTAT;
    335   1.45   thorpej 			break;
    336    1.1       cgd 		case 'i':
    337    1.1       cgd 			todo |= INTRSTAT;
    338    1.1       cgd 			break;
    339   1.45   thorpej 		case 'l':
    340   1.45   thorpej 			todo |= HISTLIST;
    341   1.45   thorpej 			break;
    342   1.88     lukem 		case 'L':
    343   1.88     lukem 			todo |= HASHLIST;
    344   1.88     lukem 			break;
    345    1.1       cgd 		case 'M':
    346   1.13       cgd 			memf = optarg;
    347    1.1       cgd 			break;
    348    1.1       cgd 		case 'm':
    349    1.1       cgd 			todo |= MEMSTAT;
    350    1.1       cgd 			break;
    351    1.1       cgd 		case 'N':
    352   1.13       cgd 			nlistf = optarg;
    353    1.1       cgd 			break;
    354    1.1       cgd 		case 's':
    355    1.1       cgd 			todo |= SUMSTAT;
    356    1.1       cgd 			break;
    357  1.130        he 		case 't':
    358  1.130        he 			todo |= VMTOTAL;
    359  1.130        he 			break;
    360   1.87     lukem 		case 'u':
    361   1.87     lukem 			histname = optarg;
    362   1.87     lukem 			/* FALLTHROUGH */
    363   1.87     lukem 		case 'U':
    364   1.87     lukem 			todo |= HISTDUMP;
    365   1.87     lukem 			break;
    366   1.66       cgd 		case 'v':
    367   1.87     lukem 			verbose++;
    368   1.66       cgd 			break;
    369  1.126    simonb 		case 'W':
    370  1.126    simonb 			wide++;
    371  1.126    simonb 			break;
    372    1.1       cgd 		case 'w':
    373  1.103   mycroft 			interval.tv_sec = atol(optarg);
    374    1.1       cgd 			break;
    375    1.1       cgd 		case '?':
    376    1.1       cgd 		default:
    377    1.1       cgd 			usage();
    378    1.1       cgd 		}
    379    1.1       cgd 	}
    380    1.1       cgd 	argc -= optind;
    381    1.1       cgd 	argv += optind;
    382    1.1       cgd 
    383    1.1       cgd 	if (todo == 0)
    384    1.1       cgd 		todo = VMSTAT;
    385    1.1       cgd 
    386   1.13       cgd 	/*
    387   1.48       mrg 	 * Discard setgid privileges.  If not the running kernel, we toss
    388   1.48       mrg 	 * them away totally so that bad guys can't print interesting stuff
    389   1.48       mrg 	 * from kernel memory, otherwise switch back to kmem for the
    390   1.48       mrg 	 * duration of the kvm_openfiles() call.
    391   1.13       cgd 	 */
    392   1.13       cgd 	if (nlistf != NULL || memf != NULL)
    393   1.48       mrg 		(void)setgid(getgid());
    394   1.48       mrg 	else
    395   1.48       mrg 		(void)setegid(egid);
    396   1.13       cgd 
    397   1.75     enami 	kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
    398   1.75     enami 	if (kd == NULL)
    399   1.87     lukem 		errx(1, "kvm_openfiles: %s", errbuf);
    400   1.48       mrg 
    401   1.95    simonb 	if (nlistf == NULL && memf == NULL)
    402   1.95    simonb 		(void)setgid(getgid());
    403    1.1       cgd 
    404   1.13       cgd 	if ((c = kvm_nlist(kd, namelist)) != 0) {
    405  1.147    kardel 		int doexit = 0;
    406   1.90     lukem 		if (c == -1)
    407   1.90     lukem 			errx(1, "kvm_nlist: %s %s", "namelist", kvm_geterr(kd));
    408  1.165     lukem 		for (i = 0; i < sizeof(namelist) / sizeof(namelist[0])-1; i++)
    409  1.165     lukem 			if (namelist[i].n_type == 0 &&
    410  1.165     lukem 			    i != X_TIME_SECOND &&
    411  1.165     lukem 			    i != X_TIME) {
    412  1.147    kardel 				if (doexit++ == 0)
    413  1.147    kardel 					(void)fprintf(stderr, "vmstat: undefined symbols:");
    414  1.153  christos 				(void)fprintf(stderr, " %s",
    415  1.165     lukem 				    namelist[i].n_name);
    416  1.147    kardel 			}
    417  1.147    kardel 		if (doexit) {
    418  1.147    kardel 			(void)fputc('\n', stderr);
    419  1.147    kardel 			exit(1);
    420  1.147    kardel 		}
    421    1.1       cgd 	}
    422  1.133       chs 	if (todo & INTRSTAT)
    423  1.133       chs 		(void) kvm_nlist(kd, intrnl);
    424   1.90     lukem 	if ((c = kvm_nlist(kd, hashnl)) == -1 || c == X_HASHNL_SIZE)
    425   1.90     lukem 		errx(1, "kvm_nlist: %s %s", "hashnl", kvm_geterr(kd));
    426   1.90     lukem 	if (kvm_nlist(kd, histnl) == -1)
    427   1.90     lukem 		errx(1, "kvm_nlist: %s %s", "histnl", kvm_geterr(kd));
    428    1.1       cgd 
    429    1.1       cgd 	if (todo & VMSTAT) {
    430    1.1       cgd 		struct winsize winsize;
    431    1.1       cgd 
    432  1.153  christos 		(void)drvinit(0);/* Initialize disk stats, no disks selected. */
    433   1.49  drochner 
    434   1.49  drochner 		(void)setgid(getgid()); /* don't need privs anymore */
    435   1.49  drochner 
    436   1.29   thorpej 		argv = choosedrives(argv);	/* Select disks. */
    437    1.1       cgd 		winsize.ws_row = 0;
    438  1.115    simonb 		(void)ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
    439    1.1       cgd 		if (winsize.ws_row > 0)
    440    1.1       cgd 			winlines = winsize.ws_row;
    441    1.1       cgd 
    442    1.1       cgd 	}
    443    1.1       cgd 
    444    1.1       cgd #ifdef	BACKWARD_COMPATIBILITY
    445    1.1       cgd 	if (*argv) {
    446  1.103   mycroft 		interval.tv_sec = atol(*argv);
    447    1.1       cgd 		if (*++argv)
    448    1.1       cgd 			reps = atoi(*argv);
    449    1.1       cgd 	}
    450    1.1       cgd #endif
    451    1.1       cgd 
    452  1.103   mycroft 	if (interval.tv_sec) {
    453    1.1       cgd 		if (!reps)
    454    1.1       cgd 			reps = -1;
    455    1.1       cgd 	} else if (reps)
    456  1.103   mycroft 		interval.tv_sec = 1;
    457    1.1       cgd 
    458   1.78     jhawk 
    459   1.78     jhawk 	/*
    460   1.78     jhawk 	 * Statistics dumping is incompatible with the default
    461   1.78     jhawk 	 * VMSTAT/dovmstat() output. So perform the interval/reps handling
    462   1.78     jhawk 	 * for it here.
    463   1.78     jhawk 	 */
    464  1.130        he 	if ((todo & (VMSTAT|VMTOTAL)) == 0) {
    465   1.99     enami 		for (;;) {
    466   1.99     enami 			if (todo & (HISTLIST|HISTDUMP)) {
    467   1.99     enami 				if ((todo & (HISTLIST|HISTDUMP)) ==
    468   1.99     enami 				    (HISTLIST|HISTDUMP))
    469   1.99     enami 					errx(1, "you may list or dump,"
    470   1.99     enami 					    " but not both!");
    471   1.99     enami 				hist_traverse(todo, histname);
    472  1.153  christos 				(void)putchar('\n');
    473   1.99     enami 			}
    474   1.99     enami 			if (todo & FORKSTAT) {
    475   1.99     enami 				doforkst();
    476  1.153  christos 				(void)putchar('\n');
    477   1.99     enami 			}
    478   1.99     enami 			if (todo & MEMSTAT) {
    479   1.99     enami 				domem();
    480  1.126    simonb 				dopool(verbose, wide);
    481  1.153  christos 				(void)putchar('\n');
    482   1.99     enami 			}
    483  1.154        ad 			if (todo & POOLCACHESTAT) {
    484  1.154        ad 				dopoolcache();
    485  1.154        ad 				(void)putchar('\n');
    486  1.154        ad 			}
    487   1.99     enami 			if (todo & SUMSTAT) {
    488   1.99     enami 				dosum();
    489  1.153  christos 				(void)putchar('\n');
    490   1.99     enami 			}
    491   1.99     enami 			if (todo & INTRSTAT) {
    492   1.99     enami 				dointr(verbose);
    493  1.153  christos 				(void)putchar('\n');
    494   1.99     enami 			}
    495   1.99     enami 			if (todo & EVCNTSTAT) {
    496   1.99     enami 				doevcnt(verbose);
    497  1.153  christos 				(void)putchar('\n');
    498   1.99     enami 			}
    499   1.99     enami 			if (todo & (HASHLIST|HASHSTAT)) {
    500   1.99     enami 				if ((todo & (HASHLIST|HASHSTAT)) ==
    501   1.99     enami 				    (HASHLIST|HASHSTAT))
    502   1.99     enami 					errx(1, "you may list or display,"
    503   1.99     enami 					    " but not both!");
    504   1.99     enami 				dohashstat(verbose, todo, hashname);
    505  1.153  christos 				(void)putchar('\n');
    506   1.99     enami 			}
    507  1.101  sommerfe 
    508  1.164  dholland 			fflush(stdout);
    509  1.101  sommerfe 			if (reps >= 0 && --reps <=0)
    510   1.99     enami 				break;
    511  1.153  christos 			(void)nanosleep(&interval, NULL);
    512   1.87     lukem 		}
    513  1.130        he 	} else {
    514  1.130        he 		if ((todo & (VMSTAT|VMTOTAL)) == (VMSTAT|VMTOTAL)) {
    515  1.130        he 			errx(1, "you may not both do vmstat and vmtotal");
    516  1.130        he 		}
    517  1.130        he 		if (todo & VMSTAT)
    518  1.130        he 			dovmstat(&interval, reps);
    519  1.130        he 		if (todo & VMTOTAL)
    520  1.130        he 			dovmtotal(&interval, reps);
    521  1.130        he 	}
    522  1.153  christos 	return 0;
    523    1.1       cgd }
    524    1.1       cgd 
    525    1.1       cgd char **
    526   1.73    simonb choosedrives(char **argv)
    527    1.1       cgd {
    528  1.165     lukem 	size_t i;
    529    1.1       cgd 
    530    1.1       cgd 	/*
    531    1.1       cgd 	 * Choose drives to be displayed.  Priority goes to (in order) drives
    532    1.1       cgd 	 * supplied as arguments, default drives.  If everything isn't filled
    533    1.1       cgd 	 * in and there are drives not taken care of, display the first few
    534    1.1       cgd 	 * that fit.
    535    1.1       cgd 	 */
    536   1.75     enami #define	BACKWARD_COMPATIBILITY
    537    1.1       cgd 	for (ndrives = 0; *argv; ++argv) {
    538    1.1       cgd #ifdef	BACKWARD_COMPATIBILITY
    539  1.124       dsl 		if (isdigit((unsigned char)**argv))
    540    1.1       cgd 			break;
    541    1.1       cgd #endif
    542  1.140     blymn 		for (i = 0; i < ndrive; i++) {
    543    1.1       cgd 			if (strcmp(dr_name[i], *argv))
    544    1.1       cgd 				continue;
    545  1.140     blymn 			drv_select[i] = 1;
    546  1.136     blymn 			++ndrives;
    547  1.136     blymn 			break;
    548  1.136     blymn 		}
    549    1.1       cgd 	}
    550  1.151      yamt 	for (i = 0; i < ndrive && ndrives < 2; i++) {
    551  1.140     blymn 		if (drv_select[i])
    552    1.1       cgd 			continue;
    553  1.140     blymn 		drv_select[i] = 1;
    554    1.1       cgd 		++ndrives;
    555    1.1       cgd 	}
    556  1.140     blymn 
    557   1.75     enami 	return (argv);
    558    1.1       cgd }
    559    1.1       cgd 
    560    1.1       cgd long
    561   1.73    simonb getuptime(void)
    562    1.1       cgd {
    563   1.30       cgd 	static struct timeval boottime;
    564  1.145    kardel 	struct timeval now;
    565  1.149    kardel 	time_t uptime, nowsec;
    566    1.1       cgd 
    567   1.30       cgd 	if (boottime.tv_sec == 0)
    568  1.133       chs 		kread(namelist, X_BOOTTIME, &boottime, sizeof(boottime));
    569  1.149    kardel 	if (kreadc(namelist, X_TIME_SECOND, &nowsec, sizeof(nowsec))) {
    570  1.149    kardel 		/*
    571  1.149    kardel 		 * XXX this assignment dance can be removed once timeval tv_sec
    572  1.149    kardel 		 * is SUS mandated time_t
    573  1.149    kardel 		 */
    574  1.149    kardel 		now.tv_sec = nowsec;
    575  1.147    kardel 		now.tv_usec = 0;
    576  1.147    kardel 	} else {
    577  1.147    kardel 		kread(namelist, X_TIME, &now, sizeof(now));
    578  1.147    kardel 	}
    579  1.145    kardel 	uptime = now.tv_sec - boottime.tv_sec;
    580   1.87     lukem 	if (uptime <= 0 || uptime > 60*60*24*365*10)
    581   1.87     lukem 		errx(1, "time makes no sense; namelist must be wrong.");
    582   1.75     enami 	return (uptime);
    583    1.1       cgd }
    584    1.1       cgd 
    585    1.1       cgd int	hz, hdrcnt;
    586    1.1       cgd 
    587    1.1       cgd void
    588  1.130        he print_total_hdr()
    589  1.130        he {
    590  1.130        he 
    591  1.166     rmind 	(void)printf("procs         memory\n");
    592  1.166     rmind 	(void)printf("ru dw pw sl");
    593  1.130        he 	(void)printf("   total-v  active-v  active-r");
    594  1.130        he 	(void)printf(" vm-sh avm-sh rm-sh arm-sh free\n");
    595  1.130        he 	hdrcnt = winlines - 2;
    596  1.130        he }
    597  1.130        he 
    598  1.130        he void
    599  1.130        he dovmtotal(struct timespec *interval, int reps)
    600  1.130        he {
    601  1.130        he 	struct vmtotal total;
    602  1.130        he 	int mib[2];
    603  1.130        he 	size_t size;
    604  1.130        he 
    605  1.130        he 	(void)signal(SIGCONT, needhdr);
    606  1.130        he 
    607  1.130        he 	for (hdrcnt = 1;;) {
    608  1.130        he 		if (!--hdrcnt)
    609  1.130        he 			print_total_hdr();
    610  1.130        he 		if (memf != NULL) {
    611  1.153  christos 			(void)printf(
    612  1.153  christos 			    "Unable to get vmtotals from crash dump.\n");
    613  1.153  christos 			(void)memset(&total, 0, sizeof(total));
    614  1.130        he 		} else {
    615  1.130        he 			size = sizeof(total);
    616  1.130        he 			mib[0] = CTL_VM;
    617  1.130        he 			mib[1] = VM_METER;
    618  1.130        he 			if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
    619  1.153  christos 				(void)printf("Can't get vmtotals: %s\n",
    620  1.130        he 				    strerror(errno));
    621  1.153  christos 				(void)memset(&total, 0, sizeof(total));
    622  1.130        he 			}
    623  1.130        he 		}
    624  1.153  christos 		(void)printf("%2d ", total.t_rq);
    625  1.153  christos 		(void)printf("%2d ", total.t_dw);
    626  1.153  christos 		(void)printf("%2d ", total.t_pw);
    627  1.153  christos 		(void)printf("%2d ", total.t_sl);
    628  1.153  christos 
    629  1.153  christos 		(void)printf("%9d ", total.t_vm);
    630  1.153  christos 		(void)printf("%9d ", total.t_avm);
    631  1.153  christos 		(void)printf("%9d ", total.t_arm);
    632  1.153  christos 		(void)printf("%5d ", total.t_vmshr);
    633  1.153  christos 		(void)printf("%6d ", total.t_avmshr);
    634  1.153  christos 		(void)printf("%5d ", total.t_rmshr);
    635  1.153  christos 		(void)printf("%6d ", total.t_armshr);
    636  1.153  christos 		(void)printf("%5d",  total.t_free);
    637  1.130        he 
    638  1.153  christos 		(void)putchar('\n');
    639  1.130        he 
    640  1.130        he 		(void)fflush(stdout);
    641  1.130        he 		if (reps >= 0 && --reps <= 0)
    642  1.130        he 			break;
    643  1.130        he 
    644  1.153  christos 		(void)nanosleep(interval, NULL);
    645  1.130        he 	}
    646  1.130        he }
    647  1.130        he 
    648  1.130        he void
    649  1.103   mycroft dovmstat(struct timespec *interval, int reps)
    650    1.1       cgd {
    651    1.1       cgd 	struct vmtotal total;
    652    1.1       cgd 	time_t uptime, halfuptime;
    653   1.17       cgd 	int mib[2];
    654   1.17       cgd 	size_t size;
    655   1.41       mrg 	int pagesize = getpagesize();
    656  1.151      yamt 	int ovflw;
    657    1.1       cgd 
    658    1.1       cgd 	uptime = getuptime();
    659    1.1       cgd 	halfuptime = uptime / 2;
    660    1.1       cgd 	(void)signal(SIGCONT, needhdr);
    661    1.1       cgd 
    662   1.13       cgd 	if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
    663  1.133       chs 		kread(namelist, X_STATHZ, &hz, sizeof(hz));
    664    1.1       cgd 	if (!hz)
    665  1.133       chs 		kread(namelist, X_HZ, &hz, sizeof(hz));
    666    1.1       cgd 
    667    1.1       cgd 	for (hdrcnt = 1;;) {
    668    1.1       cgd 		if (!--hdrcnt)
    669    1.1       cgd 			printhdr();
    670   1.29   thorpej 		/* Read new disk statistics */
    671  1.139       dsl 		cpureadstats();
    672  1.140     blymn 		drvreadstats();
    673  1.139       dsl 		tkreadstats();
    674  1.133       chs 		kread(namelist, X_UVMEXP, &uvmexp, sizeof(uvmexp));
    675   1.58   thorpej 		if (memf != NULL) {
    676   1.58   thorpej 			/*
    677   1.58   thorpej 			 * XXX Can't do this if we're reading a crash
    678   1.58   thorpej 			 * XXX dump because they're lazily-calculated.
    679   1.58   thorpej 			 */
    680  1.153  christos 			(void)printf(
    681  1.153  christos 			    "Unable to get vmtotals from crash dump.\n");
    682  1.153  christos 			(void)memset(&total, 0, sizeof(total));
    683   1.58   thorpej 		} else {
    684   1.58   thorpej 			size = sizeof(total);
    685   1.58   thorpej 			mib[0] = CTL_VM;
    686   1.58   thorpej 			mib[1] = VM_METER;
    687   1.58   thorpej 			if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
    688  1.153  christos 				(void)printf("Can't get vmtotals: %s\n",
    689   1.58   thorpej 				    strerror(errno));
    690  1.153  christos 				(void)memset(&total, 0, sizeof(total));
    691   1.58   thorpej 			}
    692   1.13       cgd 		}
    693  1.151      yamt 		ovflw = 0;
    694  1.151      yamt 		PRWORD(ovflw, " %*d", 2, 1, total.t_rq - 1);
    695  1.151      yamt 		PRWORD(ovflw, " %*d", 2, 1, total.t_dw + total.t_pw);
    696  1.153  christos #define	pgtok(a) (long)((a) * ((uint32_t)pagesize >> 10))
    697   1.38       mrg #define	rate(x)	(u_long)(((x) + halfuptime) / uptime)	/* round */
    698  1.166     rmind 		PRWORD(ovflw, " %*ld", 9, 1, pgtok(total.t_avm));
    699  1.151      yamt 		PRWORD(ovflw, " %*ld", 7, 1, pgtok(total.t_free));
    700  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    701  1.151      yamt 		    rate(uvmexp.faults - ouvmexp.faults));
    702  1.151      yamt 		PRWORD(ovflw, " %*ld", 4, 1,
    703  1.151      yamt 		    rate(uvmexp.pdreact - ouvmexp.pdreact));
    704  1.151      yamt 		PRWORD(ovflw, " %*ld", 4, 1,
    705  1.151      yamt 		    rate(uvmexp.pageins - ouvmexp.pageins));
    706  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    707   1.44       mrg 		    rate(uvmexp.pgswapout - ouvmexp.pgswapout));
    708  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    709  1.151      yamt 		    rate(uvmexp.pdfreed - ouvmexp.pdfreed));
    710  1.151      yamt 		PRWORD(ovflw, " %*ld", 6, 2,
    711  1.151      yamt 		    rate(uvmexp.pdscans - ouvmexp.pdscans));
    712  1.151      yamt 		drvstats(&ovflw);
    713  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    714  1.151      yamt 		    rate(uvmexp.intrs - ouvmexp.intrs));
    715  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    716  1.151      yamt 		    rate(uvmexp.syscalls - ouvmexp.syscalls));
    717  1.151      yamt 		PRWORD(ovflw, " %*ld", 4, 1,
    718   1.42       mrg 		    rate(uvmexp.swtch - ouvmexp.swtch));
    719  1.151      yamt 		cpustats(&ovflw);
    720  1.153  christos 		(void)putchar('\n');
    721   1.42       mrg 		(void)fflush(stdout);
    722   1.42       mrg 		if (reps >= 0 && --reps <= 0)
    723   1.42       mrg 			break;
    724   1.42       mrg 		ouvmexp = uvmexp;
    725  1.103   mycroft 		uptime = interval->tv_sec;
    726    1.1       cgd 		/*
    727    1.1       cgd 		 * We round upward to avoid losing low-frequency events
    728    1.1       cgd 		 * (i.e., >= 1 per interval but < 1 per second).
    729    1.1       cgd 		 */
    730   1.33   thorpej 		halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
    731  1.153  christos 		(void)nanosleep(interval, NULL);
    732    1.1       cgd 	}
    733    1.1       cgd }
    734    1.1       cgd 
    735   1.38       mrg void
    736   1.73    simonb printhdr(void)
    737    1.1       cgd {
    738  1.165     lukem 	size_t i;
    739    1.1       cgd 
    740  1.104       mrg 	(void)printf(" procs    memory      page%*s", 23, "");
    741   1.29   thorpej 	if (ndrives > 0)
    742   1.70  sommerfe 		(void)printf("%s %*sfaults      cpu\n",
    743   1.75     enami 		    ((ndrives > 1) ? "disks" : "disk"),
    744   1.75     enami 		    ((ndrives > 1) ? ndrives * 3 - 4 : 0), "");
    745    1.1       cgd 	else
    746   1.29   thorpej 		(void)printf("%*s  faults   cpu\n",
    747   1.75     enami 		    ndrives * 3, "");
    748   1.29   thorpej 
    749  1.166     rmind 	(void)printf(" r b      avm    fre  flt  re  pi   po   fr   sr ");
    750  1.140     blymn 	for (i = 0; i < ndrive; i++)
    751  1.140     blymn 		if (drv_select[i])
    752    1.1       cgd 			(void)printf("%c%c ", dr_name[i][0],
    753    1.1       cgd 			    dr_name[i][strlen(dr_name[i]) - 1]);
    754    1.1       cgd 	(void)printf("  in   sy  cs us sy id\n");
    755    1.1       cgd 	hdrcnt = winlines - 2;
    756    1.1       cgd }
    757    1.1       cgd 
    758    1.1       cgd /*
    759    1.1       cgd  * Force a header to be prepended to the next output.
    760    1.1       cgd  */
    761    1.1       cgd void
    762  1.153  christos /*ARGSUSED*/
    763   1.73    simonb needhdr(int dummy)
    764    1.1       cgd {
    765    1.1       cgd 
    766    1.1       cgd 	hdrcnt = 1;
    767    1.1       cgd }
    768    1.1       cgd 
    769   1.38       mrg long
    770   1.73    simonb pct(long top, long bot)
    771    1.1       cgd {
    772   1.13       cgd 	long ans;
    773   1.13       cgd 
    774    1.1       cgd 	if (bot == 0)
    775   1.75     enami 		return (0);
    776  1.153  christos 	ans = (long)((quad_t)top * 100 / bot);
    777   1.13       cgd 	return (ans);
    778    1.1       cgd }
    779    1.1       cgd 
    780   1.38       mrg #define	PCT(top, bot) (int)pct((long)(top), (long)(bot))
    781    1.1       cgd 
    782    1.1       cgd void
    783   1.73    simonb dosum(void)
    784    1.1       cgd {
    785    1.1       cgd 	struct nchstats nchstats;
    786  1.123     enami 	u_long nchtotal;
    787  1.162        he 	int mib[2];
    788  1.162        he 	struct uvmexp_sysctl uvmexp2;
    789  1.162        he 	size_t ssize;
    790  1.162        he 	int active_kernel;
    791  1.162        he 
    792  1.162        he 	/*
    793  1.162        he 	 * The "active" and "inactive" variables
    794  1.162        he 	 * are now estimated by the kernel and sadly
    795  1.162        he 	 * can not easily be dug out of a crash dump.
    796  1.162        he 	 */
    797  1.162        he 	ssize = sizeof(uvmexp2);
    798  1.162        he 	memset(&uvmexp2, 0, ssize);
    799  1.162        he 	active_kernel = (memf == NULL);
    800  1.162        he 	if (active_kernel) {
    801  1.162        he 		/* only on active kernel */
    802  1.162        he 		mib[0] = CTL_VM;
    803  1.162        he 		mib[1] = VM_UVMEXP2;
    804  1.162        he 		if (sysctl(mib, 2, &uvmexp2, &ssize, NULL, 0) < 0)
    805  1.162        he 			fprintf(stderr, "%s: sysctl vm.uvmexp2 failed: %s",
    806  1.162        he 				getprogname(), strerror(errno));
    807  1.162        he 	}
    808    1.1       cgd 
    809  1.133       chs 	kread(namelist, X_UVMEXP, &uvmexp, sizeof(uvmexp));
    810   1.41       mrg 
    811   1.44       mrg 	(void)printf("%9u bytes per page\n", uvmexp.pagesize);
    812   1.44       mrg 
    813   1.81   thorpej 	(void)printf("%9u page color%s\n",
    814   1.81   thorpej 	    uvmexp.ncolors, uvmexp.ncolors == 1 ? "" : "s");
    815   1.81   thorpej 
    816   1.44       mrg 	(void)printf("%9u pages managed\n", uvmexp.npages);
    817   1.44       mrg 	(void)printf("%9u pages free\n", uvmexp.free);
    818  1.162        he 	if (active_kernel) {
    819  1.162        he 		(void)printf("%9" PRIu64 " pages active\n", uvmexp2.active);
    820  1.162        he 		(void)printf("%9" PRIu64 " pages inactive\n", uvmexp2.inactive);
    821  1.162        he 	}
    822   1.44       mrg 	(void)printf("%9u pages paging\n", uvmexp.paging);
    823   1.44       mrg 	(void)printf("%9u pages wired\n", uvmexp.wired);
    824   1.63   thorpej 	(void)printf("%9u zero pages\n", uvmexp.zeropages);
    825   1.44       mrg 	(void)printf("%9u reserve pagedaemon pages\n",
    826   1.44       mrg 	    uvmexp.reserve_pagedaemon);
    827   1.44       mrg 	(void)printf("%9u reserve kernel pages\n", uvmexp.reserve_kernel);
    828   1.94       chs 	(void)printf("%9u anonymous pages\n", uvmexp.anonpages);
    829   1.94       chs 	(void)printf("%9u cached file pages\n", uvmexp.filepages);
    830   1.94       chs 	(void)printf("%9u cached executable pages\n", uvmexp.execpages);
    831   1.44       mrg 
    832   1.44       mrg 	(void)printf("%9u minimum free pages\n", uvmexp.freemin);
    833   1.44       mrg 	(void)printf("%9u target free pages\n", uvmexp.freetarg);
    834   1.44       mrg 	(void)printf("%9u maximum wired pages\n", uvmexp.wiredmax);
    835   1.44       mrg 
    836   1.44       mrg 	(void)printf("%9u swap devices\n", uvmexp.nswapdev);
    837   1.44       mrg 	(void)printf("%9u swap pages\n", uvmexp.swpages);
    838   1.44       mrg 	(void)printf("%9u swap pages in use\n", uvmexp.swpginuse);
    839   1.44       mrg 	(void)printf("%9u swap allocations\n", uvmexp.nswget);
    840   1.44       mrg 
    841   1.43       mrg 	(void)printf("%9u total faults taken\n", uvmexp.faults);
    842   1.43       mrg 	(void)printf("%9u traps\n", uvmexp.traps);
    843   1.43       mrg 	(void)printf("%9u device interrupts\n", uvmexp.intrs);
    844  1.121       wiz 	(void)printf("%9u CPU context switches\n", uvmexp.swtch);
    845   1.43       mrg 	(void)printf("%9u software interrupts\n", uvmexp.softs);
    846   1.43       mrg 	(void)printf("%9u system calls\n", uvmexp.syscalls);
    847   1.60     fredb 	(void)printf("%9u pagein requests\n", uvmexp.pageins);
    848   1.60     fredb 	(void)printf("%9u pageout requests\n", uvmexp.pdpageouts);
    849   1.60     fredb 	(void)printf("%9u pages swapped in\n", uvmexp.pgswapin);
    850   1.60     fredb 	(void)printf("%9u pages swapped out\n", uvmexp.pgswapout);
    851   1.43       mrg 	(void)printf("%9u forks total\n", uvmexp.forks);
    852   1.43       mrg 	(void)printf("%9u forks blocked parent\n", uvmexp.forks_ppwait);
    853   1.43       mrg 	(void)printf("%9u forks shared address space with parent\n",
    854   1.43       mrg 	    uvmexp.forks_sharevm);
    855   1.63   thorpej 	(void)printf("%9u pagealloc zero wanted and avail\n",
    856   1.63   thorpej 	    uvmexp.pga_zerohit);
    857   1.63   thorpej 	(void)printf("%9u pagealloc zero wanted and not avail\n",
    858   1.63   thorpej 	    uvmexp.pga_zeromiss);
    859   1.68   thorpej 	(void)printf("%9u aborts of idle page zeroing\n",
    860   1.68   thorpej 	    uvmexp.zeroaborts);
    861   1.79   thorpej 	(void)printf("%9u pagealloc desired color avail\n",
    862   1.79   thorpej 	    uvmexp.colorhit);
    863   1.79   thorpej 	(void)printf("%9u pagealloc desired color not avail\n",
    864   1.79   thorpej 	    uvmexp.colormiss);
    865  1.159        ad 	(void)printf("%9u pagealloc local cpu avail\n",
    866  1.159        ad 	    uvmexp.cpuhit);
    867  1.159        ad 	(void)printf("%9u pagealloc local cpu not avail\n",
    868  1.159        ad 	    uvmexp.cpumiss);
    869   1.44       mrg 
    870   1.44       mrg 	(void)printf("%9u faults with no memory\n", uvmexp.fltnoram);
    871   1.44       mrg 	(void)printf("%9u faults with no anons\n", uvmexp.fltnoanon);
    872   1.43       mrg 	(void)printf("%9u faults had to wait on pages\n", uvmexp.fltpgwait);
    873   1.43       mrg 	(void)printf("%9u faults found released page\n", uvmexp.fltpgrele);
    874   1.43       mrg 	(void)printf("%9u faults relock (%u ok)\n", uvmexp.fltrelck,
    875   1.43       mrg 	    uvmexp.fltrelckok);
    876   1.43       mrg 	(void)printf("%9u anon page faults\n", uvmexp.fltanget);
    877   1.43       mrg 	(void)printf("%9u anon retry faults\n", uvmexp.fltanretry);
    878   1.43       mrg 	(void)printf("%9u amap copy faults\n", uvmexp.fltamcopy);
    879   1.43       mrg 	(void)printf("%9u neighbour anon page faults\n", uvmexp.fltnamap);
    880   1.43       mrg 	(void)printf("%9u neighbour object page faults\n", uvmexp.fltnomap);
    881   1.43       mrg 	(void)printf("%9u locked pager get faults\n", uvmexp.fltlget);
    882   1.43       mrg 	(void)printf("%9u unlocked pager get faults\n", uvmexp.fltget);
    883   1.43       mrg 	(void)printf("%9u anon faults\n", uvmexp.flt_anon);
    884   1.43       mrg 	(void)printf("%9u anon copy on write faults\n", uvmexp.flt_acow);
    885   1.43       mrg 	(void)printf("%9u object faults\n", uvmexp.flt_obj);
    886   1.43       mrg 	(void)printf("%9u promote copy faults\n", uvmexp.flt_prcopy);
    887   1.43       mrg 	(void)printf("%9u promote zero fill faults\n", uvmexp.flt_przero);
    888   1.44       mrg 
    889   1.44       mrg 	(void)printf("%9u times daemon wokeup\n",uvmexp.pdwoke);
    890   1.44       mrg 	(void)printf("%9u revolutions of the clock hand\n", uvmexp.pdrevs);
    891   1.44       mrg 	(void)printf("%9u pages freed by daemon\n", uvmexp.pdfreed);
    892   1.44       mrg 	(void)printf("%9u pages scanned by daemon\n", uvmexp.pdscans);
    893   1.75     enami 	(void)printf("%9u anonymous pages scanned by daemon\n",
    894   1.75     enami 	    uvmexp.pdanscan);
    895   1.44       mrg 	(void)printf("%9u object pages scanned by daemon\n", uvmexp.pdobscan);
    896   1.44       mrg 	(void)printf("%9u pages reactivated\n", uvmexp.pdreact);
    897   1.44       mrg 	(void)printf("%9u pages found busy by daemon\n", uvmexp.pdbusy);
    898   1.44       mrg 	(void)printf("%9u total pending pageouts\n", uvmexp.pdpending);
    899   1.44       mrg 	(void)printf("%9u pages deactivated\n", uvmexp.pddeact);
    900  1.123     enami 
    901  1.133       chs 	kread(namelist, X_NCHSTATS, &nchstats, sizeof(nchstats));
    902    1.1       cgd 	nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
    903    1.1       cgd 	    nchstats.ncs_badhits + nchstats.ncs_falsehits +
    904    1.1       cgd 	    nchstats.ncs_miss + nchstats.ncs_long;
    905  1.123     enami 	(void)printf("%9lu total name lookups\n", nchtotal);
    906  1.123     enami 	(void)printf("%9lu good hits\n", nchstats.ncs_goodhits);
    907  1.123     enami 	(void)printf("%9lu negative hits\n", nchstats.ncs_neghits);
    908  1.123     enami 	(void)printf("%9lu bad hits\n", nchstats.ncs_badhits);
    909  1.123     enami 	(void)printf("%9lu false hits\n", nchstats.ncs_falsehits);
    910  1.123     enami 	(void)printf("%9lu miss\n", nchstats.ncs_miss);
    911  1.123     enami 	(void)printf("%9lu too long\n", nchstats.ncs_long);
    912  1.123     enami 	(void)printf("%9lu pass2 hits\n", nchstats.ncs_pass2);
    913  1.123     enami 	(void)printf("%9lu 2passes\n", nchstats.ncs_2passes);
    914    1.1       cgd 	(void)printf(
    915    1.1       cgd 	    "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
    916    1.1       cgd 	    "", PCT(nchstats.ncs_goodhits, nchtotal),
    917    1.1       cgd 	    PCT(nchstats.ncs_neghits, nchtotal),
    918    1.1       cgd 	    PCT(nchstats.ncs_pass2, nchtotal));
    919    1.1       cgd 	(void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
    920    1.1       cgd 	    PCT(nchstats.ncs_badhits, nchtotal),
    921    1.1       cgd 	    PCT(nchstats.ncs_falsehits, nchtotal),
    922    1.1       cgd 	    PCT(nchstats.ncs_long, nchtotal));
    923    1.1       cgd }
    924    1.1       cgd 
    925    1.1       cgd void
    926   1.73    simonb doforkst(void)
    927    1.1       cgd {
    928   1.41       mrg 
    929  1.133       chs 	kread(namelist, X_UVMEXP, &uvmexp, sizeof(uvmexp));
    930   1.58   thorpej 
    931   1.41       mrg 	(void)printf("%u forks total\n", uvmexp.forks);
    932   1.41       mrg 	(void)printf("%u forks blocked parent\n", uvmexp.forks_ppwait);
    933   1.41       mrg 	(void)printf("%u forks shared address space with parent\n",
    934   1.41       mrg 	    uvmexp.forks_sharevm);
    935    1.1       cgd }
    936    1.1       cgd 
    937    1.1       cgd void
    938  1.151      yamt drvstats(int *ovflwp)
    939    1.1       cgd {
    940  1.165     lukem 	size_t dn;
    941    1.1       cgd 	double etime;
    942  1.151      yamt 	int ovflw = *ovflwp;
    943    1.1       cgd 
    944   1.29   thorpej 	/* Calculate disk stat deltas. */
    945  1.139       dsl 	cpuswap();
    946  1.140     blymn 	drvswap();
    947  1.139       dsl 	tkswap();
    948  1.101  sommerfe 	etime = cur.cp_etime;
    949  1.101  sommerfe 
    950  1.140     blymn 	for (dn = 0; dn < ndrive; ++dn) {
    951  1.140     blymn 		if (!drv_select[dn])
    952  1.151      yamt 	 		continue;
    953  1.151      yamt 		PRWORD(ovflw, " %*.0f", 3, 1,
    954  1.151      yamt 		    (cur.rxfer[dn] + cur.wxfer[dn]) / etime);
    955  1.136     blymn 	}
    956  1.151      yamt 	*ovflwp = ovflw;
    957  1.136     blymn }
    958  1.136     blymn 
    959  1.136     blymn void
    960  1.151      yamt cpustats(int *ovflwp)
    961    1.1       cgd {
    962   1.38       mrg 	int state;
    963  1.129       dsl 	double pcnt, total;
    964  1.120       dbj 	double stat_us, stat_sy, stat_id;
    965  1.151      yamt 	int ovflw = *ovflwp;
    966    1.1       cgd 
    967    1.1       cgd 	total = 0;
    968    1.1       cgd 	for (state = 0; state < CPUSTATES; ++state)
    969   1.29   thorpej 		total += cur.cp_time[state];
    970    1.1       cgd 	if (total)
    971  1.129       dsl 		pcnt = 100 / total;
    972    1.1       cgd 	else
    973  1.129       dsl 		pcnt = 0;
    974  1.129       dsl 	stat_us = (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pcnt;
    975  1.129       dsl 	stat_sy = (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pcnt;
    976  1.129       dsl 	stat_id = cur.cp_time[CP_IDLE] * pcnt;
    977  1.151      yamt 	PRWORD(ovflw, " %*.0f", ((stat_sy >= 100) ? 2 : 3), 1, stat_us);
    978  1.151      yamt 	PRWORD(ovflw, " %*.0f", ((stat_us >= 100 || stat_id >= 100) ? 2 : 3), 1,
    979  1.151      yamt 	    stat_sy);
    980  1.151      yamt 	PRWORD(ovflw, " %*.0f", 3, 1, stat_id);
    981  1.151      yamt 	*ovflwp = ovflw;
    982    1.1       cgd }
    983    1.1       cgd 
    984    1.1       cgd void
    985   1.66       cgd dointr(int verbose)
    986    1.1       cgd {
    987  1.138    nonaka 	unsigned long *intrcnt, *ointrcnt;
    988   1.85     enami 	unsigned long long inttotal, uptime;
    989   1.38       mrg 	int nintr, inamlen;
    990  1.138    nonaka 	char *intrname, *ointrname;
    991   1.28       cgd 	struct evcntlist allevents;
    992   1.28       cgd 	struct evcnt evcnt, *evptr;
    993   1.66       cgd 	char evgroup[EVCNT_STRING_MAX], evname[EVCNT_STRING_MAX];
    994    1.1       cgd 
    995  1.133       chs 	inttotal = 0;
    996    1.1       cgd 	uptime = getuptime();
    997   1.83      matt 	(void)printf("%-34s %16s %8s\n", "interrupt", "total", "rate");
    998  1.133       chs 	nintr = intrnl[X_EINTRCNT].n_value - intrnl[X_INTRCNT].n_value;
    999  1.133       chs 	inamlen = intrnl[X_EINTRNAMES].n_value - intrnl[X_INTRNAMES].n_value;
   1000  1.133       chs 	if (nintr != 0 && inamlen != 0) {
   1001  1.138    nonaka 		ointrcnt = intrcnt = malloc((size_t)nintr);
   1002  1.138    nonaka 		ointrname = intrname = malloc((size_t)inamlen);
   1003  1.133       chs 		if (intrcnt == NULL || intrname == NULL)
   1004  1.133       chs 			errx(1, "%s", "");
   1005  1.133       chs 		kread(intrnl, X_INTRCNT, intrcnt, (size_t)nintr);
   1006  1.133       chs 		kread(intrnl, X_INTRNAMES, intrname, (size_t)inamlen);
   1007  1.133       chs 		nintr /= sizeof(long);
   1008  1.133       chs 		while (--nintr >= 0) {
   1009  1.133       chs 			if (*intrcnt || verbose)
   1010  1.133       chs 				(void)printf("%-34s %16llu %8llu\n", intrname,
   1011  1.133       chs 					     (unsigned long long)*intrcnt,
   1012  1.133       chs 					     (unsigned long long)
   1013  1.133       chs 					     (*intrcnt / uptime));
   1014  1.133       chs 			intrname += strlen(intrname) + 1;
   1015  1.133       chs 			inttotal += *intrcnt++;
   1016  1.133       chs 		}
   1017  1.138    nonaka 		free(ointrcnt);
   1018  1.138    nonaka 		free(ointrname);
   1019    1.1       cgd 	}
   1020  1.133       chs 
   1021  1.133       chs 	kread(namelist, X_ALLEVENTS, &allevents, sizeof allevents);
   1022  1.133       chs 	evptr = TAILQ_FIRST(&allevents);
   1023   1.28       cgd 	while (evptr) {
   1024   1.87     lukem 		deref_kptr(evptr, &evcnt, sizeof(evcnt), "event chain trashed");
   1025  1.133       chs 		evptr = TAILQ_NEXT(&evcnt, ev_list);
   1026   1.66       cgd 		if (evcnt.ev_type != EVCNT_TYPE_INTR)
   1027   1.66       cgd 			continue;
   1028   1.66       cgd 
   1029   1.66       cgd 		if (evcnt.ev_count == 0 && !verbose)
   1030   1.66       cgd 			continue;
   1031   1.66       cgd 
   1032  1.153  christos 		deref_kptr(evcnt.ev_group, evgroup,
   1033  1.153  christos 		    (size_t)evcnt.ev_grouplen + 1, "event chain trashed");
   1034  1.153  christos 		deref_kptr(evcnt.ev_name, evname,
   1035  1.153  christos 		    (size_t)evcnt.ev_namelen + 1, "event chain trashed");
   1036   1.66       cgd 
   1037   1.85     enami 		(void)printf("%s %s%*s %16llu %8llu\n", evgroup, evname,
   1038   1.83      matt 		    34 - (evcnt.ev_grouplen + 1 + evcnt.ev_namelen), "",
   1039   1.85     enami 		    (unsigned long long)evcnt.ev_count,
   1040   1.85     enami 		    (unsigned long long)(evcnt.ev_count / uptime));
   1041   1.66       cgd 
   1042   1.66       cgd 		inttotal += evcnt.ev_count++;
   1043   1.66       cgd 	}
   1044   1.85     enami 	(void)printf("%-34s %16llu %8llu\n", "Total", inttotal,
   1045   1.85     enami 	    (unsigned long long)(inttotal / uptime));
   1046   1.66       cgd }
   1047   1.66       cgd 
   1048   1.66       cgd void
   1049   1.66       cgd doevcnt(int verbose)
   1050   1.66       cgd {
   1051   1.83      matt 	static const char * evtypes [] = { "misc", "intr", "trap" };
   1052   1.85     enami 	unsigned long long uptime;
   1053   1.66       cgd 	struct evcntlist allevents;
   1054   1.66       cgd 	struct evcnt evcnt, *evptr;
   1055   1.66       cgd 	char evgroup[EVCNT_STRING_MAX], evname[EVCNT_STRING_MAX];
   1056   1.66       cgd 
   1057   1.66       cgd 	/* XXX should print type! */
   1058   1.66       cgd 
   1059   1.66       cgd 	uptime = getuptime();
   1060   1.83      matt 	(void)printf("%-34s %16s %8s %s\n", "event", "total", "rate", "type");
   1061  1.133       chs 	kread(namelist, X_ALLEVENTS, &allevents, sizeof allevents);
   1062  1.133       chs 	evptr = TAILQ_FIRST(&allevents);
   1063   1.66       cgd 	while (evptr) {
   1064   1.87     lukem 		deref_kptr(evptr, &evcnt, sizeof(evcnt), "event chain trashed");
   1065   1.32       cgd 
   1066  1.133       chs 		evptr = TAILQ_NEXT(&evcnt, ev_list);
   1067   1.66       cgd 		if (evcnt.ev_count == 0 && !verbose)
   1068   1.66       cgd 			continue;
   1069   1.66       cgd 
   1070  1.153  christos 		deref_kptr(evcnt.ev_group, evgroup,
   1071  1.153  christos 		    (size_t)evcnt.ev_grouplen + 1, "event chain trashed");
   1072  1.153  christos 		deref_kptr(evcnt.ev_name, evname,
   1073  1.153  christos 		    (size_t)evcnt.ev_namelen + 1, "event chain trashed");
   1074   1.66       cgd 
   1075   1.85     enami 		(void)printf("%s %s%*s %16llu %8llu %s\n", evgroup, evname,
   1076   1.83      matt 		    34 - (evcnt.ev_grouplen + 1 + evcnt.ev_namelen), "",
   1077   1.85     enami 		    (unsigned long long)evcnt.ev_count,
   1078   1.85     enami 		    (unsigned long long)(evcnt.ev_count / uptime),
   1079   1.86     enami 		    (evcnt.ev_type < sizeof(evtypes)/sizeof(evtypes[0]) ?
   1080   1.86     enami 			evtypes[evcnt.ev_type] : "?"));
   1081   1.18        pk 	}
   1082    1.1       cgd }
   1083    1.1       cgd 
   1084  1.109   thorpej static char memname[64];
   1085    1.1       cgd 
   1086    1.1       cgd void
   1087   1.73    simonb domem(void)
   1088    1.1       cgd {
   1089   1.38       mrg 	struct kmembuckets *kp;
   1090  1.109   thorpej 	struct malloc_type ks, *ksp;
   1091   1.38       mrg 	int i, j;
   1092   1.13       cgd 	int len, size, first;
   1093   1.13       cgd 	long totuse = 0, totfree = 0, totreq = 0;
   1094    1.1       cgd 	struct kmembuckets buckets[MINBUCKET + 16];
   1095    1.1       cgd 
   1096  1.133       chs 	kread(namelist, X_KMEMBUCKETS, buckets, sizeof(buckets));
   1097   1.34   thorpej 	for (first = 1, i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16;
   1098   1.34   thorpej 	    i++, kp++) {
   1099    1.1       cgd 		if (kp->kb_calls == 0)
   1100    1.1       cgd 			continue;
   1101   1.34   thorpej 		if (first) {
   1102   1.34   thorpej 			(void)printf("Memory statistics by bucket size\n");
   1103   1.34   thorpej 			(void)printf(
   1104   1.34   thorpej 		 "    Size   In Use   Free   Requests  HighWater  Couldfree\n");
   1105   1.34   thorpej 			first = 0;
   1106   1.34   thorpej 		}
   1107    1.1       cgd 		size = 1 << i;
   1108   1.75     enami 		(void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
   1109   1.75     enami 		    kp->kb_total - kp->kb_totalfree,
   1110   1.75     enami 		    kp->kb_totalfree, kp->kb_calls,
   1111   1.75     enami 		    kp->kb_highwat, kp->kb_couldfree);
   1112    1.1       cgd 		totfree += size * kp->kb_totalfree;
   1113   1.34   thorpej 	}
   1114   1.34   thorpej 
   1115   1.34   thorpej 	/*
   1116   1.34   thorpej 	 * If kmem statistics are not being gathered by the kernel,
   1117   1.34   thorpej 	 * first will still be 1.
   1118   1.34   thorpej 	 */
   1119   1.34   thorpej 	if (first) {
   1120   1.87     lukem 		warnx("Kmem statistics are not being gathered by the kernel.");
   1121   1.34   thorpej 		return;
   1122    1.1       cgd 	}
   1123    1.1       cgd 
   1124   1.13       cgd 	(void)printf("\nMemory usage type by bucket size\n");
   1125   1.13       cgd 	(void)printf("    Size  Type(s)\n");
   1126   1.13       cgd 	kp = &buckets[MINBUCKET];
   1127   1.13       cgd 	for (j =  1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
   1128   1.13       cgd 		if (kp->kb_calls == 0)
   1129   1.13       cgd 			continue;
   1130   1.13       cgd 		first = 1;
   1131   1.13       cgd 		len = 8;
   1132  1.133       chs 		for (kread(namelist, X_KMEMSTAT, &ksp, sizeof(ksp));
   1133  1.109   thorpej 		     ksp != NULL; ksp = ks.ks_next) {
   1134  1.109   thorpej 			deref_kptr(ksp, &ks, sizeof(ks), "malloc type");
   1135  1.109   thorpej 			if (ks.ks_calls == 0)
   1136   1.13       cgd 				continue;
   1137  1.109   thorpej 			if ((ks.ks_size & j) == 0)
   1138   1.13       cgd 				continue;
   1139  1.109   thorpej 			deref_kptr(ks.ks_shortdesc, memname,
   1140  1.109   thorpej 			    sizeof(memname), "malloc type name");
   1141  1.109   thorpej 			len += 2 + strlen(memname);
   1142   1.13       cgd 			if (first)
   1143  1.153  christos 				(void)printf("%8d  %s", j, memname);
   1144   1.13       cgd 			else
   1145  1.153  christos 				(void)printf(",");
   1146   1.13       cgd 			if (len >= 80) {
   1147  1.153  christos 				(void)printf("\n\t ");
   1148  1.109   thorpej 				len = 10 + strlen(memname);
   1149   1.13       cgd 			}
   1150   1.13       cgd 			if (!first)
   1151  1.153  christos 				(void)printf(" %s", memname);
   1152   1.13       cgd 			first = 0;
   1153   1.13       cgd 		}
   1154  1.153  christos 		(void)putchar('\n');
   1155   1.13       cgd 	}
   1156   1.13       cgd 
   1157    1.1       cgd 	(void)printf(
   1158  1.160        he 	    "\nMemory statistics by type                                Type  Kern\n");
   1159   1.13       cgd 	(void)printf(
   1160  1.160        he "           Type InUse  MemUse HighUse   Limit   Requests Limit Limit Size(s)\n");
   1161  1.133       chs 	for (kread(namelist, X_KMEMSTAT, &ksp, sizeof(ksp));
   1162  1.109   thorpej 	     ksp != NULL; ksp = ks.ks_next) {
   1163  1.109   thorpej 		deref_kptr(ksp, &ks, sizeof(ks), "malloc type");
   1164  1.109   thorpej 		if (ks.ks_calls == 0)
   1165    1.1       cgd 			continue;
   1166  1.109   thorpej 		deref_kptr(ks.ks_shortdesc, memname,
   1167  1.109   thorpej 		    sizeof(memname), "malloc type name");
   1168  1.160        he 		(void)printf("%15s %5ld %6ldK %6ldK %6ldK %10ld %5u %5u",
   1169  1.109   thorpej 		    memname,
   1170  1.152  christos 		    ks.ks_inuse, howmany(ks.ks_memuse, KILO),
   1171  1.152  christos 		    howmany(ks.ks_maxused, KILO),
   1172  1.152  christos 		    howmany(ks.ks_limit, KILO), ks.ks_calls,
   1173  1.109   thorpej 		    ks.ks_limblocks, ks.ks_mapblocks);
   1174   1.13       cgd 		first = 1;
   1175  1.167        he 		for (j = 1 << MINBUCKET, i = MINBUCKET;
   1176  1.167        he 		     j < 1 << (MINBUCKET + 16);
   1177  1.167        he 		     j <<= 1, i++)
   1178  1.167        he 		{
   1179  1.109   thorpej 			if ((ks.ks_size & j) == 0)
   1180   1.13       cgd 				continue;
   1181   1.13       cgd 			if (first)
   1182  1.160        he 				(void)printf(" %d", j);
   1183   1.13       cgd 			else
   1184  1.153  christos 				(void)printf(",%d", j);
   1185   1.13       cgd 			first = 0;
   1186  1.168        he 			(void)printf(":%u", ks.ks_active[i - MINBUCKET]);
   1187   1.13       cgd 		}
   1188  1.153  christos 		(void)printf("\n");
   1189  1.109   thorpej 		totuse += ks.ks_memuse;
   1190  1.109   thorpej 		totreq += ks.ks_calls;
   1191    1.1       cgd 	}
   1192  1.102     soren 	(void)printf("\nMemory totals:  In Use    Free    Requests\n");
   1193  1.102     soren 	(void)printf("              %7ldK %6ldK    %8ld\n\n",
   1194  1.152  christos 	    howmany(totuse, KILO), howmany(totfree, KILO), totreq);
   1195   1.51        pk }
   1196   1.51        pk 
   1197   1.51        pk void
   1198  1.126    simonb dopool(int verbose, int wide)
   1199   1.51        pk {
   1200   1.69     enami 	int first, ovflw;
   1201   1.87     lukem 	void *addr;
   1202  1.126    simonb 	long total, inuse, this_total, this_inuse;
   1203  1.157        ad 	TAILQ_HEAD(,pool) pool_head;
   1204   1.51        pk 	struct pool pool, *pp = &pool;
   1205   1.98  christos 	struct pool_allocator pa;
   1206   1.87     lukem 	char name[32], maxp[32];
   1207   1.51        pk 
   1208  1.133       chs 	kread(namelist, X_POOLHEAD, &pool_head, sizeof(pool_head));
   1209  1.157        ad 	addr = TAILQ_FIRST(&pool_head);
   1210   1.51        pk 
   1211  1.126    simonb 	total = inuse = 0;
   1212  1.126    simonb 
   1213  1.157        ad 	for (first = 1; addr != NULL; addr = TAILQ_NEXT(pp, pr_poollist) ) {
   1214   1.87     lukem 		deref_kptr(addr, pp, sizeof(*pp), "pool chain trashed");
   1215   1.98  christos 		deref_kptr(pp->pr_alloc, &pa, sizeof(pa),
   1216  1.125   dsainty 		    "pool allocator trashed");
   1217   1.87     lukem 		deref_kptr(pp->pr_wchan, name, sizeof(name),
   1218   1.98  christos 		    "pool wait channel trashed");
   1219   1.87     lukem 		name[sizeof(name)-1] = '\0';
   1220   1.51        pk 
   1221   1.51        pk 		if (first) {
   1222   1.51        pk 			(void)printf("Memory resource pool statistics\n");
   1223   1.51        pk 			(void)printf(
   1224  1.126    simonb 			    "%-*s%*s%*s%5s%*s%s%s%*s%*s%6s%s%6s%6s%6s%5s%s%s\n",
   1225  1.126    simonb 			    wide ? 16 : 11, "Name",
   1226  1.126    simonb 			    wide ? 6 : 5, "Size",
   1227  1.126    simonb 			    wide ? 12 : 9, "Requests",
   1228   1.75     enami 			    "Fail",
   1229  1.126    simonb 			    wide ? 12 : 9, "Releases",
   1230  1.148    simonb 			    wide ? "  InUse" : "",
   1231  1.126    simonb 			    wide ? " Avail" : "",
   1232  1.126    simonb 			    wide ? 7 : 6, "Pgreq",
   1233  1.126    simonb 			    wide ? 7 : 6, "Pgrel",
   1234   1.75     enami 			    "Npage",
   1235  1.126    simonb 			    wide ? " PageSz" : "",
   1236   1.75     enami 			    "Hiwat",
   1237   1.75     enami 			    "Minpg",
   1238   1.75     enami 			    "Maxpg",
   1239  1.126    simonb 			    "Idle",
   1240  1.126    simonb 			    wide ? " Flags" : "",
   1241  1.126    simonb 			    wide ? "   Util" : "");
   1242   1.51        pk 			first = 0;
   1243   1.51        pk 		}
   1244  1.113       dsl 		if (pp->pr_nget == 0 && !verbose)
   1245  1.113       dsl 			continue;
   1246   1.51        pk 		if (pp->pr_maxpages == UINT_MAX)
   1247  1.153  christos 			(void)snprintf(maxp, sizeof(maxp), "inf");
   1248   1.51        pk 		else
   1249  1.153  christos 			(void)snprintf(maxp, sizeof(maxp), "%u",
   1250  1.153  christos 			    pp->pr_maxpages);
   1251   1.69     enami 		ovflw = 0;
   1252  1.126    simonb 		PRWORD(ovflw, "%-*s", wide ? 16 : 11, 0, name);
   1253  1.126    simonb 		PRWORD(ovflw, " %*u", wide ? 6 : 5, 1, pp->pr_size);
   1254  1.126    simonb 		PRWORD(ovflw, " %*lu", wide ? 12 : 9, 1, pp->pr_nget);
   1255   1.69     enami 		PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nfail);
   1256  1.126    simonb 		PRWORD(ovflw, " %*lu", wide ? 12 : 9, 1, pp->pr_nput);
   1257  1.126    simonb 		if (wide)
   1258  1.148    simonb 			PRWORD(ovflw, " %*u", 7, 1, pp->pr_nout);
   1259  1.126    simonb 		if (wide)
   1260  1.126    simonb 			PRWORD(ovflw, " %*u", 6, 1, pp->pr_nitems);
   1261  1.126    simonb 		PRWORD(ovflw, " %*lu", wide ? 7 : 6, 1, pp->pr_npagealloc);
   1262  1.126    simonb 		PRWORD(ovflw, " %*lu", wide ? 7 : 6, 1, pp->pr_npagefree);
   1263  1.126    simonb 		PRWORD(ovflw, " %*u", 6, 1, pp->pr_npages);
   1264  1.126    simonb 		if (wide)
   1265  1.126    simonb 			PRWORD(ovflw, " %*u", 7, 1, pa.pa_pagesz);
   1266  1.126    simonb 		PRWORD(ovflw, " %*u", 6, 1, pp->pr_hiwat);
   1267  1.126    simonb 		PRWORD(ovflw, " %*u", 6, 1, pp->pr_minpages);
   1268   1.69     enami 		PRWORD(ovflw, " %*s", 6, 1, maxp);
   1269  1.126    simonb 		PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nidle);
   1270  1.126    simonb 		if (wide)
   1271  1.126    simonb 			PRWORD(ovflw, " 0x%0*x", 4, 1,
   1272  1.126    simonb 			    pp->pr_flags | pp->pr_roflags);
   1273   1.51        pk 
   1274  1.126    simonb 		this_inuse = pp->pr_nout * pp->pr_size;
   1275  1.126    simonb 		this_total = pp->pr_npages * pa.pa_pagesz;
   1276   1.84     bjh21 		if (pp->pr_roflags & PR_RECURSIVE) {
   1277   1.84     bjh21 			/*
   1278   1.84     bjh21 			 * Don't count in-use memory, since it's part
   1279   1.84     bjh21 			 * of another pool and will be accounted for
   1280   1.84     bjh21 			 * there.
   1281   1.84     bjh21 			 */
   1282  1.126    simonb 			total += (this_total - this_inuse);
   1283   1.84     bjh21 		} else {
   1284  1.126    simonb 			inuse += this_inuse;
   1285  1.126    simonb 			total += this_total;
   1286   1.84     bjh21 		}
   1287  1.126    simonb 		if (wide) {
   1288  1.126    simonb 			if (this_total == 0)
   1289  1.153  christos 				(void)printf("   ---");
   1290  1.126    simonb 			else
   1291  1.153  christos 				(void)printf(" %5.1f%%",
   1292  1.126    simonb 				    (100.0 * this_inuse) / this_total);
   1293  1.126    simonb 		}
   1294  1.153  christos 		(void)printf("\n");
   1295   1.51        pk 	}
   1296   1.51        pk 
   1297  1.152  christos 	inuse /= KILO;
   1298  1.152  christos 	total /= KILO;
   1299  1.153  christos 	(void)printf(
   1300  1.153  christos 	    "\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n",
   1301  1.126    simonb 	    inuse, total, (100.0 * inuse) / total);
   1302    1.1       cgd }
   1303   1.96     enami 
   1304   1.96     enami void
   1305  1.154        ad dopoolcache(void)
   1306   1.96     enami {
   1307   1.96     enami 	struct pool_cache pool_cache, *pc = &pool_cache;
   1308  1.154        ad 	pool_cache_cpu_t cache_cpu, *cc = &cache_cpu;
   1309  1.157        ad 	TAILQ_HEAD(,pool) pool_head;
   1310  1.154        ad 	struct pool pool, *pp = &pool;
   1311  1.154        ad 	char name[32];
   1312  1.154        ad 	uint64_t cpuhit, cpumiss, tot;
   1313  1.154        ad 	void *addr;
   1314  1.165     lukem 	int first, ovflw;
   1315  1.165     lukem 	size_t i;
   1316  1.154        ad 	double p;
   1317   1.96     enami 
   1318  1.154        ad 	kread(namelist, X_POOLHEAD, &pool_head, sizeof(pool_head));
   1319  1.157        ad 	addr = TAILQ_FIRST(&pool_head);
   1320   1.96     enami 
   1321  1.157        ad 	for (first = 1; addr != NULL; addr = TAILQ_NEXT(pp, pr_poollist) ) {
   1322  1.154        ad 		deref_kptr(addr, pp, sizeof(*pp), "pool chain trashed");
   1323  1.154        ad 		if (pp->pr_cache == NULL)
   1324   1.96     enami 			continue;
   1325  1.154        ad 		deref_kptr(pp->pr_wchan, name, sizeof(name),
   1326  1.154        ad 		    "pool wait channel trashed");
   1327  1.154        ad 		deref_kptr(pp->pr_cache, pc, sizeof(*pc), "pool cache trashed");
   1328  1.154        ad 		name[sizeof(name)-1] = '\0';
   1329  1.154        ad 
   1330  1.154        ad 		cpuhit = 0;
   1331  1.154        ad 		cpumiss = 0;
   1332  1.154        ad 		for (i = 0; i < sizeof(pc->pc_cpus) / sizeof(pc->pc_cpus[0]);
   1333  1.154        ad 		    i++) {
   1334  1.154        ad 		    	if ((addr = pc->pc_cpus[i]) == NULL)
   1335  1.154        ad 		    		continue;
   1336  1.154        ad 			deref_kptr(addr, cc, sizeof(*cc),
   1337  1.154        ad 			    "pool cache cpu trashed");
   1338  1.154        ad 			cpuhit += cc->cc_hits;
   1339  1.154        ad 			cpumiss += cc->cc_misses;
   1340  1.137       chs 		}
   1341  1.154        ad 
   1342  1.154        ad 		if (first) {
   1343  1.154        ad 			(void)printf("Pool cache statistics.\n");
   1344  1.156        ad 			(void)printf("%-*s%*s%*s%*s%*s%*s%*s%*s%*s%*s\n",
   1345  1.154        ad 			    12, "Name",
   1346  1.154        ad 			    6, "Spin",
   1347  1.156        ad 			    6, "GrpSz",
   1348  1.156        ad 			    5, "Full",
   1349  1.156        ad 			    5, "Emty",
   1350  1.156        ad 			    10, "PoolLayer",
   1351  1.156        ad 			    11, "CacheLayer",
   1352  1.154        ad 			    6, "Hit%",
   1353  1.154        ad 			    12, "CpuLayer",
   1354  1.154        ad 			    6, "Hit%"
   1355  1.154        ad 			);
   1356  1.154        ad 			first = 0;
   1357   1.96     enami 		}
   1358  1.154        ad 
   1359  1.154        ad 		ovflw = 0;
   1360  1.154        ad 		PRWORD(ovflw, "%-*s", 13, 1, name);
   1361  1.154        ad 		PRWORD(ovflw, " %*llu", 6, 1, (long long)pc->pc_contended);
   1362  1.156        ad 		PRWORD(ovflw, " %*u", 6, 1, pc->pc_pcgsize);
   1363  1.156        ad 		PRWORD(ovflw, " %*u", 5, 1, pc->pc_nfull);
   1364  1.156        ad 		PRWORD(ovflw, " %*u", 5, 1, pc->pc_nempty);
   1365  1.156        ad 		PRWORD(ovflw, " %*llu", 10, 1, (long long)pc->pc_misses);
   1366  1.154        ad 
   1367  1.154        ad 		tot = pc->pc_hits + pc->pc_misses;
   1368  1.154        ad 		p = pc->pc_hits * 100.0 / (tot);
   1369  1.156        ad 		PRWORD(ovflw, " %*llu", 11, 1, (long long)tot);
   1370  1.154        ad 		PRWORD(ovflw, " %*.1f", 6, 1, p);
   1371  1.154        ad 
   1372  1.154        ad 		tot = cpuhit + cpumiss;
   1373  1.154        ad 		p = cpuhit * 100.0 / (tot);
   1374  1.154        ad 		PRWORD(ovflw, " %*llu", 12, 1, (long long)tot);
   1375  1.154        ad 		PRWORD(ovflw, " %*.1f", 6, 1, p);
   1376  1.154        ad 		printf("\n");
   1377   1.96     enami 	}
   1378   1.96     enami }
   1379   1.90     lukem 
   1380   1.87     lukem enum hashtype {			/* from <sys/systm.h> */
   1381   1.87     lukem 	HASH_LIST,
   1382   1.87     lukem 	HASH_TAILQ
   1383   1.87     lukem };
   1384   1.87     lukem 
   1385   1.87     lukem struct uidinfo {		/* XXX: no kernel header file */
   1386   1.87     lukem 	LIST_ENTRY(uidinfo) ui_hash;
   1387   1.87     lukem 	uid_t	ui_uid;
   1388   1.87     lukem 	long	ui_proccnt;
   1389   1.87     lukem };
   1390   1.87     lukem 
   1391   1.87     lukem struct kernel_hash {
   1392   1.90     lukem 	const char *	description;	/* description */
   1393   1.90     lukem 	int		hashsize;	/* nlist index for hash size */
   1394   1.90     lukem 	int		hashtbl;	/* nlist index for hash table */
   1395   1.90     lukem 	enum hashtype	type;		/* type of hash table */
   1396  1.101  sommerfe 	size_t		offset;		/* offset of {LIST,TAILQ}_NEXT */
   1397   1.87     lukem } khashes[] =
   1398   1.87     lukem {
   1399   1.87     lukem 	{
   1400   1.90     lukem 		"buffer hash",
   1401   1.90     lukem 		X_BUFHASH, X_BUFHASHTBL,
   1402   1.90     lukem 		HASH_LIST, offsetof(struct buf, b_hash)
   1403   1.90     lukem 	}, {
   1404   1.90     lukem 		"inode cache (ihash)",
   1405   1.87     lukem 		X_IHASH, X_IHASHTBL,
   1406   1.87     lukem 		HASH_LIST, offsetof(struct inode, i_hash)
   1407   1.90     lukem 	}, {
   1408   1.90     lukem 		"ipv4 address -> interface hash",
   1409   1.87     lukem 		X_IFADDRHASH, X_IFADDRHASHTBL,
   1410   1.87     lukem 		HASH_LIST, offsetof(struct in_ifaddr, ia_hash),
   1411   1.90     lukem 	}, {
   1412   1.90     lukem 		"name cache hash",
   1413   1.89     lukem 		X_NCHASH, X_NCHASHTBL,
   1414   1.89     lukem 		HASH_LIST, offsetof(struct namecache, nc_hash),
   1415   1.90     lukem 	}, {
   1416   1.90     lukem 		"name cache directory hash",
   1417   1.89     lukem 		X_NCVHASH, X_NCVHASHTBL,
   1418   1.89     lukem 		HASH_LIST, offsetof(struct namecache, nc_vhash),
   1419   1.90     lukem 	}, {
   1420   1.90     lukem 		"user info (uid -> used processes) hash",
   1421   1.90     lukem 		X_UIHASH, X_UIHASHTBL,
   1422   1.90     lukem 		HASH_LIST, offsetof(struct uidinfo, ui_hash),
   1423   1.90     lukem 	}, {
   1424   1.90     lukem 		NULL, -1, -1, 0, 0,
   1425   1.87     lukem 	}
   1426   1.87     lukem };
   1427   1.87     lukem 
   1428   1.87     lukem void
   1429   1.88     lukem dohashstat(int verbose, int todo, const char *hashname)
   1430  1.101  sommerfe {
   1431   1.87     lukem 	LIST_HEAD(, generic)	*hashtbl_list;
   1432   1.87     lukem 	TAILQ_HEAD(, generic)	*hashtbl_tailq;
   1433   1.87     lukem 	struct kernel_hash	*curhash;
   1434  1.118    itojun 	void	*hashaddr, *hashbuf, *nhashbuf, *nextaddr;
   1435   1.87     lukem 	size_t	elemsize, hashbufsize, thissize;
   1436  1.165     lukem 	u_long	hashsize, i;
   1437  1.165     lukem 	int	used, items, chain, maxchain;
   1438   1.87     lukem 
   1439   1.87     lukem 	hashbuf = NULL;
   1440   1.87     lukem 	hashbufsize = 0;
   1441   1.88     lukem 
   1442   1.88     lukem 	if (todo & HASHLIST) {
   1443  1.153  christos 		(void)printf("Supported hashes:\n");
   1444   1.90     lukem 		for (curhash = khashes; curhash->description; curhash++) {
   1445  1.101  sommerfe 			if (hashnl[curhash->hashsize].n_value == 0 ||
   1446   1.90     lukem 			    hashnl[curhash->hashtbl].n_value == 0)
   1447   1.90     lukem 				continue;
   1448  1.153  christos 			(void)printf("\t%-16s%s\n",
   1449   1.90     lukem 			    hashnl[curhash->hashsize].n_name + 1,
   1450   1.90     lukem 			    curhash->description);
   1451   1.88     lukem 		}
   1452   1.88     lukem 		return;
   1453   1.88     lukem 	}
   1454   1.88     lukem 
   1455   1.88     lukem 	if (hashname != NULL) {
   1456   1.90     lukem 		for (curhash = khashes; curhash->description; curhash++) {
   1457   1.90     lukem 			if (strcmp(hashnl[curhash->hashsize].n_name + 1,
   1458   1.90     lukem 			    hashname) == 0 &&
   1459  1.101  sommerfe 			    hashnl[curhash->hashsize].n_value != 0 &&
   1460   1.90     lukem 			    hashnl[curhash->hashtbl].n_value != 0)
   1461   1.88     lukem 				break;
   1462   1.88     lukem 		}
   1463   1.90     lukem 		if (curhash->description == NULL) {
   1464   1.90     lukem 			warnx("%s: no such hash", hashname);
   1465   1.90     lukem 			return;
   1466   1.90     lukem 		}
   1467   1.88     lukem 	}
   1468   1.88     lukem 
   1469  1.153  christos 	(void)printf(
   1470   1.88     lukem 	    "%-16s %8s %8s %8s %8s %8s %8s\n"
   1471   1.88     lukem 	    "%-16s %8s %8s %8s %8s %8s %8s\n",
   1472   1.88     lukem 	    "", "total", "used", "util", "num", "average", "maximum",
   1473   1.88     lukem 	    "hash table", "buckets", "buckets", "%", "items", "chain",
   1474   1.88     lukem 	    "chain");
   1475   1.87     lukem 
   1476   1.90     lukem 	for (curhash = khashes; curhash->description; curhash++) {
   1477  1.101  sommerfe 		if (hashnl[curhash->hashsize].n_value == 0 ||
   1478   1.90     lukem 		    hashnl[curhash->hashtbl].n_value == 0)
   1479   1.90     lukem 			continue;
   1480   1.88     lukem 		if (hashname != NULL &&
   1481   1.90     lukem 		    strcmp(hashnl[curhash->hashsize].n_name + 1, hashname))
   1482   1.88     lukem 			continue;
   1483   1.87     lukem 		elemsize = curhash->type == HASH_LIST ?
   1484   1.87     lukem 		    sizeof(*hashtbl_list) : sizeof(*hashtbl_tailq);
   1485   1.90     lukem 		deref_kptr((void *)hashnl[curhash->hashsize].n_value,
   1486   1.90     lukem 		    &hashsize, sizeof(hashsize),
   1487   1.90     lukem 		    hashnl[curhash->hashsize].n_name);
   1488   1.87     lukem 		hashsize++;
   1489   1.90     lukem 		deref_kptr((void *)hashnl[curhash->hashtbl].n_value,
   1490   1.90     lukem 		    &hashaddr, sizeof(hashaddr),
   1491   1.90     lukem 		    hashnl[curhash->hashtbl].n_name);
   1492   1.87     lukem 		if (verbose)
   1493  1.153  christos 			(void)printf(
   1494  1.153  christos 			    "%s %lu, %s %p, offset %ld, elemsize %llu\n",
   1495   1.90     lukem 			    hashnl[curhash->hashsize].n_name + 1, hashsize,
   1496   1.90     lukem 			    hashnl[curhash->hashtbl].n_name + 1, hashaddr,
   1497  1.101  sommerfe 			    (long)curhash->offset,
   1498   1.91       jmc 			    (unsigned long long)elemsize);
   1499   1.87     lukem 		thissize = hashsize * elemsize;
   1500  1.144  christos 		if (hashbuf == NULL || thissize > hashbufsize) {
   1501  1.118    itojun 			if ((nhashbuf = realloc(hashbuf, thissize)) == NULL)
   1502  1.101  sommerfe 				errx(1, "malloc hashbuf %llu",
   1503   1.91       jmc 				    (unsigned long long)hashbufsize);
   1504  1.118    itojun 			hashbuf = nhashbuf;
   1505  1.118    itojun 			hashbufsize = thissize;
   1506   1.87     lukem 		}
   1507   1.87     lukem 		deref_kptr(hashaddr, hashbuf, thissize,
   1508   1.90     lukem 		    hashnl[curhash->hashtbl].n_name);
   1509   1.87     lukem 		used = 0;
   1510   1.87     lukem 		items = maxchain = 0;
   1511  1.135     lukem 		if (curhash->type == HASH_LIST) {
   1512   1.87     lukem 			hashtbl_list = hashbuf;
   1513  1.135     lukem 			hashtbl_tailq = NULL;
   1514  1.135     lukem 		} else {
   1515  1.135     lukem 			hashtbl_list = NULL;
   1516   1.87     lukem 			hashtbl_tailq = hashbuf;
   1517  1.135     lukem 		}
   1518   1.87     lukem 		for (i = 0; i < hashsize; i++) {
   1519   1.87     lukem 			if (curhash->type == HASH_LIST)
   1520   1.87     lukem 				nextaddr = LIST_FIRST(&hashtbl_list[i]);
   1521   1.87     lukem 			else
   1522   1.87     lukem 				nextaddr = TAILQ_FIRST(&hashtbl_tailq[i]);
   1523   1.87     lukem 			if (nextaddr == NULL)
   1524   1.87     lukem 				continue;
   1525   1.87     lukem 			if (verbose)
   1526  1.165     lukem 				(void)printf("%5lu: %p\n", i, nextaddr);
   1527   1.87     lukem 			used++;
   1528   1.87     lukem 			chain = 0;
   1529   1.87     lukem 			do {
   1530   1.87     lukem 				chain++;
   1531   1.87     lukem 				deref_kptr((char *)nextaddr + curhash->offset,
   1532   1.87     lukem 				    &nextaddr, sizeof(void *),
   1533   1.87     lukem 				    "hash chain corrupted");
   1534   1.87     lukem 				if (verbose > 1)
   1535  1.153  christos 					(void)printf("got nextaddr as %p\n",
   1536   1.87     lukem 					    nextaddr);
   1537   1.87     lukem 			} while (nextaddr != NULL);
   1538   1.87     lukem 			items += chain;
   1539   1.87     lukem 			if (verbose && chain > 1)
   1540  1.153  christos 				(void)printf("\tchain = %d\n", chain);
   1541   1.87     lukem 			if (chain > maxchain)
   1542   1.87     lukem 				maxchain = chain;
   1543   1.87     lukem 		}
   1544  1.153  christos 		(void)printf("%-16s %8ld %8d %8.2f %8d %8.2f %8d\n",
   1545   1.90     lukem 		    hashnl[curhash->hashsize].n_name + 1,
   1546   1.87     lukem 		    hashsize, used, used * 100.0 / hashsize,
   1547   1.93     lukem 		    items, used ? (double)items / used : 0.0, maxchain);
   1548   1.87     lukem 	}
   1549   1.87     lukem }
   1550   1.87     lukem 
   1551    1.1       cgd /*
   1552  1.147    kardel  * kreadc like kread but returns 1 if sucessful, 0 otherwise
   1553  1.147    kardel  */
   1554  1.147    kardel int
   1555  1.147    kardel kreadc(struct nlist *nl, int nlx, void *addr, size_t size)
   1556  1.147    kardel {
   1557  1.147    kardel 	const char *sym;
   1558  1.147    kardel 
   1559  1.147    kardel 	sym = nl[nlx].n_name;
   1560  1.147    kardel 	if (*sym == '_')
   1561  1.147    kardel 		++sym;
   1562  1.147    kardel 	if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0)
   1563  1.147    kardel 		return 0;
   1564  1.147    kardel 	deref_kptr((void *)nl[nlx].n_value, addr, size, sym);
   1565  1.147    kardel 	return 1;
   1566  1.147    kardel }
   1567  1.147    kardel 
   1568  1.147    kardel /*
   1569   1.90     lukem  * kread reads something from the kernel, given its nlist index in namelist[].
   1570    1.1       cgd  */
   1571    1.1       cgd void
   1572  1.133       chs kread(struct nlist *nl, int nlx, void *addr, size_t size)
   1573    1.1       cgd {
   1574   1.50   mycroft 	const char *sym;
   1575    1.1       cgd 
   1576  1.133       chs 	sym = nl[nlx].n_name;
   1577   1.87     lukem 	if (*sym == '_')
   1578   1.87     lukem 		++sym;
   1579  1.133       chs 	if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0)
   1580   1.87     lukem 		errx(1, "symbol %s not defined", sym);
   1581  1.133       chs 	deref_kptr((void *)nl[nlx].n_value, addr, size, sym);
   1582   1.87     lukem }
   1583   1.87     lukem 
   1584   1.87     lukem /*
   1585  1.101  sommerfe  * Dereference the kernel pointer `kptr' and fill in the local copy
   1586   1.87     lukem  * pointed to by `ptr'.  The storage space must be pre-allocated,
   1587   1.87     lukem  * and the size of the copy passed in `len'.
   1588   1.87     lukem  */
   1589   1.87     lukem void
   1590   1.87     lukem deref_kptr(const void *kptr, void *ptr, size_t len, const char *msg)
   1591   1.87     lukem {
   1592   1.87     lukem 
   1593   1.87     lukem 	if (*msg == '_')
   1594   1.87     lukem 		msg++;
   1595  1.165     lukem 	if ((size_t)kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len)
   1596   1.87     lukem 		errx(1, "kptr %lx: %s: %s", (u_long)kptr, msg, kvm_geterr(kd));
   1597    1.1       cgd }
   1598    1.1       cgd 
   1599   1.45   thorpej /*
   1600   1.45   thorpej  * Traverse the UVM history buffers, performing the requested action.
   1601   1.45   thorpej  *
   1602   1.45   thorpej  * Note, we assume that if we're not listing, we're dumping.
   1603   1.45   thorpej  */
   1604   1.45   thorpej void
   1605   1.73    simonb hist_traverse(int todo, const char *histname)
   1606   1.45   thorpej {
   1607   1.45   thorpej 	struct uvm_history_head histhead;
   1608   1.45   thorpej 	struct uvm_history hist, *histkva;
   1609   1.45   thorpej 	char *name = NULL;
   1610   1.45   thorpej 	size_t namelen = 0;
   1611   1.45   thorpej 
   1612   1.90     lukem 	if (histnl[0].n_value == 0) {
   1613   1.87     lukem 		warnx("UVM history is not compiled into the kernel.");
   1614   1.45   thorpej 		return;
   1615   1.45   thorpej 	}
   1616   1.45   thorpej 
   1617   1.87     lukem 	deref_kptr((void *)histnl[X_UVM_HISTORIES].n_value, &histhead,
   1618   1.87     lukem 	    sizeof(histhead), histnl[X_UVM_HISTORIES].n_name);
   1619   1.45   thorpej 
   1620   1.45   thorpej 	if (histhead.lh_first == NULL) {
   1621   1.87     lukem 		warnx("No active UVM history logs.");
   1622   1.45   thorpej 		return;
   1623   1.45   thorpej 	}
   1624   1.45   thorpej 
   1625   1.45   thorpej 	if (todo & HISTLIST)
   1626  1.153  christos 		(void)printf("Active UVM histories:");
   1627   1.45   thorpej 
   1628   1.75     enami 	for (histkva = LIST_FIRST(&histhead); histkva != NULL;
   1629   1.75     enami 	    histkva = LIST_NEXT(&hist, list)) {
   1630   1.87     lukem 		deref_kptr(histkva, &hist, sizeof(hist), "histkva");
   1631  1.142  christos 		if (name == NULL || hist.namelen > namelen) {
   1632   1.45   thorpej 			if (name != NULL)
   1633   1.45   thorpej 				free(name);
   1634   1.45   thorpej 			namelen = hist.namelen;
   1635   1.45   thorpej 			if ((name = malloc(namelen + 1)) == NULL)
   1636   1.45   thorpej 				err(1, "malloc history name");
   1637   1.45   thorpej 		}
   1638   1.45   thorpej 
   1639   1.87     lukem 		deref_kptr(hist.name, name, namelen, "history name");
   1640   1.45   thorpej 		name[namelen] = '\0';
   1641   1.45   thorpej 		if (todo & HISTLIST)
   1642  1.153  christos 			(void)printf(" %s", name);
   1643   1.45   thorpej 		else {
   1644   1.45   thorpej 			/*
   1645   1.45   thorpej 			 * If we're dumping all histories, do it, else
   1646   1.45   thorpej 			 * check to see if this is the one we want.
   1647   1.45   thorpej 			 */
   1648   1.45   thorpej 			if (histname == NULL || strcmp(histname, name) == 0) {
   1649   1.45   thorpej 				if (histname == NULL)
   1650  1.153  christos 					(void)printf(
   1651  1.153  christos 					    "\nUVM history `%s':\n", name);
   1652   1.45   thorpej 				hist_dodump(&hist);
   1653   1.45   thorpej 			}
   1654   1.45   thorpej 		}
   1655   1.45   thorpej 	}
   1656   1.45   thorpej 
   1657   1.45   thorpej 	if (todo & HISTLIST)
   1658  1.153  christos 		(void)putchar('\n');
   1659   1.45   thorpej 
   1660   1.45   thorpej 	if (name != NULL)
   1661   1.45   thorpej 		free(name);
   1662   1.45   thorpej }
   1663   1.45   thorpej 
   1664   1.45   thorpej /*
   1665   1.45   thorpej  * Actually dump the history buffer at the specified KVA.
   1666   1.45   thorpej  */
   1667   1.45   thorpej void
   1668   1.73    simonb hist_dodump(struct uvm_history *histp)
   1669   1.45   thorpej {
   1670   1.45   thorpej 	struct uvm_history_ent *histents, *e;
   1671   1.45   thorpej 	size_t histsize;
   1672   1.45   thorpej 	char *fmt = NULL, *fn = NULL;
   1673   1.45   thorpej 	size_t fmtlen = 0, fnlen = 0;
   1674  1.169     pooka 	unsigned i;
   1675   1.45   thorpej 
   1676   1.45   thorpej 	histsize = sizeof(struct uvm_history_ent) * histp->n;
   1677   1.45   thorpej 
   1678   1.45   thorpej 	if ((histents = malloc(histsize)) == NULL)
   1679   1.45   thorpej 		err(1, "malloc history entries");
   1680   1.45   thorpej 
   1681  1.153  christos 	(void)memset(histents, 0, histsize);
   1682   1.45   thorpej 
   1683   1.87     lukem 	deref_kptr(histp->e, histents, histsize, "history entries");
   1684   1.45   thorpej 	i = histp->f;
   1685   1.45   thorpej 	do {
   1686   1.45   thorpej 		e = &histents[i];
   1687   1.45   thorpej 		if (e->fmt != NULL) {
   1688  1.143  christos 			if (fmt == NULL || e->fmtlen > fmtlen) {
   1689   1.45   thorpej 				if (fmt != NULL)
   1690   1.45   thorpej 					free(fmt);
   1691   1.45   thorpej 				fmtlen = e->fmtlen;
   1692   1.45   thorpej 				if ((fmt = malloc(fmtlen + 1)) == NULL)
   1693   1.45   thorpej 					err(1, "malloc printf format");
   1694   1.45   thorpej 			}
   1695  1.143  christos 			if (fn == NULL || e->fnlen > fnlen) {
   1696   1.45   thorpej 				if (fn != NULL)
   1697   1.45   thorpej 					free(fn);
   1698   1.45   thorpej 				fnlen = e->fnlen;
   1699   1.45   thorpej 				if ((fn = malloc(fnlen + 1)) == NULL)
   1700   1.45   thorpej 					err(1, "malloc function name");
   1701   1.45   thorpej 			}
   1702   1.45   thorpej 
   1703   1.87     lukem 			deref_kptr(e->fmt, fmt, fmtlen, "printf format");
   1704   1.45   thorpej 			fmt[fmtlen] = '\0';
   1705   1.45   thorpej 
   1706   1.87     lukem 			deref_kptr(e->fn, fn, fnlen, "function name");
   1707   1.45   thorpej 			fn[fnlen] = '\0';
   1708   1.45   thorpej 
   1709  1.153  christos 			(void)printf("%06ld.%06ld ", (long int)e->tv.tv_sec,
   1710   1.61    kleink 			    (long int)e->tv.tv_usec);
   1711  1.153  christos 			(void)printf("%s#%ld: ", fn, e->call);
   1712  1.153  christos 			(void)printf(fmt, e->v[0], e->v[1], e->v[2], e->v[3]);
   1713  1.153  christos 			(void)putchar('\n');
   1714   1.45   thorpej 		}
   1715   1.45   thorpej 		i = (i + 1) % histp->n;
   1716   1.45   thorpej 	} while (i != histp->f);
   1717   1.45   thorpej 
   1718   1.45   thorpej 	free(histents);
   1719   1.45   thorpej 	if (fmt != NULL)
   1720   1.45   thorpej 		free(fmt);
   1721   1.45   thorpej 	if (fn != NULL)
   1722   1.45   thorpej 		free(fn);
   1723   1.45   thorpej }
   1724   1.45   thorpej 
   1725    1.1       cgd void
   1726   1.73    simonb usage(void)
   1727    1.1       cgd {
   1728   1.47       mrg 
   1729    1.1       cgd 	(void)fprintf(stderr,
   1730  1.155      yamt 	    "usage: %s [-CefHiLlmstUvW] [-c count] [-h hashname] [-M core] [-N system]\n"
   1731  1.127       wiz 	    "\t\t[-u histname] [-w wait] [disks]\n", getprogname());
   1732    1.1       cgd 	exit(1);
   1733    1.1       cgd }
   1734