Home | History | Annotate | Line # | Download | only in vmstat
      1  1.262     skrll /* $NetBSD: vmstat.c,v 1.262 2025/02/16 10:56:31 skrll Exp $ */
      2   1.45   thorpej 
      3   1.45   thorpej /*-
      4  1.235        ad  * Copyright (c) 1998, 2000, 2001, 2007, 2019, 2020
      5  1.235        ad  *     The NetBSD Foundation, Inc.
      6   1.45   thorpej  * All rights reserved.
      7   1.45   thorpej  *
      8   1.87     lukem  * This code is derived from software contributed to The NetBSD Foundation by:
      9   1.87     lukem  *	- Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
     10   1.87     lukem  *	  NASA Ames Research Center.
     11   1.87     lukem  *	- Simon Burge and Luke Mewburn of Wasabi Systems, Inc.
     12   1.45   thorpej  *
     13   1.45   thorpej  * Redistribution and use in source and binary forms, with or without
     14   1.45   thorpej  * modification, are permitted provided that the following conditions
     15   1.45   thorpej  * are met:
     16   1.45   thorpej  * 1. Redistributions of source code must retain the above copyright
     17   1.45   thorpej  *    notice, this list of conditions and the following disclaimer.
     18   1.45   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     19   1.45   thorpej  *    notice, this list of conditions and the following disclaimer in the
     20   1.45   thorpej  *    documentation and/or other materials provided with the distribution.
     21   1.45   thorpej  *
     22   1.45   thorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     23   1.45   thorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     24   1.45   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     25   1.45   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     26   1.45   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27   1.45   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28   1.45   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29   1.45   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30   1.45   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31   1.45   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32   1.45   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     33   1.45   thorpej  */
     34   1.21       cgd 
     35    1.1       cgd /*
     36   1.13       cgd  * Copyright (c) 1980, 1986, 1991, 1993
     37   1.13       cgd  *	The Regents of the University of California.  All rights reserved.
     38    1.1       cgd  *
     39    1.1       cgd  * Redistribution and use in source and binary forms, with or without
     40    1.1       cgd  * modification, are permitted provided that the following conditions
     41    1.1       cgd  * are met:
     42    1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     43    1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     44    1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     45    1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     46    1.1       cgd  *    documentation and/or other materials provided with the distribution.
     47  1.117       agc  * 3. Neither the name of the University nor the names of its contributors
     48    1.1       cgd  *    may be used to endorse or promote products derived from this software
     49    1.1       cgd  *    without specific prior written permission.
     50    1.1       cgd  *
     51    1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     52    1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     53    1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     54    1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     55    1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     56    1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     57    1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58    1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     59    1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     60    1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     61    1.1       cgd  * SUCH DAMAGE.
     62    1.1       cgd  */
     63    1.1       cgd 
     64   1.38       mrg #include <sys/cdefs.h>
     65    1.1       cgd #ifndef lint
     66  1.161     lukem __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\
     67  1.161     lukem  The Regents of the University of California.  All rights reserved.");
     68    1.1       cgd #endif /* not lint */
     69    1.1       cgd 
     70    1.1       cgd #ifndef lint
     71   1.21       cgd #if 0
     72   1.37       mrg static char sccsid[] = "@(#)vmstat.c	8.2 (Berkeley) 3/1/95";
     73   1.21       cgd #else
     74  1.262     skrll __RCSID("$NetBSD: vmstat.c,v 1.262 2025/02/16 10:56:31 skrll Exp $");
     75   1.21       cgd #endif
     76    1.1       cgd #endif /* not lint */
     77   1.57   thorpej 
     78   1.57   thorpej #define	__POOL_EXPOSE
     79  1.228  christos #define __NAMECACHE_PRIVATE
     80    1.1       cgd 
     81    1.1       cgd #include <sys/param.h>
     82  1.174  christos #include <sys/types.h>
     83   1.87     lukem #include <sys/mount.h>
     84   1.87     lukem #include <sys/uio.h>
     85   1.87     lukem 
     86   1.87     lukem #include <sys/buf.h>
     87  1.146      yamt #include <sys/evcnt.h>
     88   1.87     lukem #include <sys/ioctl.h>
     89   1.87     lukem #include <sys/malloc.h>
     90  1.109   thorpej #include <sys/mallocvar.h>
     91    1.1       cgd #include <sys/namei.h>
     92   1.87     lukem #include <sys/pool.h>
     93   1.87     lukem #include <sys/proc.h>
     94   1.64     perry #include <sys/sched.h>
     95   1.87     lukem #include <sys/socket.h>
     96   1.13       cgd #include <sys/sysctl.h>
     97   1.87     lukem #include <sys/time.h>
     98  1.171  christos #include <sys/queue.h>
     99  1.181       mrg #include <sys/kernhist.h>
    100  1.229        ad #include <sys/vnode.h>
    101  1.229        ad #include <sys/vnode_impl.h>
    102  1.258        ad #include <sys/uidinfo.h>
    103   1.67       mrg 
    104   1.67       mrg #include <uvm/uvm_extern.h>
    105   1.67       mrg #include <uvm/uvm_stat.h>
    106   1.67       mrg 
    107   1.87     lukem #include <net/if.h>
    108   1.87     lukem #include <netinet/in.h>
    109   1.87     lukem #include <netinet/in_var.h>
    110   1.87     lukem 
    111   1.87     lukem #include <ufs/ufs/inode.h>
    112   1.87     lukem 
    113   1.87     lukem #include <nfs/rpcv2.h>
    114   1.87     lukem #include <nfs/nfsproto.h>
    115   1.87     lukem #include <nfs/nfsnode.h>
    116   1.87     lukem 
    117  1.245    simonb #include <assert.h>
    118   1.87     lukem #include <ctype.h>
    119   1.45   thorpej #include <err.h>
    120   1.87     lukem #include <errno.h>
    121   1.55    kleink #include <fcntl.h>
    122   1.87     lukem #include <kvm.h>
    123   1.87     lukem #include <limits.h>
    124    1.1       cgd #include <nlist.h>
    125   1.87     lukem #undef n_hash
    126   1.87     lukem #include <paths.h>
    127   1.22       jtc #include <signal.h>
    128    1.1       cgd #include <stdio.h>
    129   1.87     lukem #include <stddef.h>
    130    1.1       cgd #include <stdlib.h>
    131    1.1       cgd #include <string.h>
    132   1.87     lukem #include <time.h>
    133   1.87     lukem #include <unistd.h>
    134  1.104       mrg #include <util.h>
    135   1.87     lukem 
    136  1.140     blymn #include "drvstats.h"
    137   1.45   thorpej 
    138   1.90     lukem /*
    139  1.174  christos  * All this mess will go away once everything is converted.
    140  1.174  christos  */
    141  1.174  christos #ifdef __HAVE_CPU_DATA_FIRST
    142  1.175  christos 
    143  1.175  christos # include <sys/cpu_data.h>
    144  1.175  christos struct cpu_info {
    145  1.174  christos 	struct cpu_data ci_data;
    146  1.174  christos };
    147  1.174  christos #else
    148  1.190     rmind # include <sys/cpu.h>
    149  1.190     rmind #endif
    150  1.175  christos 
    151  1.174  christos /*
    152   1.90     lukem  * General namelist
    153   1.90     lukem  */
    154   1.87     lukem struct nlist namelist[] =
    155   1.87     lukem {
    156  1.232       mrg #define	X_HZ		0
    157  1.153  christos 	{ .n_name = "_hz" },
    158  1.232       mrg #define	X_STATHZ	1
    159  1.153  christos 	{ .n_name = "_stathz" },
    160  1.232       mrg #define	X_NCHSTATS	2
    161  1.153  christos 	{ .n_name = "_nchstats" },
    162  1.232       mrg #define	X_ALLEVENTS	3
    163  1.153  christos 	{ .n_name = "_allevents" },
    164  1.232       mrg #define	X_POOLHEAD	4
    165  1.153  christos 	{ .n_name = "_pool_head" },
    166  1.232       mrg #define	X_UVMEXP	5
    167  1.153  christos 	{ .n_name = "_uvmexp" },
    168  1.232       mrg #define X_CPU_INFOS	6
    169  1.232       mrg 	{ .n_name = "_cpu_infos" },
    170  1.232       mrg #define	X_NL_SIZE	7
    171  1.232       mrg 	{ .n_name = NULL },
    172  1.232       mrg };
    173  1.232       mrg 
    174  1.232       mrg /*
    175  1.232       mrg  * Namelist for time data.
    176  1.232       mrg  */
    177  1.232       mrg struct nlist timenl[] =
    178  1.232       mrg {
    179  1.232       mrg #define	X_TIMEBASEBIN	0
    180  1.232       mrg 	{ .n_name = "_timebasebin" },
    181  1.232       mrg #define	X_TIME_SECOND	1
    182  1.153  christos 	{ .n_name = "_time_second" },
    183  1.232       mrg #define X_TIME		2
    184  1.153  christos 	{ .n_name = "_time" },
    185  1.232       mrg #define	X_TIMENL_SIZE	3
    186  1.153  christos 	{ .n_name = NULL },
    187   1.90     lukem };
    188   1.90     lukem 
    189   1.90     lukem /*
    190  1.133       chs  * Namelist for pre-evcnt interrupt counters.
    191  1.133       chs  */
    192  1.133       chs struct nlist intrnl[] =
    193  1.133       chs {
    194  1.133       chs #define	X_INTRNAMES	0
    195  1.153  christos 	{ .n_name = "_intrnames" },
    196  1.133       chs #define	X_EINTRNAMES	1
    197  1.153  christos 	{ .n_name = "_eintrnames" },
    198  1.133       chs #define	X_INTRCNT	2
    199  1.153  christos 	{ .n_name = "_intrcnt" },
    200  1.133       chs #define	X_EINTRCNT	3
    201  1.153  christos 	{ .n_name = "_eintrcnt" },
    202  1.133       chs #define	X_INTRNL_SIZE	4
    203  1.153  christos 	{ .n_name = NULL },
    204  1.133       chs };
    205  1.133       chs 
    206  1.133       chs 
    207  1.133       chs /*
    208   1.90     lukem  * Namelist for hash statistics
    209   1.90     lukem  */
    210   1.90     lukem struct nlist hashnl[] =
    211   1.90     lukem {
    212  1.245    simonb #define	X_BUFHASH	0
    213  1.153  christos 	{ .n_name = "_bufhash" },
    214  1.245    simonb #define	X_BUFHASHTBL	1
    215  1.153  christos 	{ .n_name = "_bufhashtbl" },
    216  1.245    simonb #define	X_UIHASH	2
    217  1.153  christos 	{ .n_name = "_uihash" },
    218  1.245    simonb #define	X_UIHASHTBL	3
    219  1.153  christos 	{ .n_name = "_uihashtbl" },
    220  1.245    simonb #define	X_IFADDRHASH	4
    221  1.153  christos 	{ .n_name = "_in_ifaddrhash" },
    222  1.245    simonb #define	X_IFADDRHASHTBL	5
    223  1.153  christos 	{ .n_name = "_in_ifaddrhashtbl" },
    224  1.245    simonb #define	X_VCACHEHASH	6
    225  1.229        ad 	{ .n_name = "_vcache_hashmask" },
    226  1.245    simonb #define	X_VCACHETBL	7
    227  1.229        ad 	{ .n_name = "_vcache_hashtab" },
    228  1.245    simonb #define X_HASHNL_SIZE	8	/* must be last */
    229  1.153  christos 	{ .n_name = NULL },
    230   1.90     lukem };
    231   1.87     lukem 
    232   1.90     lukem /*
    233  1.181       mrg  * Namelist for kernel histories
    234   1.90     lukem  */
    235   1.90     lukem struct nlist histnl[] =
    236   1.90     lukem {
    237  1.181       mrg 	{ .n_name = "_kern_histories" },
    238  1.181       mrg #define	X_KERN_HISTORIES		0
    239  1.153  christos 	{ .n_name = NULL },
    240    1.1       cgd };
    241    1.1       cgd 
    242   1.87     lukem 
    243  1.205     skrll #define KILO	1024
    244   1.90     lukem 
    245  1.171  christos struct cpu_counter {
    246  1.171  christos 	uint64_t nintr;
    247  1.171  christos 	uint64_t nsyscall;
    248  1.171  christos 	uint64_t nswtch;
    249  1.171  christos 	uint64_t nfault;
    250  1.171  christos 	uint64_t ntrap;
    251  1.171  christos 	uint64_t nsoft;
    252  1.171  christos } cpucounter, ocpucounter;
    253  1.171  christos 
    254  1.196     joerg struct	uvmexp_sysctl uvmexp, ouvmexp;
    255   1.73    simonb int	ndrives;
    256    1.1       cgd 
    257    1.1       cgd int	winlines = 20;
    258    1.1       cgd 
    259   1.13       cgd kvm_t *kd;
    260   1.13       cgd 
    261  1.174  christos 
    262  1.185  christos #define	FORKSTAT	0x001
    263  1.185  christos #define	INTRSTAT	0x002
    264  1.185  christos #define	MEMSTAT		0x004
    265  1.185  christos #define	SUMSTAT		0x008
    266  1.185  christos #define	EVCNTSTAT	0x010
    267  1.185  christos #define	VMSTAT		0x020
    268  1.185  christos #define	HISTLIST	0x040
    269  1.185  christos #define	HISTDUMP	0x080
    270  1.185  christos #define	HASHSTAT	0x100
    271  1.185  christos #define	HASHLIST	0x200
    272  1.185  christos #define	VMTOTAL		0x400
    273  1.185  christos #define	POOLCACHESTAT	0x800
    274    1.1       cgd 
    275  1.151      yamt /*
    276  1.151      yamt  * Print single word.  `ovflow' is number of characters didn't fit
    277  1.151      yamt  * on the last word.  `fmt' is a format string to print this word.
    278  1.151      yamt  * It must contain asterisk for field width.  `width' is a width
    279  1.151      yamt  * occupied by this word.  `fixed' is a number of constant chars in
    280  1.151      yamt  * `fmt'.  `val' is a value to be printed using format string `fmt'.
    281  1.151      yamt  */
    282  1.151      yamt #define	PRWORD(ovflw, fmt, width, fixed, val) do {	\
    283  1.151      yamt 	(ovflw) += printf((fmt),			\
    284  1.151      yamt 	    (width) - (fixed) - (ovflw) > 0 ?		\
    285  1.151      yamt 	    (width) - (fixed) - (ovflw) : 0,		\
    286  1.151      yamt 	    (val)) - (width);				\
    287  1.151      yamt 	if ((ovflw) < 0)				\
    288  1.151      yamt 		(ovflw) = 0;				\
    289  1.248    rillig } while (0)
    290  1.151      yamt 
    291  1.151      yamt void	cpustats(int *);
    292  1.171  christos void	cpucounters(struct cpu_counter *);
    293   1.87     lukem void	deref_kptr(const void *, void *, size_t, const char *);
    294  1.151      yamt void	drvstats(int *);
    295  1.176      matt void	doevcnt(int verbose, int type);
    296   1.88     lukem void	dohashstat(int, int, const char *);
    297  1.245    simonb void	dohashstat_sysctl(int, int, const char *);
    298   1.73    simonb void	dointr(int verbose);
    299  1.126    simonb void	dopool(int, int);
    300  1.182      yamt void	dopoolcache(int);
    301   1.73    simonb void	dosum(void);
    302  1.103   mycroft void	dovmstat(struct timespec *, int);
    303  1.130        he void	print_total_hdr(void);
    304  1.130        he void	dovmtotal(struct timespec *, int);
    305  1.133       chs void	kread(struct nlist *, int, void *, size_t);
    306  1.147    kardel int	kreadc(struct nlist *, int, void *, size_t);
    307   1.73    simonb void	needhdr(int);
    308  1.176      matt void	getnlist(int);
    309   1.73    simonb long	getuptime(void);
    310   1.73    simonb void	printhdr(void);
    311  1.203  nakayama long	pct(u_long, u_long);
    312  1.183     joerg __dead static void	usage(void);
    313   1.73    simonb void	doforkst(void);
    314   1.73    simonb 
    315   1.73    simonb void	hist_traverse(int, const char *);
    316  1.210  pgoyette void	hist_dodump(struct kern_history *);
    317  1.210  pgoyette void	hist_traverse_sysctl(int, const char *);
    318  1.210  pgoyette void	hist_dodump_sysctl(int[], unsigned int);
    319   1.73    simonb 
    320   1.73    simonb char	**choosedrives(char **);
    321   1.38       mrg 
    322   1.29   thorpej /* Namelist and memory file names. */
    323   1.29   thorpej char	*nlistf, *memf;
    324   1.29   thorpej 
    325   1.47       mrg /* allow old usage [vmstat 1] */
    326   1.47       mrg #define	BACKWARD_COMPATIBILITY
    327   1.47       mrg 
    328  1.197     joerg static const int clockrate_mib[] = { CTL_KERN, KERN_CLOCKRATE };
    329  1.170  christos static const int vmmeter_mib[] = { CTL_VM, VM_METER };
    330  1.170  christos static const int uvmexp2_mib[] = { CTL_VM, VM_UVMEXP2 };
    331  1.176      matt static const int boottime_mib[] = { CTL_KERN, KERN_BOOTTIME };
    332  1.170  christos 
    333  1.252    rillig static int numdisks = 2;
    334  1.250       mrg 
    335   1.38       mrg int
    336   1.75     enami main(int argc, char *argv[])
    337    1.1       cgd {
    338  1.126    simonb 	int c, todo, verbose, wide;
    339  1.103   mycroft 	struct timespec interval;
    340    1.1       cgd 	int reps;
    341   1.88     lukem 	const char *histname, *hashname;
    342  1.246    simonb 	char errbuf[_POSIX2_LINE_MAX];
    343    1.1       cgd 
    344   1.88     lukem 	histname = hashname = NULL;
    345   1.13       cgd 	memf = nlistf = NULL;
    346  1.126    simonb 	reps = todo = verbose = wide = 0;
    347  1.103   mycroft 	interval.tv_sec = 0;
    348  1.103   mycroft 	interval.tv_nsec = 0;
    349  1.250       mrg 	while ((c = getopt(argc, argv, "Cc:efh:HilLM:mN:n:stu:UvWw:")) != -1) {
    350    1.1       cgd 		switch (c) {
    351    1.1       cgd 		case 'c':
    352    1.1       cgd 			reps = atoi(optarg);
    353    1.1       cgd 			break;
    354  1.154        ad 		case 'C':
    355  1.154        ad 			todo |= POOLCACHESTAT;
    356  1.154        ad 			break;
    357   1.66       cgd 		case 'e':
    358   1.66       cgd 			todo |= EVCNTSTAT;
    359   1.66       cgd 			break;
    360    1.1       cgd 		case 'f':
    361    1.1       cgd 			todo |= FORKSTAT;
    362    1.1       cgd 			break;
    363   1.45   thorpej 		case 'h':
    364   1.88     lukem 			hashname = optarg;
    365   1.88     lukem 			/* FALLTHROUGH */
    366   1.88     lukem 		case 'H':
    367   1.87     lukem 			todo |= HASHSTAT;
    368   1.45   thorpej 			break;
    369    1.1       cgd 		case 'i':
    370    1.1       cgd 			todo |= INTRSTAT;
    371    1.1       cgd 			break;
    372   1.45   thorpej 		case 'l':
    373   1.45   thorpej 			todo |= HISTLIST;
    374   1.45   thorpej 			break;
    375   1.88     lukem 		case 'L':
    376   1.88     lukem 			todo |= HASHLIST;
    377   1.88     lukem 			break;
    378    1.1       cgd 		case 'M':
    379   1.13       cgd 			memf = optarg;
    380    1.1       cgd 			break;
    381    1.1       cgd 		case 'm':
    382    1.1       cgd 			todo |= MEMSTAT;
    383    1.1       cgd 			break;
    384    1.1       cgd 		case 'N':
    385   1.13       cgd 			nlistf = optarg;
    386    1.1       cgd 			break;
    387  1.250       mrg 		case 'n':
    388  1.250       mrg 			numdisks = atoi(optarg);
    389  1.250       mrg 			break;
    390    1.1       cgd 		case 's':
    391    1.1       cgd 			todo |= SUMSTAT;
    392    1.1       cgd 			break;
    393  1.130        he 		case 't':
    394  1.130        he 			todo |= VMTOTAL;
    395  1.130        he 			break;
    396   1.87     lukem 		case 'u':
    397   1.87     lukem 			histname = optarg;
    398   1.87     lukem 			/* FALLTHROUGH */
    399   1.87     lukem 		case 'U':
    400   1.87     lukem 			todo |= HISTDUMP;
    401   1.87     lukem 			break;
    402   1.66       cgd 		case 'v':
    403   1.87     lukem 			verbose++;
    404   1.66       cgd 			break;
    405  1.126    simonb 		case 'W':
    406  1.126    simonb 			wide++;
    407  1.126    simonb 			break;
    408    1.1       cgd 		case 'w':
    409  1.103   mycroft 			interval.tv_sec = atol(optarg);
    410    1.1       cgd 			break;
    411    1.1       cgd 		case '?':
    412    1.1       cgd 		default:
    413    1.1       cgd 			usage();
    414    1.1       cgd 		}
    415    1.1       cgd 	}
    416    1.1       cgd 	argc -= optind;
    417    1.1       cgd 	argv += optind;
    418    1.1       cgd 
    419    1.1       cgd 	if (todo == 0)
    420    1.1       cgd 		todo = VMSTAT;
    421    1.1       cgd 
    422  1.246    simonb 	if (memf == NULL) {
    423  1.246    simonb 		kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
    424  1.246    simonb 	} else {
    425  1.246    simonb 		kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
    426  1.176      matt 	}
    427   1.48       mrg 
    428  1.246    simonb 	if (kd == NULL)
    429  1.246    simonb 		errx(EXIT_FAILURE, "%s", errbuf);
    430    1.1       cgd 
    431  1.254    simonb 	if (memf != NULL)
    432  1.254    simonb 		getnlist(todo);	/* Only need this if a core is specified. */
    433  1.254    simonb 
    434    1.1       cgd 	if (todo & VMSTAT) {
    435    1.1       cgd 		struct winsize winsize;
    436    1.1       cgd 
    437  1.153  christos 		(void)drvinit(0);/* Initialize disk stats, no disks selected. */
    438   1.49  drochner 
    439   1.29   thorpej 		argv = choosedrives(argv);	/* Select disks. */
    440    1.1       cgd 		winsize.ws_row = 0;
    441  1.115    simonb 		(void)ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
    442    1.1       cgd 		if (winsize.ws_row > 0)
    443    1.1       cgd 			winlines = winsize.ws_row;
    444    1.1       cgd 
    445    1.1       cgd 	}
    446    1.1       cgd 
    447    1.1       cgd #ifdef	BACKWARD_COMPATIBILITY
    448    1.1       cgd 	if (*argv) {
    449  1.103   mycroft 		interval.tv_sec = atol(*argv);
    450    1.1       cgd 		if (*++argv)
    451    1.1       cgd 			reps = atoi(*argv);
    452    1.1       cgd 	}
    453    1.1       cgd #endif
    454    1.1       cgd 
    455  1.103   mycroft 	if (interval.tv_sec) {
    456    1.1       cgd 		if (!reps)
    457    1.1       cgd 			reps = -1;
    458    1.1       cgd 	} else if (reps)
    459  1.103   mycroft 		interval.tv_sec = 1;
    460    1.1       cgd 
    461   1.78     jhawk 	/*
    462   1.78     jhawk 	 * Statistics dumping is incompatible with the default
    463   1.78     jhawk 	 * VMSTAT/dovmstat() output. So perform the interval/reps handling
    464   1.78     jhawk 	 * for it here.
    465   1.78     jhawk 	 */
    466  1.130        he 	if ((todo & (VMSTAT|VMTOTAL)) == 0) {
    467   1.99     enami 		for (;;) {
    468   1.99     enami 			if (todo & (HISTLIST|HISTDUMP)) {
    469   1.99     enami 				if ((todo & (HISTLIST|HISTDUMP)) ==
    470   1.99     enami 				    (HISTLIST|HISTDUMP))
    471   1.99     enami 					errx(1, "you may list or dump,"
    472   1.99     enami 					    " but not both!");
    473  1.210  pgoyette 				if (memf != NULL)
    474  1.210  pgoyette 					hist_traverse(todo, histname);
    475  1.210  pgoyette 				else
    476  1.210  pgoyette 					hist_traverse_sysctl(todo, histname);
    477  1.153  christos 				(void)putchar('\n');
    478   1.99     enami 			}
    479   1.99     enami 			if (todo & FORKSTAT) {
    480   1.99     enami 				doforkst();
    481  1.153  christos 				(void)putchar('\n');
    482   1.99     enami 			}
    483   1.99     enami 			if (todo & MEMSTAT) {
    484  1.126    simonb 				dopool(verbose, wide);
    485  1.153  christos 				(void)putchar('\n');
    486   1.99     enami 			}
    487  1.154        ad 			if (todo & POOLCACHESTAT) {
    488  1.182      yamt 				dopoolcache(verbose);
    489  1.154        ad 				(void)putchar('\n');
    490  1.154        ad 			}
    491   1.99     enami 			if (todo & SUMSTAT) {
    492   1.99     enami 				dosum();
    493  1.153  christos 				(void)putchar('\n');
    494   1.99     enami 			}
    495   1.99     enami 			if (todo & INTRSTAT) {
    496   1.99     enami 				dointr(verbose);
    497  1.153  christos 				(void)putchar('\n');
    498   1.99     enami 			}
    499   1.99     enami 			if (todo & EVCNTSTAT) {
    500  1.176      matt 				doevcnt(verbose, EVCNT_TYPE_ANY);
    501  1.153  christos 				(void)putchar('\n');
    502   1.99     enami 			}
    503   1.99     enami 			if (todo & (HASHLIST|HASHSTAT)) {
    504   1.99     enami 				if ((todo & (HASHLIST|HASHSTAT)) ==
    505   1.99     enami 				    (HASHLIST|HASHSTAT))
    506   1.99     enami 					errx(1, "you may list or display,"
    507   1.99     enami 					    " but not both!");
    508   1.99     enami 				dohashstat(verbose, todo, hashname);
    509  1.153  christos 				(void)putchar('\n');
    510   1.99     enami 			}
    511  1.101  sommerfe 
    512  1.164  dholland 			fflush(stdout);
    513  1.101  sommerfe 			if (reps >= 0 && --reps <=0)
    514   1.99     enami 				break;
    515  1.153  christos 			(void)nanosleep(&interval, NULL);
    516   1.87     lukem 		}
    517  1.130        he 	} else {
    518  1.130        he 		if ((todo & (VMSTAT|VMTOTAL)) == (VMSTAT|VMTOTAL)) {
    519  1.130        he 			errx(1, "you may not both do vmstat and vmtotal");
    520  1.130        he 		}
    521  1.130        he 		if (todo & VMSTAT)
    522  1.130        he 			dovmstat(&interval, reps);
    523  1.130        he 		if (todo & VMTOTAL)
    524  1.130        he 			dovmtotal(&interval, reps);
    525  1.130        he 	}
    526  1.153  christos 	return 0;
    527    1.1       cgd }
    528    1.1       cgd 
    529  1.176      matt void
    530  1.176      matt getnlist(int todo)
    531  1.176      matt {
    532  1.185  christos 	static int done = 0;
    533  1.176      matt 	int c;
    534  1.176      matt 	size_t i;
    535  1.176      matt 
    536  1.246    simonb 	if ((c = kvm_nlist(kd, namelist)) != 0) {
    537  1.246    simonb 		int doexit = 0;
    538  1.246    simonb 		if (c == -1)
    539  1.246    simonb 			errx(1, "kvm_nlist: %s %s",
    540  1.246    simonb 			    "namelist", kvm_geterr(kd));
    541  1.246    simonb 		for (i = 0; i < __arraycount(namelist)-1; i++)
    542  1.246    simonb 			if (namelist[i].n_type == 0) {
    543  1.246    simonb 				if (doexit++ == 0)
    544  1.246    simonb 					(void)fprintf(stderr,
    545  1.246    simonb 					    "%s: undefined symbols:",
    546  1.246    simonb 					    getprogname());
    547  1.246    simonb 				(void)fprintf(stderr, " %s",
    548  1.246    simonb 				    namelist[i].n_name);
    549  1.176      matt 			}
    550  1.246    simonb 		if (doexit) {
    551  1.246    simonb 			(void)fputc('\n', stderr);
    552  1.246    simonb 			exit(1);
    553  1.176      matt 		}
    554  1.176      matt 	}
    555  1.246    simonb 
    556  1.232       mrg 	if ((todo & (VMSTAT|INTRSTAT)) && !(done & (VMSTAT))) {
    557  1.232       mrg 		done |= VMSTAT;
    558  1.232       mrg 		if ((c = kvm_nlist(kd, timenl)) == -1 || c == X_TIMENL_SIZE)
    559  1.232       mrg 			errx(1, "kvm_nlist: %s %s", "timenl", kvm_geterr(kd));
    560  1.232       mrg 	}
    561  1.185  christos 	if ((todo & (SUMSTAT|INTRSTAT)) && !(done & (SUMSTAT|INTRSTAT))) {
    562  1.185  christos 		done |= SUMSTAT|INTRSTAT;
    563  1.176      matt 		(void) kvm_nlist(kd, intrnl);
    564  1.176      matt 	}
    565  1.185  christos 	if ((todo & (HASHLIST|HASHSTAT)) && !(done & (HASHLIST|HASHSTAT))) {
    566  1.185  christos 		done |= HASHLIST|HASHSTAT;
    567  1.176      matt 		if ((c = kvm_nlist(kd, hashnl)) == -1 || c == X_HASHNL_SIZE)
    568  1.176      matt 			errx(1, "kvm_nlist: %s %s", "hashnl", kvm_geterr(kd));
    569  1.176      matt 	}
    570  1.185  christos 	if ((todo & (HISTLIST|HISTDUMP)) && !(done & (HISTLIST|HISTDUMP))) {
    571  1.185  christos 		done |= HISTLIST|HISTDUMP;
    572  1.176      matt 		if (kvm_nlist(kd, histnl) == -1)
    573  1.176      matt 			errx(1, "kvm_nlist: %s %s", "histnl", kvm_geterr(kd));
    574  1.176      matt 	}
    575  1.176      matt }
    576  1.176      matt 
    577    1.1       cgd char **
    578   1.73    simonb choosedrives(char **argv)
    579    1.1       cgd {
    580  1.249       mrg 	size_t i, j, k;
    581    1.1       cgd 
    582    1.1       cgd 	/*
    583    1.1       cgd 	 * Choose drives to be displayed.  Priority goes to (in order) drives
    584    1.1       cgd 	 * supplied as arguments, default drives.  If everything isn't filled
    585    1.1       cgd 	 * in and there are drives not taken care of, display the first few
    586    1.1       cgd 	 * that fit.
    587    1.1       cgd 	 */
    588   1.75     enami #define	BACKWARD_COMPATIBILITY
    589    1.1       cgd 	for (ndrives = 0; *argv; ++argv) {
    590    1.1       cgd #ifdef	BACKWARD_COMPATIBILITY
    591  1.124       dsl 		if (isdigit((unsigned char)**argv))
    592    1.1       cgd 			break;
    593    1.1       cgd #endif
    594  1.140     blymn 		for (i = 0; i < ndrive; i++) {
    595    1.1       cgd 			if (strcmp(dr_name[i], *argv))
    596    1.1       cgd 				continue;
    597  1.140     blymn 			drv_select[i] = 1;
    598  1.136     blymn 			++ndrives;
    599  1.136     blymn 			break;
    600  1.136     blymn 		}
    601    1.1       cgd 	}
    602  1.249       mrg 
    603  1.249       mrg 	/*
    604  1.249       mrg 	 * Pick the most active drives.  Must read the stats once before
    605  1.249       mrg 	 * sorting so that there is current IO data, before selecting
    606  1.250       mrg 	 * just the first 'numdisks' (default 2) drives.
    607  1.249       mrg 	 */
    608  1.249       mrg 	drvreadstats();
    609  1.250       mrg 	for (i = 0; i < ndrive && ndrives < numdisks; i++) {
    610  1.249       mrg 		uint64_t high_bytes = 0, bytes;
    611  1.249       mrg 
    612  1.249       mrg 		k = ndrive;
    613  1.249       mrg 		for (j = 0; j < ndrive; j++) {
    614  1.249       mrg 			if (drv_select[j])
    615  1.249       mrg 				continue;
    616  1.249       mrg 			bytes = cur.rbytes[j] + cur.wbytes[j];
    617  1.249       mrg 			if (bytes > high_bytes) {
    618  1.249       mrg 				high_bytes = bytes;
    619  1.249       mrg 				k = j;
    620  1.249       mrg 			}
    621  1.249       mrg 		}
    622  1.249       mrg 		if (k != ndrive) {
    623  1.249       mrg 			drv_select[k] = 1;
    624  1.249       mrg 			++ndrives;
    625  1.249       mrg 		}
    626    1.1       cgd 	}
    627  1.140     blymn 
    628   1.75     enami 	return (argv);
    629    1.1       cgd }
    630    1.1       cgd 
    631    1.1       cgd long
    632   1.73    simonb getuptime(void)
    633    1.1       cgd {
    634  1.176      matt 	static struct timespec boottime;
    635  1.176      matt 	struct timespec now;
    636  1.149    kardel 	time_t uptime, nowsec;
    637    1.1       cgd 
    638  1.176      matt 	if (memf == NULL) {
    639  1.176      matt 		if (boottime.tv_sec == 0) {
    640  1.176      matt 			size_t buflen = sizeof(boottime);
    641  1.176      matt 			if (sysctl(boottime_mib, __arraycount(boottime_mib),
    642  1.176      matt 			    &boottime, &buflen, NULL, 0) == -1)
    643  1.176      matt 				warn("Can't get boottime");
    644  1.176      matt 		}
    645  1.176      matt 		clock_gettime(CLOCK_REALTIME, &now);
    646  1.147    kardel 	} else {
    647  1.231   thorpej 		if (boottime.tv_sec == 0) {
    648  1.231   thorpej 			struct bintime bt;
    649  1.231   thorpej 
    650  1.232       mrg 			kread(timenl, X_TIMEBASEBIN, &bt, sizeof(bt));
    651  1.231   thorpej 			bintime2timespec(&bt, &boottime);
    652  1.231   thorpej 		}
    653  1.232       mrg 		if (kreadc(timenl, X_TIME_SECOND, &nowsec, sizeof(nowsec))) {
    654  1.176      matt 			/*
    655  1.176      matt 			 * XXX this assignment dance can be removed once
    656  1.176      matt 			 * timeval tv_sec is SUS mandated time_t
    657  1.176      matt 			 */
    658  1.176      matt 			now.tv_sec = nowsec;
    659  1.176      matt 			now.tv_nsec = 0;
    660  1.176      matt 		} else {
    661  1.232       mrg 			kread(timenl, X_TIME, &now, sizeof(now));
    662  1.176      matt 		}
    663  1.147    kardel 	}
    664  1.145    kardel 	uptime = now.tv_sec - boottime.tv_sec;
    665   1.87     lukem 	if (uptime <= 0 || uptime > 60*60*24*365*10)
    666   1.87     lukem 		errx(1, "time makes no sense; namelist must be wrong.");
    667   1.75     enami 	return (uptime);
    668    1.1       cgd }
    669    1.1       cgd 
    670    1.1       cgd int	hz, hdrcnt;
    671    1.1       cgd 
    672    1.1       cgd void
    673  1.187      matt print_total_hdr(void)
    674  1.130        he {
    675  1.130        he 
    676  1.166     rmind 	(void)printf("procs         memory\n");
    677  1.166     rmind 	(void)printf("ru dw pw sl");
    678  1.130        he 	(void)printf("   total-v  active-v  active-r");
    679  1.130        he 	(void)printf(" vm-sh avm-sh rm-sh arm-sh free\n");
    680  1.130        he 	hdrcnt = winlines - 2;
    681  1.130        he }
    682  1.130        he 
    683  1.130        he void
    684  1.130        he dovmtotal(struct timespec *interval, int reps)
    685  1.130        he {
    686  1.130        he 	struct vmtotal total;
    687  1.130        he 	size_t size;
    688  1.130        he 
    689  1.130        he 	(void)signal(SIGCONT, needhdr);
    690  1.130        he 
    691  1.130        he 	for (hdrcnt = 1;;) {
    692  1.130        he 		if (!--hdrcnt)
    693  1.130        he 			print_total_hdr();
    694  1.130        he 		if (memf != NULL) {
    695  1.170  christos 			warnx("Unable to get vmtotals from crash dump.");
    696  1.153  christos 			(void)memset(&total, 0, sizeof(total));
    697  1.130        he 		} else {
    698  1.130        he 			size = sizeof(total);
    699  1.170  christos 			if (sysctl(vmmeter_mib, __arraycount(vmmeter_mib),
    700  1.170  christos 			    &total, &size, NULL, 0) == -1) {
    701  1.170  christos 				warn("Can't get vmtotals");
    702  1.153  christos 				(void)memset(&total, 0, sizeof(total));
    703  1.130        he 			}
    704  1.130        he 		}
    705  1.153  christos 		(void)printf("%2d ", total.t_rq);
    706  1.153  christos 		(void)printf("%2d ", total.t_dw);
    707  1.153  christos 		(void)printf("%2d ", total.t_pw);
    708  1.153  christos 		(void)printf("%2d ", total.t_sl);
    709  1.153  christos 
    710  1.153  christos 		(void)printf("%9d ", total.t_vm);
    711  1.153  christos 		(void)printf("%9d ", total.t_avm);
    712  1.153  christos 		(void)printf("%9d ", total.t_arm);
    713  1.153  christos 		(void)printf("%5d ", total.t_vmshr);
    714  1.153  christos 		(void)printf("%6d ", total.t_avmshr);
    715  1.153  christos 		(void)printf("%5d ", total.t_rmshr);
    716  1.153  christos 		(void)printf("%6d ", total.t_armshr);
    717  1.153  christos 		(void)printf("%5d",  total.t_free);
    718  1.130        he 
    719  1.153  christos 		(void)putchar('\n');
    720  1.130        he 
    721  1.130        he 		(void)fflush(stdout);
    722  1.130        he 		if (reps >= 0 && --reps <= 0)
    723  1.130        he 			break;
    724  1.130        he 
    725  1.153  christos 		(void)nanosleep(interval, NULL);
    726  1.130        he 	}
    727  1.130        he }
    728  1.130        he 
    729  1.130        he void
    730  1.103   mycroft dovmstat(struct timespec *interval, int reps)
    731    1.1       cgd {
    732    1.1       cgd 	struct vmtotal total;
    733    1.1       cgd 	time_t uptime, halfuptime;
    734   1.17       cgd 	size_t size;
    735   1.41       mrg 	int pagesize = getpagesize();
    736  1.151      yamt 	int ovflw;
    737    1.1       cgd 
    738    1.1       cgd 	uptime = getuptime();
    739    1.1       cgd 	halfuptime = uptime / 2;
    740    1.1       cgd 	(void)signal(SIGCONT, needhdr);
    741    1.1       cgd 
    742  1.197     joerg 	if (memf != NULL) {
    743  1.197     joerg 		if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
    744  1.197     joerg 			kread(namelist, X_STATHZ, &hz, sizeof(hz));
    745  1.197     joerg 		if (!hz)
    746  1.197     joerg 			kread(namelist, X_HZ, &hz, sizeof(hz));
    747  1.197     joerg 	} else {
    748  1.197     joerg 		struct clockinfo clockinfo;
    749  1.197     joerg 		size = sizeof(clockinfo);
    750  1.197     joerg 		if (sysctl(clockrate_mib, 2, &clockinfo, &size, NULL, 0) == -1)
    751  1.197     joerg 			err(1, "sysctl kern.clockrate failed");
    752  1.197     joerg 		hz = clockinfo.stathz;
    753  1.197     joerg 		if (!hz)
    754  1.197     joerg 			hz = clockinfo.hz;
    755  1.197     joerg 	}
    756    1.1       cgd 
    757    1.1       cgd 	for (hdrcnt = 1;;) {
    758    1.1       cgd 		if (!--hdrcnt)
    759    1.1       cgd 			printhdr();
    760   1.29   thorpej 		/* Read new disk statistics */
    761  1.139       dsl 		cpureadstats();
    762  1.140     blymn 		drvreadstats();
    763  1.139       dsl 		tkreadstats();
    764   1.58   thorpej 		if (memf != NULL) {
    765  1.196     joerg 			struct uvmexp uvmexp_kernel;
    766   1.58   thorpej 			/*
    767   1.58   thorpej 			 * XXX Can't do this if we're reading a crash
    768   1.58   thorpej 			 * XXX dump because they're lazily-calculated.
    769   1.58   thorpej 			 */
    770  1.170  christos 			warnx("Unable to get vmtotals from crash dump.");
    771  1.153  christos 			(void)memset(&total, 0, sizeof(total));
    772  1.196     joerg 			kread(namelist, X_UVMEXP, &uvmexp_kernel, sizeof(uvmexp_kernel));
    773  1.196     joerg #define COPY(field) uvmexp.field = uvmexp_kernel.field
    774  1.196     joerg 			COPY(pdreact);
    775  1.196     joerg 			COPY(pageins);
    776  1.196     joerg 			COPY(pgswapout);
    777  1.196     joerg 			COPY(pdfreed);
    778  1.196     joerg 			COPY(pdscans);
    779  1.196     joerg #undef COPY
    780   1.58   thorpej 		} else {
    781   1.58   thorpej 			size = sizeof(total);
    782  1.170  christos 			if (sysctl(vmmeter_mib, __arraycount(vmmeter_mib),
    783  1.170  christos 			    &total, &size, NULL, 0) == -1) {
    784  1.170  christos 				warn("Can't get vmtotals");
    785  1.153  christos 				(void)memset(&total, 0, sizeof(total));
    786   1.58   thorpej 			}
    787  1.196     joerg 			size = sizeof(uvmexp);
    788  1.196     joerg 			if (sysctl(uvmexp2_mib, __arraycount(uvmexp2_mib), &uvmexp,
    789  1.196     joerg 			    &size, NULL, 0) == -1)
    790  1.196     joerg 				warn("sysctl vm.uvmexp2 failed");
    791   1.13       cgd 		}
    792  1.171  christos 		cpucounters(&cpucounter);
    793  1.151      yamt 		ovflw = 0;
    794  1.151      yamt 		PRWORD(ovflw, " %*d", 2, 1, total.t_rq - 1);
    795  1.151      yamt 		PRWORD(ovflw, " %*d", 2, 1, total.t_dw + total.t_pw);
    796  1.153  christos #define	pgtok(a) (long)((a) * ((uint32_t)pagesize >> 10))
    797   1.38       mrg #define	rate(x)	(u_long)(((x) + halfuptime) / uptime)	/* round */
    798  1.166     rmind 		PRWORD(ovflw, " %*ld", 9, 1, pgtok(total.t_avm));
    799  1.151      yamt 		PRWORD(ovflw, " %*ld", 7, 1, pgtok(total.t_free));
    800  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    801  1.171  christos 		    rate(cpucounter.nfault - ocpucounter.nfault));
    802  1.151      yamt 		PRWORD(ovflw, " %*ld", 4, 1,
    803  1.151      yamt 		    rate(uvmexp.pdreact - ouvmexp.pdreact));
    804  1.151      yamt 		PRWORD(ovflw, " %*ld", 4, 1,
    805  1.151      yamt 		    rate(uvmexp.pageins - ouvmexp.pageins));
    806  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    807   1.44       mrg 		    rate(uvmexp.pgswapout - ouvmexp.pgswapout));
    808  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    809  1.151      yamt 		    rate(uvmexp.pdfreed - ouvmexp.pdfreed));
    810  1.151      yamt 		PRWORD(ovflw, " %*ld", 6, 2,
    811  1.151      yamt 		    rate(uvmexp.pdscans - ouvmexp.pdscans));
    812  1.151      yamt 		drvstats(&ovflw);
    813  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    814  1.171  christos 		    rate(cpucounter.nintr - ocpucounter.nintr));
    815  1.151      yamt 		PRWORD(ovflw, " %*ld", 5, 1,
    816  1.171  christos 		    rate(cpucounter.nsyscall - ocpucounter.nsyscall));
    817  1.151      yamt 		PRWORD(ovflw, " %*ld", 4, 1,
    818  1.171  christos 		    rate(cpucounter.nswtch - ocpucounter.nswtch));
    819  1.151      yamt 		cpustats(&ovflw);
    820  1.153  christos 		(void)putchar('\n');
    821   1.42       mrg 		(void)fflush(stdout);
    822   1.42       mrg 		if (reps >= 0 && --reps <= 0)
    823   1.42       mrg 			break;
    824  1.172     enami 		ouvmexp = uvmexp;
    825  1.171  christos 		ocpucounter = cpucounter;
    826  1.103   mycroft 		uptime = interval->tv_sec;
    827    1.1       cgd 		/*
    828    1.1       cgd 		 * We round upward to avoid losing low-frequency events
    829    1.1       cgd 		 * (i.e., >= 1 per interval but < 1 per second).
    830    1.1       cgd 		 */
    831   1.33   thorpej 		halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
    832  1.153  christos 		(void)nanosleep(interval, NULL);
    833    1.1       cgd 	}
    834    1.1       cgd }
    835    1.1       cgd 
    836   1.38       mrg void
    837   1.73    simonb printhdr(void)
    838    1.1       cgd {
    839  1.165     lukem 	size_t i;
    840    1.1       cgd 
    841  1.104       mrg 	(void)printf(" procs    memory      page%*s", 23, "");
    842   1.29   thorpej 	if (ndrives > 0)
    843   1.70  sommerfe 		(void)printf("%s %*sfaults      cpu\n",
    844   1.75     enami 		    ((ndrives > 1) ? "disks" : "disk"),
    845   1.75     enami 		    ((ndrives > 1) ? ndrives * 3 - 4 : 0), "");
    846    1.1       cgd 	else
    847   1.29   thorpej 		(void)printf("%*s  faults   cpu\n",
    848   1.75     enami 		    ndrives * 3, "");
    849   1.29   thorpej 
    850  1.166     rmind 	(void)printf(" r b      avm    fre  flt  re  pi   po   fr   sr ");
    851  1.140     blymn 	for (i = 0; i < ndrive; i++)
    852  1.140     blymn 		if (drv_select[i])
    853    1.1       cgd 			(void)printf("%c%c ", dr_name[i][0],
    854    1.1       cgd 			    dr_name[i][strlen(dr_name[i]) - 1]);
    855    1.1       cgd 	(void)printf("  in   sy  cs us sy id\n");
    856    1.1       cgd 	hdrcnt = winlines - 2;
    857    1.1       cgd }
    858    1.1       cgd 
    859    1.1       cgd /*
    860    1.1       cgd  * Force a header to be prepended to the next output.
    861    1.1       cgd  */
    862    1.1       cgd void
    863  1.153  christos /*ARGSUSED*/
    864   1.73    simonb needhdr(int dummy)
    865    1.1       cgd {
    866    1.1       cgd 
    867    1.1       cgd 	hdrcnt = 1;
    868    1.1       cgd }
    869    1.1       cgd 
    870   1.38       mrg long
    871  1.203  nakayama pct(u_long top, u_long bot)
    872    1.1       cgd {
    873   1.13       cgd 	long ans;
    874   1.13       cgd 
    875    1.1       cgd 	if (bot == 0)
    876   1.75     enami 		return (0);
    877  1.153  christos 	ans = (long)((quad_t)top * 100 / bot);
    878   1.13       cgd 	return (ans);
    879    1.1       cgd }
    880    1.1       cgd 
    881  1.203  nakayama #define	PCT(top, bot) (int)pct((u_long)(top), (u_long)(bot))
    882    1.1       cgd 
    883    1.1       cgd void
    884   1.73    simonb dosum(void)
    885    1.1       cgd {
    886  1.206    dennis 	struct nchstats nch_stats;
    887  1.194     joerg 	uint64_t nchtotal;
    888  1.162        he 	size_t ssize;
    889  1.162        he 	int active_kernel;
    890  1.171  christos 	struct cpu_counter cc;
    891  1.162        he 
    892  1.162        he 	/*
    893  1.162        he 	 * The "active" and "inactive" variables
    894  1.162        he 	 * are now estimated by the kernel and sadly
    895  1.162        he 	 * can not easily be dug out of a crash dump.
    896  1.162        he 	 */
    897  1.195     joerg 	ssize = sizeof(uvmexp);
    898  1.195     joerg 	memset(&uvmexp, 0, ssize);
    899  1.162        he 	active_kernel = (memf == NULL);
    900  1.162        he 	if (active_kernel) {
    901  1.162        he 		/* only on active kernel */
    902  1.195     joerg 		if (sysctl(uvmexp2_mib, __arraycount(uvmexp2_mib), &uvmexp,
    903  1.170  christos 		    &ssize, NULL, 0) == -1)
    904  1.170  christos 			warn("sysctl vm.uvmexp2 failed");
    905  1.195     joerg 	} else {
    906  1.195     joerg 		struct uvmexp uvmexp_kernel;
    907  1.221       mrg 		struct pool pool, *pp = &pool;
    908  1.222       mrg 		struct pool_allocator pa;
    909  1.221       mrg 		TAILQ_HEAD(,pool) pool_head;
    910  1.221       mrg 		void *addr;
    911  1.222       mrg 		uint64_t bytes;
    912  1.221       mrg 
    913  1.195     joerg 		kread(namelist, X_UVMEXP, &uvmexp_kernel, sizeof(uvmexp_kernel));
    914  1.195     joerg #define COPY(field) uvmexp.field = uvmexp_kernel.field
    915  1.195     joerg 		COPY(pagesize);
    916  1.195     joerg 		COPY(ncolors);
    917  1.195     joerg 		COPY(npages);
    918  1.195     joerg 		COPY(free);
    919  1.195     joerg 		COPY(paging);
    920  1.195     joerg 		COPY(wired);
    921  1.195     joerg 		COPY(reserve_pagedaemon);
    922  1.195     joerg 		COPY(reserve_kernel);
    923  1.195     joerg 		COPY(anonpages);
    924  1.195     joerg 		COPY(filepages);
    925  1.195     joerg 		COPY(execpages);
    926  1.195     joerg 		COPY(freemin);
    927  1.195     joerg 		COPY(freetarg);
    928  1.195     joerg 		COPY(wiredmax);
    929  1.195     joerg 		COPY(nswapdev);
    930  1.195     joerg 		COPY(swpages);
    931  1.195     joerg 		COPY(swpginuse);
    932  1.195     joerg 		COPY(nswget);
    933  1.195     joerg 		COPY(pageins);
    934  1.195     joerg 		COPY(pdpageouts);
    935  1.195     joerg 		COPY(pgswapin);
    936  1.195     joerg 		COPY(pgswapout);
    937  1.195     joerg 		COPY(forks);
    938  1.195     joerg 		COPY(forks_ppwait);
    939  1.195     joerg 		COPY(forks_sharevm);
    940  1.195     joerg 		COPY(colorhit);
    941  1.195     joerg 		COPY(colormiss);
    942  1.195     joerg 		COPY(cpuhit);
    943  1.195     joerg 		COPY(cpumiss);
    944  1.195     joerg 		COPY(fltnoram);
    945  1.195     joerg 		COPY(fltnoanon);
    946  1.195     joerg 		COPY(fltpgwait);
    947  1.195     joerg 		COPY(fltpgrele);
    948  1.195     joerg 		COPY(fltrelck);
    949  1.195     joerg 		COPY(fltrelckok);
    950  1.195     joerg 		COPY(fltanget);
    951  1.195     joerg 		COPY(fltanretry);
    952  1.195     joerg 		COPY(fltamcopy);
    953  1.195     joerg 		COPY(fltamcopy);
    954  1.195     joerg 		COPY(fltnomap);
    955  1.195     joerg 		COPY(fltlget);
    956  1.195     joerg 		COPY(fltget);
    957  1.195     joerg 		COPY(flt_anon);
    958  1.195     joerg 		COPY(flt_acow);
    959  1.195     joerg 		COPY(flt_obj);
    960  1.195     joerg 		COPY(flt_prcopy);
    961  1.195     joerg 		COPY(flt_przero);
    962  1.195     joerg 		COPY(pdwoke);
    963  1.195     joerg 		COPY(pdrevs);
    964  1.195     joerg 		COPY(pdfreed);
    965  1.195     joerg 		COPY(pdscans);
    966  1.195     joerg 		COPY(pdanscan);
    967  1.195     joerg 		COPY(pdobscan);
    968  1.195     joerg 		COPY(pdreact);
    969  1.195     joerg 		COPY(pdbusy);
    970  1.195     joerg 		COPY(pdpending);
    971  1.195     joerg 		COPY(pddeact);
    972  1.221       mrg 		COPY(bootpages);
    973  1.195     joerg #undef COPY
    974  1.221       mrg 		kread(namelist, X_POOLHEAD, &pool_head, sizeof(pool_head));
    975  1.221       mrg 		addr = TAILQ_FIRST(&pool_head);
    976  1.222       mrg 		uvmexp.poolpages = 0;
    977  1.221       mrg 		for (; addr != NULL; addr = TAILQ_NEXT(pp, pr_poollist)) {
    978  1.221       mrg 			deref_kptr(addr, pp, sizeof(*pp), "pool chain trashed");
    979  1.224       mrg 			deref_kptr(pp->pr_alloc, &pa, sizeof(pa),
    980  1.224       mrg 			    "pool allocator trashed");
    981  1.222       mrg 			bytes = pp->pr_npages * pa.pa_pagesz;
    982  1.222       mrg 			if ((pp->pr_roflags & PR_RECURSIVE) != 0)
    983  1.222       mrg 				bytes -= (pp->pr_nout * pp->pr_size);
    984  1.222       mrg 			uvmexp.poolpages += bytes / uvmexp.pagesize;
    985  1.221       mrg 		}
    986  1.162        he 	}
    987    1.1       cgd 
    988   1.41       mrg 
    989  1.195     joerg 	(void)printf("%9" PRIu64 " bytes per page\n", uvmexp.pagesize);
    990   1.44       mrg 
    991  1.195     joerg 	(void)printf("%9" PRIu64 " page color%s\n",
    992   1.81   thorpej 	    uvmexp.ncolors, uvmexp.ncolors == 1 ? "" : "s");
    993   1.81   thorpej 
    994  1.195     joerg 	(void)printf("%9" PRIu64 " pages managed\n", uvmexp.npages);
    995  1.195     joerg 	(void)printf("%9" PRIu64 " pages free\n", uvmexp.free);
    996  1.162        he 	if (active_kernel) {
    997  1.195     joerg 		(void)printf("%9" PRIu64 " pages active\n", uvmexp.active);
    998  1.195     joerg 		(void)printf("%9" PRIu64 " pages inactive\n", uvmexp.inactive);
    999  1.162        he 	}
   1000  1.195     joerg 	(void)printf("%9" PRIu64 " pages paging\n", uvmexp.paging);
   1001  1.195     joerg 	(void)printf("%9" PRIu64 " pages wired\n", uvmexp.wired);
   1002  1.195     joerg 	(void)printf("%9" PRIu64 " reserve pagedaemon pages\n",
   1003   1.44       mrg 	    uvmexp.reserve_pagedaemon);
   1004  1.195     joerg 	(void)printf("%9" PRIu64 " reserve kernel pages\n", uvmexp.reserve_kernel);
   1005  1.221       mrg 	(void)printf("%9" PRIu64 " boot kernel pages\n", uvmexp.bootpages);
   1006  1.221       mrg 	(void)printf("%9" PRIu64 " kernel pool pages\n", uvmexp.poolpages);
   1007  1.195     joerg 	(void)printf("%9" PRIu64 " anonymous pages\n", uvmexp.anonpages);
   1008  1.195     joerg 	(void)printf("%9" PRIu64 " cached file pages\n", uvmexp.filepages);
   1009  1.195     joerg 	(void)printf("%9" PRIu64 " cached executable pages\n", uvmexp.execpages);
   1010  1.195     joerg 
   1011  1.195     joerg 	(void)printf("%9" PRIu64 " minimum free pages\n", uvmexp.freemin);
   1012  1.195     joerg 	(void)printf("%9" PRIu64 " target free pages\n", uvmexp.freetarg);
   1013  1.195     joerg 	(void)printf("%9" PRIu64 " maximum wired pages\n", uvmexp.wiredmax);
   1014  1.195     joerg 
   1015  1.195     joerg 	(void)printf("%9" PRIu64 " swap devices\n", uvmexp.nswapdev);
   1016  1.195     joerg 	(void)printf("%9" PRIu64 " swap pages\n", uvmexp.swpages);
   1017  1.195     joerg 	(void)printf("%9" PRIu64 " swap pages in use\n", uvmexp.swpginuse);
   1018  1.195     joerg 	(void)printf("%9" PRIu64 " swap allocations\n", uvmexp.nswget);
   1019   1.44       mrg 
   1020  1.171  christos 	cpucounters(&cc);
   1021  1.190     rmind 
   1022  1.171  christos 	(void)printf("%9" PRIu64 " total faults taken\n", cc.nfault);
   1023  1.171  christos 	(void)printf("%9" PRIu64 " traps\n", cc.ntrap);
   1024  1.171  christos 	(void)printf("%9" PRIu64 " device interrupts\n", cc.nintr);
   1025  1.171  christos 	(void)printf("%9" PRIu64 " CPU context switches\n", cc.nswtch);
   1026  1.171  christos 	(void)printf("%9" PRIu64 " software interrupts\n", cc.nsoft);
   1027  1.171  christos 	(void)printf("%9" PRIu64 " system calls\n", cc.nsyscall);
   1028  1.195     joerg 	(void)printf("%9" PRIu64 " pagein requests\n", uvmexp.pageins);
   1029  1.195     joerg 	(void)printf("%9" PRIu64 " pageout requests\n", uvmexp.pdpageouts);
   1030  1.195     joerg 	(void)printf("%9" PRIu64 " pages swapped in\n", uvmexp.pgswapin);
   1031  1.195     joerg 	(void)printf("%9" PRIu64 " pages swapped out\n", uvmexp.pgswapout);
   1032  1.195     joerg 	(void)printf("%9" PRIu64 " forks total\n", uvmexp.forks);
   1033  1.195     joerg 	(void)printf("%9" PRIu64 " forks blocked parent\n", uvmexp.forks_ppwait);
   1034  1.195     joerg 	(void)printf("%9" PRIu64 " forks shared address space with parent\n",
   1035   1.43       mrg 	    uvmexp.forks_sharevm);
   1036  1.195     joerg 	(void)printf("%9" PRIu64 " pagealloc desired color avail\n",
   1037   1.79   thorpej 	    uvmexp.colorhit);
   1038  1.195     joerg 	(void)printf("%9" PRIu64 " pagealloc desired color not avail\n",
   1039   1.79   thorpej 	    uvmexp.colormiss);
   1040  1.195     joerg 	(void)printf("%9" PRIu64 " pagealloc local cpu avail\n",
   1041  1.159        ad 	    uvmexp.cpuhit);
   1042  1.195     joerg 	(void)printf("%9" PRIu64 " pagealloc local cpu not avail\n",
   1043  1.159        ad 	    uvmexp.cpumiss);
   1044   1.44       mrg 
   1045  1.195     joerg 	(void)printf("%9" PRIu64 " faults with no memory\n", uvmexp.fltnoram);
   1046  1.195     joerg 	(void)printf("%9" PRIu64 " faults with no anons\n", uvmexp.fltnoanon);
   1047  1.195     joerg 	(void)printf("%9" PRIu64 " faults had to wait on pages\n", uvmexp.fltpgwait);
   1048  1.195     joerg 	(void)printf("%9" PRIu64 " faults found released page\n", uvmexp.fltpgrele);
   1049  1.195     joerg 	(void)printf("%9" PRIu64 " faults relock (%" PRIu64 " ok)\n", uvmexp.fltrelck,
   1050   1.43       mrg 	    uvmexp.fltrelckok);
   1051  1.195     joerg 	(void)printf("%9" PRIu64 " anon page faults\n", uvmexp.fltanget);
   1052  1.195     joerg 	(void)printf("%9" PRIu64 " anon retry faults\n", uvmexp.fltanretry);
   1053  1.195     joerg 	(void)printf("%9" PRIu64 " amap copy faults\n", uvmexp.fltamcopy);
   1054  1.195     joerg 	(void)printf("%9" PRIu64 " neighbour anon page faults\n", uvmexp.fltnamap);
   1055  1.195     joerg 	(void)printf("%9" PRIu64 " neighbour object page faults\n", uvmexp.fltnomap);
   1056  1.195     joerg 	(void)printf("%9" PRIu64 " locked pager get faults\n", uvmexp.fltlget);
   1057  1.195     joerg 	(void)printf("%9" PRIu64 " unlocked pager get faults\n", uvmexp.fltget);
   1058  1.195     joerg 	(void)printf("%9" PRIu64 " anon faults\n", uvmexp.flt_anon);
   1059  1.195     joerg 	(void)printf("%9" PRIu64 " anon copy on write faults\n", uvmexp.flt_acow);
   1060  1.195     joerg 	(void)printf("%9" PRIu64 " object faults\n", uvmexp.flt_obj);
   1061  1.195     joerg 	(void)printf("%9" PRIu64 " promote copy faults\n", uvmexp.flt_prcopy);
   1062  1.195     joerg 	(void)printf("%9" PRIu64 " promote zero fill faults\n", uvmexp.flt_przero);
   1063  1.238        ad 	(void)printf("%9" PRIu64 " faults upgraded lock\n",
   1064  1.238        ad 	    uvmexp.fltup);
   1065  1.238        ad 	(void)printf("%9" PRIu64 " faults couldn't upgrade lock\n",
   1066  1.238        ad 	    uvmexp.fltnoup);
   1067  1.195     joerg 
   1068  1.195     joerg 	(void)printf("%9" PRIu64 " times daemon wokeup\n",uvmexp.pdwoke);
   1069  1.195     joerg 	(void)printf("%9" PRIu64 " revolutions of the clock hand\n", uvmexp.pdrevs);
   1070  1.195     joerg 	(void)printf("%9" PRIu64 " pages freed by daemon\n", uvmexp.pdfreed);
   1071  1.195     joerg 	(void)printf("%9" PRIu64 " pages scanned by daemon\n", uvmexp.pdscans);
   1072  1.195     joerg 	(void)printf("%9" PRIu64 " anonymous pages scanned by daemon\n",
   1073   1.75     enami 	    uvmexp.pdanscan);
   1074  1.195     joerg 	(void)printf("%9" PRIu64 " object pages scanned by daemon\n", uvmexp.pdobscan);
   1075  1.195     joerg 	(void)printf("%9" PRIu64 " pages reactivated\n", uvmexp.pdreact);
   1076  1.195     joerg 	(void)printf("%9" PRIu64 " pages found busy by daemon\n", uvmexp.pdbusy);
   1077  1.195     joerg 	(void)printf("%9" PRIu64 " total pending pageouts\n", uvmexp.pdpending);
   1078  1.195     joerg 	(void)printf("%9" PRIu64 " pages deactivated\n", uvmexp.pddeact);
   1079  1.240        ad 	(void)printf("%9" PRIu64 " per-cpu stats synced\n", uvmexp.countsyncall);
   1080  1.235        ad 	(void)printf("%9" PRIu64 " anon pages possibly dirty\n", uvmexp.anonunknown);
   1081  1.235        ad 	(void)printf("%9" PRIu64 " anon pages dirty\n", uvmexp.anondirty);
   1082  1.235        ad 	(void)printf("%9" PRIu64 " anon pages clean\n", uvmexp.anonclean);
   1083  1.235        ad 	(void)printf("%9" PRIu64 " file pages possibly dirty\n", uvmexp.fileunknown);
   1084  1.235        ad 	(void)printf("%9" PRIu64 " file pages dirty\n", uvmexp.filedirty);
   1085  1.235        ad 	(void)printf("%9" PRIu64 " file pages clean\n", uvmexp.fileclean);
   1086  1.123     enami 
   1087  1.194     joerg 	if (active_kernel) {
   1088  1.194     joerg 		ssize = sizeof(nch_stats);
   1089  1.194     joerg 		if (sysctlbyname("vfs.namecache_stats", &nch_stats, &ssize,
   1090  1.194     joerg 		    NULL, 0)) {
   1091  1.194     joerg 			warn("vfs.namecache_stats failed");
   1092  1.194     joerg 			memset(&nch_stats, 0, sizeof(nch_stats));
   1093  1.194     joerg 		}
   1094  1.194     joerg 	} else {
   1095  1.206    dennis 		kread(namelist, X_NCHSTATS, &nch_stats, sizeof(nch_stats));
   1096  1.194     joerg 	}
   1097  1.194     joerg 
   1098  1.194     joerg 	nchtotal = nch_stats.ncs_goodhits + nch_stats.ncs_neghits +
   1099  1.194     joerg 	    nch_stats.ncs_badhits + nch_stats.ncs_falsehits +
   1100  1.194     joerg 	    nch_stats.ncs_miss + nch_stats.ncs_long;
   1101  1.194     joerg 	(void)printf("%9" PRIu64 " total name lookups\n", nchtotal);
   1102  1.194     joerg 	(void)printf("%9" PRIu64 " good hits\n", nch_stats.ncs_goodhits);
   1103  1.194     joerg 	(void)printf("%9" PRIu64 " negative hits\n", nch_stats.ncs_neghits);
   1104  1.194     joerg 	(void)printf("%9" PRIu64 " bad hits\n", nch_stats.ncs_badhits);
   1105  1.194     joerg 	(void)printf("%9" PRIu64 " false hits\n", nch_stats.ncs_falsehits);
   1106  1.194     joerg 	(void)printf("%9" PRIu64 " miss\n", nch_stats.ncs_miss);
   1107  1.194     joerg 	(void)printf("%9" PRIu64 " too long\n", nch_stats.ncs_long);
   1108  1.194     joerg 	(void)printf("%9" PRIu64 " pass2 hits\n", nch_stats.ncs_pass2);
   1109  1.194     joerg 	(void)printf("%9" PRIu64 " 2passes\n", nch_stats.ncs_2passes);
   1110  1.233        ad 	(void)printf("%9" PRIu64 " reverse hits\n", nch_stats.ncs_revhits);
   1111  1.234        ad 	(void)printf("%9" PRIu64 " reverse miss\n", nch_stats.ncs_revmiss);
   1112  1.237        ad 	(void)printf("%9" PRIu64 " access denied\n", nch_stats.ncs_denied);
   1113    1.1       cgd 	(void)printf(
   1114    1.1       cgd 	    "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
   1115  1.194     joerg 	    "", PCT(nch_stats.ncs_goodhits, nchtotal),
   1116  1.194     joerg 	    PCT(nch_stats.ncs_neghits, nchtotal),
   1117  1.194     joerg 	    PCT(nch_stats.ncs_pass2, nchtotal));
   1118    1.1       cgd 	(void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
   1119  1.194     joerg 	    PCT(nch_stats.ncs_badhits, nchtotal),
   1120  1.194     joerg 	    PCT(nch_stats.ncs_falsehits, nchtotal),
   1121  1.194     joerg 	    PCT(nch_stats.ncs_long, nchtotal));
   1122    1.1       cgd }
   1123    1.1       cgd 
   1124    1.1       cgd void
   1125   1.73    simonb doforkst(void)
   1126    1.1       cgd {
   1127  1.196     joerg 	if (memf != NULL) {
   1128  1.196     joerg 		struct uvmexp uvmexp_kernel;
   1129  1.196     joerg 		kread(namelist, X_UVMEXP, &uvmexp_kernel, sizeof(uvmexp_kernel));
   1130  1.196     joerg #define COPY(field) uvmexp.field = uvmexp_kernel.field
   1131  1.196     joerg 		COPY(forks);
   1132  1.196     joerg 		COPY(forks_ppwait);
   1133  1.196     joerg 		COPY(forks_sharevm);
   1134  1.196     joerg #undef COPY
   1135  1.196     joerg 	} else {
   1136  1.196     joerg 		size_t size = sizeof(uvmexp);
   1137  1.196     joerg 		if (sysctl(uvmexp2_mib, __arraycount(uvmexp2_mib), &uvmexp,
   1138  1.196     joerg 		    &size, NULL, 0) == -1)
   1139  1.196     joerg 			warn("sysctl vm.uvmexp2 failed");
   1140  1.196     joerg 	}
   1141   1.58   thorpej 
   1142  1.196     joerg 	(void)printf("%" PRIu64 " forks total\n", uvmexp.forks);
   1143  1.196     joerg 	(void)printf("%" PRIu64 " forks blocked parent\n", uvmexp.forks_ppwait);
   1144  1.196     joerg 	(void)printf("%" PRIu64 " forks shared address space with parent\n",
   1145   1.41       mrg 	    uvmexp.forks_sharevm);
   1146    1.1       cgd }
   1147    1.1       cgd 
   1148    1.1       cgd void
   1149  1.151      yamt drvstats(int *ovflwp)
   1150    1.1       cgd {
   1151  1.165     lukem 	size_t dn;
   1152  1.217   mlelstv 	double dtime;
   1153  1.151      yamt 	int ovflw = *ovflwp;
   1154    1.1       cgd 
   1155   1.29   thorpej 	/* Calculate disk stat deltas. */
   1156  1.139       dsl 	cpuswap();
   1157  1.140     blymn 	drvswap();
   1158  1.139       dsl 	tkswap();
   1159  1.101  sommerfe 
   1160  1.140     blymn 	for (dn = 0; dn < ndrive; ++dn) {
   1161  1.217   mlelstv 		/* elapsed time for disk stats */
   1162  1.218   mlelstv 		dtime = cur.cp_etime;
   1163  1.218   mlelstv 		if (cur.timestamp[dn].tv_sec || cur.timestamp[dn].tv_usec) {
   1164  1.218   mlelstv 			dtime = (double)cur.timestamp[dn].tv_sec +
   1165  1.218   mlelstv 				((double)cur.timestamp[dn].tv_usec / (double)1000000);
   1166  1.218   mlelstv 		}
   1167  1.217   mlelstv 
   1168  1.140     blymn 		if (!drv_select[dn])
   1169  1.151      yamt 	 		continue;
   1170  1.151      yamt 		PRWORD(ovflw, " %*.0f", 3, 1,
   1171  1.217   mlelstv 		    (cur.rxfer[dn] + cur.wxfer[dn]) / dtime);
   1172  1.136     blymn 	}
   1173  1.151      yamt 	*ovflwp = ovflw;
   1174  1.136     blymn }
   1175  1.136     blymn 
   1176  1.136     blymn void
   1177  1.171  christos cpucounters(struct cpu_counter *cc)
   1178  1.171  christos {
   1179  1.198     joerg 	static struct cpu_info **cpu_infos;
   1180  1.198     joerg 	static int initialised;
   1181  1.198     joerg 	struct cpu_info **slot;
   1182  1.198     joerg 
   1183  1.198     joerg 	if (memf == NULL) {
   1184  1.198     joerg 		cc->nintr = uvmexp.intrs;
   1185  1.198     joerg 		cc->nsyscall = uvmexp.syscalls;
   1186  1.198     joerg 		cc->nswtch = uvmexp.swtch;
   1187  1.198     joerg 		cc->nfault = uvmexp.faults;
   1188  1.198     joerg 		cc->ntrap = uvmexp.traps;
   1189  1.198     joerg 		cc->nsoft = uvmexp.softs;
   1190  1.198     joerg 		return;
   1191  1.198     joerg 	}
   1192  1.198     joerg 
   1193  1.198     joerg 	if (!initialised) {
   1194  1.198     joerg 		kread(namelist, X_CPU_INFOS, &cpu_infos, sizeof(cpu_infos));
   1195  1.198     joerg 		initialised = 1;
   1196  1.198     joerg 	}
   1197  1.198     joerg 
   1198  1.198     joerg 	slot = cpu_infos;
   1199  1.190     rmind 
   1200  1.190     rmind 	memset(cc, 0, sizeof(*cc));
   1201  1.190     rmind 
   1202  1.190     rmind 	for (;;) {
   1203  1.190     rmind 		struct cpu_info tci, *ci = NULL;
   1204  1.190     rmind 
   1205  1.190     rmind 		deref_kptr(slot++, &ci, sizeof(ci), "CPU array trashed");
   1206  1.190     rmind 		if (!ci) {
   1207  1.190     rmind 			break;
   1208  1.190     rmind 		}
   1209  1.190     rmind 
   1210  1.171  christos 		if ((size_t)kvm_read(kd, (u_long)ci, &tci, sizeof(tci))
   1211  1.171  christos 		    != sizeof(tci)) {
   1212  1.190     rmind 			warnx("Can't read cpu info from %p (%s)",
   1213  1.190     rmind 			    ci, kvm_geterr(kd));
   1214  1.190     rmind 			memset(cc, 0, sizeof(*cc));
   1215  1.190     rmind 			return;
   1216  1.171  christos 		}
   1217  1.171  christos 		cc->nintr += tci.ci_data.cpu_nintr;
   1218  1.171  christos 		cc->nsyscall += tci.ci_data.cpu_nsyscall;
   1219  1.171  christos 		cc->nswtch = tci.ci_data.cpu_nswtch;
   1220  1.171  christos 		cc->nfault = tci.ci_data.cpu_nfault;
   1221  1.171  christos 		cc->ntrap = tci.ci_data.cpu_ntrap;
   1222  1.171  christos 		cc->nsoft = tci.ci_data.cpu_nsoft;
   1223  1.171  christos 	}
   1224  1.171  christos }
   1225  1.171  christos 
   1226  1.171  christos void
   1227  1.151      yamt cpustats(int *ovflwp)
   1228    1.1       cgd {
   1229   1.38       mrg 	int state;
   1230  1.129       dsl 	double pcnt, total;
   1231  1.120       dbj 	double stat_us, stat_sy, stat_id;
   1232  1.151      yamt 	int ovflw = *ovflwp;
   1233    1.1       cgd 
   1234    1.1       cgd 	total = 0;
   1235    1.1       cgd 	for (state = 0; state < CPUSTATES; ++state)
   1236   1.29   thorpej 		total += cur.cp_time[state];
   1237    1.1       cgd 	if (total)
   1238  1.129       dsl 		pcnt = 100 / total;
   1239    1.1       cgd 	else
   1240  1.129       dsl 		pcnt = 0;
   1241  1.129       dsl 	stat_us = (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pcnt;
   1242  1.129       dsl 	stat_sy = (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pcnt;
   1243  1.129       dsl 	stat_id = cur.cp_time[CP_IDLE] * pcnt;
   1244  1.151      yamt 	PRWORD(ovflw, " %*.0f", ((stat_sy >= 100) ? 2 : 3), 1, stat_us);
   1245  1.151      yamt 	PRWORD(ovflw, " %*.0f", ((stat_us >= 100 || stat_id >= 100) ? 2 : 3), 1,
   1246  1.151      yamt 	    stat_sy);
   1247  1.151      yamt 	PRWORD(ovflw, " %*.0f", 3, 1, stat_id);
   1248  1.151      yamt 	*ovflwp = ovflw;
   1249    1.1       cgd }
   1250    1.1       cgd 
   1251    1.1       cgd void
   1252   1.66       cgd dointr(int verbose)
   1253    1.1       cgd {
   1254  1.138    nonaka 	unsigned long *intrcnt, *ointrcnt;
   1255   1.85     enami 	unsigned long long inttotal, uptime;
   1256   1.38       mrg 	int nintr, inamlen;
   1257  1.138    nonaka 	char *intrname, *ointrname;
   1258    1.1       cgd 
   1259  1.244    simonb 	if (memf == NULL) {
   1260  1.244    simonb 		doevcnt(verbose, EVCNT_TYPE_INTR);
   1261  1.244    simonb 		return;
   1262  1.244    simonb 	}
   1263  1.244    simonb 
   1264  1.133       chs 	inttotal = 0;
   1265    1.1       cgd 	uptime = getuptime();
   1266  1.133       chs 	nintr = intrnl[X_EINTRCNT].n_value - intrnl[X_INTRCNT].n_value;
   1267  1.133       chs 	inamlen = intrnl[X_EINTRNAMES].n_value - intrnl[X_INTRNAMES].n_value;
   1268  1.133       chs 	if (nintr != 0 && inamlen != 0) {
   1269  1.216       ryo 		(void)printf("%-34s %16s %8s\n", "interrupt", "total", "rate");
   1270  1.216       ryo 
   1271  1.138    nonaka 		ointrcnt = intrcnt = malloc((size_t)nintr);
   1272  1.138    nonaka 		ointrname = intrname = malloc((size_t)inamlen);
   1273  1.133       chs 		if (intrcnt == NULL || intrname == NULL)
   1274  1.133       chs 			errx(1, "%s", "");
   1275  1.133       chs 		kread(intrnl, X_INTRCNT, intrcnt, (size_t)nintr);
   1276  1.133       chs 		kread(intrnl, X_INTRNAMES, intrname, (size_t)inamlen);
   1277  1.133       chs 		nintr /= sizeof(long);
   1278  1.133       chs 		while (--nintr >= 0) {
   1279  1.133       chs 			if (*intrcnt || verbose)
   1280  1.133       chs 				(void)printf("%-34s %16llu %8llu\n", intrname,
   1281  1.133       chs 					     (unsigned long long)*intrcnt,
   1282  1.133       chs 					     (unsigned long long)
   1283  1.133       chs 					     (*intrcnt / uptime));
   1284  1.133       chs 			intrname += strlen(intrname) + 1;
   1285  1.133       chs 			inttotal += *intrcnt++;
   1286  1.133       chs 		}
   1287  1.138    nonaka 		free(ointrcnt);
   1288  1.138    nonaka 		free(ointrname);
   1289    1.1       cgd 	}
   1290  1.133       chs 
   1291  1.176      matt 	doevcnt(verbose, EVCNT_TYPE_INTR);
   1292   1.66       cgd }
   1293   1.66       cgd 
   1294   1.66       cgd void
   1295  1.176      matt doevcnt(int verbose, int type)
   1296   1.66       cgd {
   1297  1.176      matt 	static const char * const evtypes [] = { "misc", "intr", "trap" };
   1298  1.176      matt 	uint64_t counttotal, uptime;
   1299   1.66       cgd 	struct evcntlist allevents;
   1300   1.66       cgd 	struct evcnt evcnt, *evptr;
   1301  1.216       ryo 	size_t evlen_max, total_max, rate_max;
   1302   1.66       cgd 	char evgroup[EVCNT_STRING_MAX], evname[EVCNT_STRING_MAX];
   1303   1.66       cgd 
   1304  1.176      matt 	counttotal = 0;
   1305   1.66       cgd 	uptime = getuptime();
   1306  1.176      matt 
   1307  1.261     skrll 	if (memf == NULL) {
   1308  1.176      matt 		const int mib[4] = { CTL_KERN, KERN_EVCNT, type,
   1309  1.176      matt 		    verbose ? KERN_EVCNT_COUNT_ANY : KERN_EVCNT_COUNT_NONZERO };
   1310  1.216       ryo 		size_t buflen0, buflen = 0;
   1311  1.216       ryo 		void *buf0, *buf = NULL;
   1312  1.176      matt 		const struct evcnt_sysctl *evs, *last_evs;
   1313  1.176      matt 		for (;;) {
   1314  1.176      matt 			size_t newlen;
   1315  1.176      matt 			int error;
   1316  1.176      matt 			if (buflen)
   1317  1.176      matt 				buf = malloc(buflen);
   1318  1.176      matt 			error = sysctl(mib, __arraycount(mib),
   1319  1.176      matt 			    buf, &newlen, NULL, 0);
   1320  1.176      matt 			if (error) {
   1321  1.193     joerg 				err(1, "kern.evcnt");
   1322  1.176      matt 				if (buf)
   1323  1.176      matt 					free(buf);
   1324  1.176      matt 				return;
   1325  1.176      matt 			}
   1326  1.176      matt 			if (newlen <= buflen) {
   1327  1.176      matt 				buflen = newlen;
   1328  1.176      matt 				break;
   1329  1.176      matt 			}
   1330  1.176      matt 			if (buf)
   1331  1.176      matt 				free(buf);
   1332  1.176      matt 			buflen = newlen;
   1333  1.176      matt 		}
   1334  1.216       ryo 		buflen0 = buflen;
   1335  1.216       ryo 		evs = buf0 = buf;
   1336  1.216       ryo 		last_evs = (void *)((char *)buf + buflen);
   1337  1.216       ryo 		buflen /= sizeof(uint64_t);
   1338  1.216       ryo 		/* calc columns */
   1339  1.216       ryo 		evlen_max = 0;
   1340  1.216       ryo 		total_max = sizeof("total") - 1;
   1341  1.216       ryo 		rate_max = sizeof("rate") - 1;
   1342  1.216       ryo 		while (evs < last_evs
   1343  1.216       ryo 		    && buflen >= sizeof(*evs)/sizeof(uint64_t)
   1344  1.216       ryo 		    && buflen >= evs->ev_len) {
   1345  1.216       ryo 			char cbuf[64];
   1346  1.216       ryo 			size_t len;
   1347  1.216       ryo 			len = strlen(evs->ev_strings + evs->ev_grouplen + 1);
   1348  1.216       ryo 			len += evs->ev_grouplen + 1;
   1349  1.216       ryo 			if (evlen_max < len)
   1350  1.216       ryo 				evlen_max= len;
   1351  1.216       ryo 			len = snprintf(cbuf, sizeof(cbuf), "%"PRIu64,
   1352  1.216       ryo 			    evs->ev_count);
   1353  1.216       ryo 			if (total_max < len)
   1354  1.216       ryo 				total_max = len;
   1355  1.216       ryo 			len = snprintf(cbuf, sizeof(cbuf), "%"PRIu64,
   1356  1.216       ryo 			    evs->ev_count / uptime);
   1357  1.216       ryo 			if (rate_max < len)
   1358  1.216       ryo 				rate_max = len;
   1359  1.216       ryo 			buflen -= evs->ev_len;
   1360  1.259     skrll 			counttotal += evs->ev_count;
   1361  1.216       ryo 			evs = (const void *)
   1362  1.216       ryo 			    ((const uint64_t *)evs + evs->ev_len);
   1363  1.216       ryo 		}
   1364  1.259     skrll 		if (type != EVCNT_TYPE_ANY) {
   1365  1.259     skrll 			char cbuf[64];
   1366  1.259     skrll 			size_t len;
   1367  1.259     skrll 
   1368  1.259     skrll 			len = snprintf(cbuf, sizeof(cbuf), "%"PRIu64,
   1369  1.259     skrll 			    counttotal);
   1370  1.259     skrll 			if (total_max < len)
   1371  1.259     skrll 				total_max = len;
   1372  1.259     skrll 
   1373  1.259     skrll 			len = snprintf(cbuf, sizeof(cbuf), "%"PRIu64,
   1374  1.259     skrll 			    counttotal / uptime);
   1375  1.259     skrll 			if (rate_max < len)
   1376  1.259     skrll 				rate_max = len;
   1377  1.259     skrll 		}
   1378  1.262     skrll 		const char *evdesc = type == EVCNT_TYPE_ANY ?
   1379  1.262     skrll 		    "event" : "interrupt";
   1380  1.262     skrll 		const char *typedesc = type == EVCNT_TYPE_ANY ?
   1381  1.262     skrll 		    " type" : "";
   1382  1.216       ryo 
   1383  1.262     skrll 		(void)printf("%-*s  %*s %*s%s\n",
   1384  1.262     skrll 		    (int)evlen_max, evdesc,
   1385  1.216       ryo 		    (int)total_max, "total",
   1386  1.216       ryo 		    (int)rate_max, "rate",
   1387  1.262     skrll 		    typedesc);
   1388  1.216       ryo 
   1389  1.216       ryo 		buflen = buflen0;
   1390  1.216       ryo 		evs = buf0;
   1391  1.176      matt 		last_evs = (void *)((char *)buf + buflen);
   1392  1.176      matt 		buflen /= sizeof(uint64_t);
   1393  1.176      matt 		while (evs < last_evs
   1394  1.176      matt 		    && buflen >= sizeof(*evs)/sizeof(uint64_t)
   1395  1.176      matt 		    && buflen >= evs->ev_len) {
   1396  1.180  nakayama 			(void)printf(type == EVCNT_TYPE_ANY ?
   1397  1.216       ryo 			    "%s %s%*s  %*"PRIu64" %*"PRIu64" %s\n" :
   1398  1.216       ryo 			    "%s %s%*s  %*"PRIu64" %*"PRIu64"\n",
   1399  1.176      matt 			    evs->ev_strings,
   1400  1.176      matt 			    evs->ev_strings + evs->ev_grouplen + 1,
   1401  1.216       ryo 			    (int)evlen_max - (evs->ev_grouplen + 1
   1402  1.216       ryo 			    + evs->ev_namelen), "",
   1403  1.216       ryo 			    (int)total_max, evs->ev_count,
   1404  1.216       ryo 			    (int)rate_max, evs->ev_count / uptime,
   1405  1.176      matt 			    (evs->ev_type < __arraycount(evtypes) ?
   1406  1.216       ryo 			    evtypes[evs->ev_type] : "?"));
   1407  1.176      matt 			buflen -= evs->ev_len;
   1408  1.216       ryo 			evs = (const void *)
   1409  1.216       ryo 			    ((const uint64_t *)evs + evs->ev_len);
   1410  1.176      matt 		}
   1411  1.176      matt 		free(buf);
   1412  1.176      matt 		if (type != EVCNT_TYPE_ANY)
   1413  1.216       ryo 			(void)printf("%-*s  %*"PRIu64" %*"PRIu64"\n",
   1414  1.216       ryo 			    (int)evlen_max, "Total",
   1415  1.216       ryo 			    (int)total_max, counttotal,
   1416  1.216       ryo 			    (int)rate_max, counttotal / uptime);
   1417  1.176      matt 		return;
   1418  1.261     skrll 	}
   1419  1.176      matt 
   1420  1.216       ryo 	if (type == EVCNT_TYPE_ANY)
   1421  1.216       ryo 		(void)printf("%-34s %16s %8s %s\n", "event", "total", "rate",
   1422  1.216       ryo 		    "type");
   1423  1.216       ryo 
   1424  1.133       chs 	kread(namelist, X_ALLEVENTS, &allevents, sizeof allevents);
   1425  1.133       chs 	evptr = TAILQ_FIRST(&allevents);
   1426   1.66       cgd 	while (evptr) {
   1427   1.87     lukem 		deref_kptr(evptr, &evcnt, sizeof(evcnt), "event chain trashed");
   1428   1.32       cgd 
   1429  1.133       chs 		evptr = TAILQ_NEXT(&evcnt, ev_list);
   1430   1.66       cgd 		if (evcnt.ev_count == 0 && !verbose)
   1431   1.66       cgd 			continue;
   1432  1.176      matt 		if (type != EVCNT_TYPE_ANY && evcnt.ev_type != type)
   1433  1.176      matt 			continue;
   1434   1.66       cgd 
   1435  1.153  christos 		deref_kptr(evcnt.ev_group, evgroup,
   1436  1.153  christos 		    (size_t)evcnt.ev_grouplen + 1, "event chain trashed");
   1437  1.153  christos 		deref_kptr(evcnt.ev_name, evname,
   1438  1.153  christos 		    (size_t)evcnt.ev_namelen + 1, "event chain trashed");
   1439   1.66       cgd 
   1440  1.180  nakayama 		(void)printf(type == EVCNT_TYPE_ANY ?
   1441  1.180  nakayama 		    "%s %s%*s %16"PRIu64" %8"PRIu64" %s\n" :
   1442  1.180  nakayama 		    "%s %s%*s %16"PRIu64" %8"PRIu64"\n",
   1443  1.176      matt 		    evgroup, evname,
   1444   1.83      matt 		    34 - (evcnt.ev_grouplen + 1 + evcnt.ev_namelen), "",
   1445  1.176      matt 		    evcnt.ev_count,
   1446  1.176      matt 		    (evcnt.ev_count / uptime),
   1447  1.176      matt 		    (evcnt.ev_type < __arraycount(evtypes) ?
   1448   1.86     enami 			evtypes[evcnt.ev_type] : "?"));
   1449  1.176      matt 
   1450  1.180  nakayama 		counttotal += evcnt.ev_count;
   1451   1.18        pk 	}
   1452  1.176      matt 	if (type != EVCNT_TYPE_ANY)
   1453  1.176      matt 		(void)printf("%-34s %16"PRIu64" %8"PRIu64"\n",
   1454  1.176      matt 		    "Total", counttotal, counttotal / uptime);
   1455    1.1       cgd }
   1456    1.1       cgd 
   1457  1.200     joerg static void
   1458  1.200     joerg dopool_sysctl(int verbose, int wide)
   1459  1.200     joerg {
   1460  1.200     joerg 	uint64_t total, inuse, this_total, this_inuse;
   1461  1.200     joerg 	struct {
   1462  1.200     joerg 		uint64_t pt_nget;
   1463  1.200     joerg 		uint64_t pt_nfail;
   1464  1.200     joerg 		uint64_t pt_nput;
   1465  1.200     joerg 		uint64_t pt_nout;
   1466  1.200     joerg 		uint64_t pt_nitems;
   1467  1.200     joerg 		uint64_t pt_npagealloc;
   1468  1.200     joerg 		uint64_t pt_npagefree;
   1469  1.200     joerg 		uint64_t pt_npages;
   1470  1.200     joerg 	} pool_totals;
   1471  1.200     joerg 	size_t i, len;
   1472  1.200     joerg 	int name_len, ovflw;
   1473  1.200     joerg 	struct pool_sysctl *pp, *data;
   1474  1.226    simonb 	char maxp[32];
   1475  1.200     joerg 
   1476  1.200     joerg 	data = asysctlbyname("kern.pool", &len);
   1477  1.200     joerg 	if (data == NULL)
   1478  1.225     sevan 		err(1, "failed to read kern.pool");
   1479  1.200     joerg 
   1480  1.202     joerg 	memset(&pool_totals, 0, sizeof pool_totals);
   1481  1.200     joerg 	total = inuse = 0;
   1482  1.200     joerg 	len /= sizeof(*data);
   1483  1.200     joerg 
   1484  1.200     joerg 	(void)printf("Memory resource pool statistics\n");
   1485  1.200     joerg 	(void)printf(
   1486  1.257    simonb 	    "%-*s%*s%*s%*s%*s%s%s%*s%*s%*s%s%*s%6s%*s%*s%s%s%s\n",
   1487  1.200     joerg 	    wide ? 16 : 11, "Name",
   1488  1.257    simonb 	    wide ? 9 : 5, "Size",
   1489  1.253    simonb 	    wide ? 13 : 9, "Requests",
   1490  1.226    simonb 	    wide ? 8 : 5, "Fail",
   1491  1.253    simonb 	    wide ? 13 : 9, "Releases",
   1492  1.226    simonb 	    wide ? "    InUse" : "",
   1493  1.226    simonb 	    wide ? "    Avail" : "",
   1494  1.226    simonb 	    wide ? 11 : 6, "Pgreq",
   1495  1.226    simonb 	    wide ? 11 : 6, "Pgrel",
   1496  1.253    simonb 	    wide ? 9 : 6, "Npage",
   1497  1.257    simonb 	    wide ? "   PageSz" : "",
   1498  1.253    simonb 	    wide ? 8 : 6, "Hiwat",
   1499  1.200     joerg 	    "Minpg",
   1500  1.253    simonb 	    wide ? 9 : 6, "Maxpg",
   1501  1.253    simonb 	    wide ? 8 : 5, "Idle",
   1502  1.236    simonb 	    wide ? "   Flags" : "",
   1503  1.257    simonb 	    wide ? "   Util" : "",
   1504  1.257    simonb 	    wide ? "    TotalKB" : "");
   1505  1.200     joerg 
   1506  1.200     joerg 	name_len = MIN((int)sizeof(pp->pr_wchan), wide ? 16 : 11);
   1507  1.200     joerg 	for (i = 0; i < len; ++i) {
   1508  1.200     joerg 		pp = &data[i];
   1509  1.200     joerg 		if (pp->pr_nget == 0 && !verbose)
   1510  1.200     joerg 			continue;
   1511  1.200     joerg 		if (pp->pr_maxpages == UINT_MAX)
   1512  1.200     joerg 			(void)snprintf(maxp, sizeof(maxp), "inf");
   1513  1.200     joerg 		else
   1514  1.200     joerg 			(void)snprintf(maxp, sizeof(maxp), "%" PRIu64,
   1515  1.200     joerg 			    pp->pr_maxpages);
   1516  1.200     joerg 		ovflw = 0;
   1517  1.200     joerg 		PRWORD(ovflw, "%-*s", name_len, 0, pp->pr_wchan);
   1518  1.257    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 9 : 5, 1, pp->pr_size);
   1519  1.253    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 13 : 9, 1, pp->pr_nget);
   1520  1.200     joerg 		pool_totals.pt_nget += pp->pr_nget;
   1521  1.226    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 8 : 5, 1, pp->pr_nfail);
   1522  1.200     joerg 		pool_totals.pt_nfail += pp->pr_nfail;
   1523  1.253    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 13 : 9, 1, pp->pr_nput);
   1524  1.200     joerg 		pool_totals.pt_nput += pp->pr_nput;
   1525  1.200     joerg 		if (wide) {
   1526  1.226    simonb 			PRWORD(ovflw, " %*" PRIu64, 9, 1, pp->pr_nout);
   1527  1.200     joerg 			pool_totals.pt_nout += pp->pr_nout;
   1528  1.226    simonb 			PRWORD(ovflw, " %*" PRIu64, 9, 1, pp->pr_nitems);
   1529  1.200     joerg 			pool_totals.pt_nitems += pp->pr_nitems;
   1530  1.200     joerg 		}
   1531  1.226    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 11 : 6, 1, pp->pr_npagealloc);
   1532  1.200     joerg 		pool_totals.pt_npagealloc += pp->pr_npagealloc;
   1533  1.226    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 11 : 6, 1, pp->pr_npagefree);
   1534  1.200     joerg 		pool_totals.pt_npagefree += pp->pr_npagefree;
   1535  1.253    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 9 : 6, 1, pp->pr_npages);
   1536  1.200     joerg 		pool_totals.pt_npages += pp->pr_npages;
   1537  1.200     joerg 		if (wide)
   1538  1.257    simonb 			PRWORD(ovflw, " %*" PRIu64, 9, 1, pp->pr_pagesize);
   1539  1.253    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 8 : 6, 1, pp->pr_hiwat);
   1540  1.200     joerg 		PRWORD(ovflw, " %*" PRIu64, 6, 1, pp->pr_minpages);
   1541  1.253    simonb 		PRWORD(ovflw, " %*s", wide ? 9 : 6, 1, maxp);
   1542  1.253    simonb 		PRWORD(ovflw, " %*" PRIu64, wide ? 8 : 5, 1, pp->pr_nidle);
   1543  1.200     joerg 		if (wide)
   1544  1.236    simonb 			PRWORD(ovflw, " 0x%0*" PRIx64, 6, 1,
   1545  1.200     joerg 			    pp->pr_flags);
   1546  1.200     joerg 
   1547  1.200     joerg 		this_inuse = pp->pr_nout * pp->pr_size;
   1548  1.200     joerg 		this_total = pp->pr_npages * pp->pr_pagesize;
   1549  1.200     joerg 		if (pp->pr_flags & PR_RECURSIVE) {
   1550  1.200     joerg 			/*
   1551  1.200     joerg 			 * Don't count in-use memory, since it's part
   1552  1.200     joerg 			 * of another pool and will be accounted for
   1553  1.200     joerg 			 * there.
   1554  1.200     joerg 			 */
   1555  1.200     joerg 			total += (this_total - this_inuse);
   1556  1.200     joerg 		} else {
   1557  1.200     joerg 			inuse += this_inuse;
   1558  1.200     joerg 			total += this_total;
   1559  1.200     joerg 		}
   1560  1.200     joerg 		if (wide) {
   1561  1.257    simonb 			if (this_total == 0) {
   1562  1.200     joerg 				(void)printf("   ---");
   1563  1.257    simonb 			} else {
   1564  1.257    simonb 				(void)printf(" %5.1f%% %10" PRIu64,
   1565  1.257    simonb 				    (100.0 * this_inuse) / this_total,
   1566  1.257    simonb 				    this_total / KILO);
   1567  1.257    simonb 			}
   1568  1.200     joerg 		}
   1569  1.200     joerg 		(void)printf("\n");
   1570  1.200     joerg 	}
   1571  1.226    simonb 	ovflw = 0;
   1572  1.226    simonb 	PRWORD(ovflw, "%-*s", name_len, 0, "Totals");
   1573  1.257    simonb 	PRWORD(ovflw, " %*s", wide ? 9 : 5, 1, "");
   1574  1.253    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 13 : 9, 1, pool_totals.pt_nget);
   1575  1.226    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 8 : 5, 1, pool_totals.pt_nfail);
   1576  1.253    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 13 : 9, 1, pool_totals.pt_nput);
   1577  1.200     joerg 	if (wide) {
   1578  1.226    simonb 		PRWORD(ovflw, " %*" PRIu64, 9, 1, pool_totals.pt_nout);
   1579  1.226    simonb 		PRWORD(ovflw, " %*" PRIu64, 9, 1, pool_totals.pt_nitems);
   1580  1.200     joerg 	}
   1581  1.226    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 11 : 6, 1, pool_totals.pt_npagealloc);
   1582  1.226    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 11 : 6, 1, pool_totals.pt_npagefree);
   1583  1.253    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 9 : 6, 1, pool_totals.pt_npages);
   1584  1.226    simonb 	(void)printf("\n");
   1585  1.200     joerg 
   1586  1.200     joerg 	inuse /= KILO;
   1587  1.200     joerg 	total /= KILO;
   1588  1.200     joerg 	(void)printf(
   1589  1.201     joerg 	    "\nIn use %" PRIu64 "K, "
   1590  1.201     joerg 	    "total allocated %" PRIu64 "K; utilization %.1f%%\n",
   1591  1.200     joerg 	    inuse, total, (100.0 * inuse) / total);
   1592  1.200     joerg 
   1593  1.200     joerg 	free(data);
   1594  1.200     joerg }
   1595  1.200     joerg 
   1596   1.51        pk void
   1597  1.126    simonb dopool(int verbose, int wide)
   1598   1.51        pk {
   1599   1.69     enami 	int first, ovflw;
   1600   1.87     lukem 	void *addr;
   1601  1.255    simonb 	uint64_t total, inuse, this_total, this_inuse;
   1602  1.189       mrg 	struct {
   1603  1.189       mrg 		uint64_t pt_nget;
   1604  1.189       mrg 		uint64_t pt_nfail;
   1605  1.189       mrg 		uint64_t pt_nput;
   1606  1.189       mrg 		uint64_t pt_nout;
   1607  1.189       mrg 		uint64_t pt_nitems;
   1608  1.189       mrg 		uint64_t pt_npagealloc;
   1609  1.189       mrg 		uint64_t pt_npagefree;
   1610  1.189       mrg 		uint64_t pt_npages;
   1611  1.189       mrg 	} pool_totals;
   1612  1.157        ad 	TAILQ_HEAD(,pool) pool_head;
   1613   1.51        pk 	struct pool pool, *pp = &pool;
   1614   1.98  christos 	struct pool_allocator pa;
   1615  1.226    simonb 	char maxp[32], name[32];
   1616   1.51        pk 
   1617  1.247    rillig 	if (memf == NULL) {
   1618  1.247    rillig 		dopool_sysctl(verbose, wide);
   1619  1.247    rillig 		return;
   1620  1.247    rillig 	}
   1621  1.200     joerg 
   1622  1.189       mrg 	memset(&pool_totals, 0, sizeof pool_totals);
   1623  1.133       chs 	kread(namelist, X_POOLHEAD, &pool_head, sizeof(pool_head));
   1624  1.157        ad 	addr = TAILQ_FIRST(&pool_head);
   1625   1.51        pk 
   1626  1.126    simonb 	total = inuse = 0;
   1627  1.126    simonb 
   1628  1.157        ad 	for (first = 1; addr != NULL; addr = TAILQ_NEXT(pp, pr_poollist) ) {
   1629   1.87     lukem 		deref_kptr(addr, pp, sizeof(*pp), "pool chain trashed");
   1630   1.98  christos 		deref_kptr(pp->pr_alloc, &pa, sizeof(pa),
   1631  1.125   dsainty 		    "pool allocator trashed");
   1632   1.87     lukem 		deref_kptr(pp->pr_wchan, name, sizeof(name),
   1633   1.98  christos 		    "pool wait channel trashed");
   1634   1.87     lukem 		name[sizeof(name)-1] = '\0';
   1635   1.51        pk 
   1636   1.51        pk 		if (first) {
   1637   1.51        pk 			(void)printf("Memory resource pool statistics\n");
   1638   1.51        pk 			(void)printf(
   1639  1.257    simonb 			    "%-*s%*s%*s%*s%*s%s%s%*s%*s%*s%s%*s%6s%*s%*s%s%s%s\n",
   1640  1.126    simonb 			    wide ? 16 : 11, "Name",
   1641  1.257    simonb 			    wide ? 9 : 5, "Size",
   1642  1.253    simonb 			    wide ? 13 : 9, "Requests",
   1643  1.226    simonb 			    wide ? 8 : 5, "Fail",
   1644  1.253    simonb 			    wide ? 13 : 9, "Releases",
   1645  1.226    simonb 			    wide ? "    InUse" : "",
   1646  1.226    simonb 			    wide ? "    Avail" : "",
   1647  1.226    simonb 			    wide ? 11 : 6, "Pgreq",
   1648  1.226    simonb 			    wide ? 11 : 6, "Pgrel",
   1649  1.253    simonb 			    wide ? 9 : 6, "Npage",
   1650  1.257    simonb 			    wide ? "   PageSz" : "",
   1651  1.253    simonb 			    wide ? 8 : 6, "Hiwat",
   1652   1.75     enami 			    "Minpg",
   1653  1.253    simonb 			    wide ? 9 : 6, "Maxpg",
   1654  1.253    simonb 			    wide ? 8 : 5, "Idle",
   1655  1.236    simonb 			    wide ? "   Flags" : "",
   1656  1.257    simonb 			    wide ? "   Util" : "",
   1657  1.257    simonb 			    wide ? "    TotalKB" : "");
   1658   1.51        pk 			first = 0;
   1659   1.51        pk 		}
   1660  1.113       dsl 		if (pp->pr_nget == 0 && !verbose)
   1661  1.113       dsl 			continue;
   1662   1.51        pk 		if (pp->pr_maxpages == UINT_MAX)
   1663  1.153  christos 			(void)snprintf(maxp, sizeof(maxp), "inf");
   1664   1.51        pk 		else
   1665  1.153  christos 			(void)snprintf(maxp, sizeof(maxp), "%u",
   1666  1.153  christos 			    pp->pr_maxpages);
   1667   1.69     enami 		ovflw = 0;
   1668  1.126    simonb 		PRWORD(ovflw, "%-*s", wide ? 16 : 11, 0, name);
   1669  1.257    simonb 		PRWORD(ovflw, " %*u", wide ? 9 : 5, 1, pp->pr_size);
   1670  1.253    simonb 		PRWORD(ovflw, " %*lu", wide ? 13 : 9, 1, pp->pr_nget);
   1671  1.189       mrg 		pool_totals.pt_nget += pp->pr_nget;
   1672  1.226    simonb 		PRWORD(ovflw, " %*lu", wide ? 8 : 5, 1, pp->pr_nfail);
   1673  1.189       mrg 		pool_totals.pt_nfail += pp->pr_nfail;
   1674  1.253    simonb 		PRWORD(ovflw, " %*lu", wide ? 13 : 9, 1, pp->pr_nput);
   1675  1.189       mrg 		pool_totals.pt_nput += pp->pr_nput;
   1676  1.189       mrg 		if (wide) {
   1677  1.226    simonb 			PRWORD(ovflw, " %*u", 9, 1, pp->pr_nout);
   1678  1.189       mrg 			pool_totals.pt_nout += pp->pr_nout;
   1679  1.226    simonb 			PRWORD(ovflw, " %*u", 9, 1, pp->pr_nitems);
   1680  1.189       mrg 			pool_totals.pt_nitems += pp->pr_nitems;
   1681  1.189       mrg 		}
   1682  1.226    simonb 		PRWORD(ovflw, " %*lu", wide ? 11 : 6, 1, pp->pr_npagealloc);
   1683  1.189       mrg 		pool_totals.pt_npagealloc += pp->pr_npagealloc;
   1684  1.226    simonb 		PRWORD(ovflw, " %*lu", wide ? 11 : 6, 1, pp->pr_npagefree);
   1685  1.189       mrg 		pool_totals.pt_npagefree += pp->pr_npagefree;
   1686  1.253    simonb 		PRWORD(ovflw, " %*u", wide ? 9 : 6, 1, pp->pr_npages);
   1687  1.189       mrg 		pool_totals.pt_npages += pp->pr_npages;
   1688  1.126    simonb 		if (wide)
   1689  1.257    simonb 			PRWORD(ovflw, " %*u", 9, 1, pa.pa_pagesz);
   1690  1.253    simonb 		PRWORD(ovflw, " %*u", wide ? 8 : 6, 1, pp->pr_hiwat);
   1691  1.126    simonb 		PRWORD(ovflw, " %*u", 6, 1, pp->pr_minpages);
   1692  1.253    simonb 		PRWORD(ovflw, " %*s", wide ? 9 : 6, 1, maxp);
   1693  1.253    simonb 		PRWORD(ovflw, " %*lu", wide ? 8 : 5, 1, pp->pr_nidle);
   1694  1.126    simonb 		if (wide)
   1695  1.236    simonb 			PRWORD(ovflw, " 0x%0*x", 6, 1,
   1696  1.126    simonb 			    pp->pr_flags | pp->pr_roflags);
   1697   1.51        pk 
   1698  1.255    simonb 		this_inuse = (uint64_t)pp->pr_nout * pp->pr_size;
   1699  1.255    simonb 		this_total = (uint64_t)pp->pr_npages * pa.pa_pagesz;
   1700   1.84     bjh21 		if (pp->pr_roflags & PR_RECURSIVE) {
   1701   1.84     bjh21 			/*
   1702   1.84     bjh21 			 * Don't count in-use memory, since it's part
   1703   1.84     bjh21 			 * of another pool and will be accounted for
   1704   1.84     bjh21 			 * there.
   1705   1.84     bjh21 			 */
   1706  1.126    simonb 			total += (this_total - this_inuse);
   1707   1.84     bjh21 		} else {
   1708  1.126    simonb 			inuse += this_inuse;
   1709  1.126    simonb 			total += this_total;
   1710   1.84     bjh21 		}
   1711  1.126    simonb 		if (wide) {
   1712  1.257    simonb 			if (this_total == 0) {
   1713  1.153  christos 				(void)printf("   ---");
   1714  1.257    simonb 			} else {
   1715  1.257    simonb 				(void)printf(" %5.1f%% %10" PRIu64,
   1716  1.257    simonb 				    (100.0 * this_inuse) / this_total,
   1717  1.257    simonb 				    this_total / KILO);
   1718  1.257    simonb 			}
   1719  1.126    simonb 		}
   1720  1.153  christos 		(void)printf("\n");
   1721   1.51        pk 	}
   1722  1.226    simonb 	ovflw = 0;
   1723  1.226    simonb 	PRWORD(ovflw, "%-*s", wide ? 16 : 11, 0, "Totals");
   1724  1.257    simonb 	PRWORD(ovflw, " %*s", wide ? 9 : 5, 1, "");
   1725  1.253    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 13 : 9, 1, pool_totals.pt_nget);
   1726  1.226    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 8 : 5, 1, pool_totals.pt_nfail);
   1727  1.253    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 13 : 9, 1, pool_totals.pt_nput);
   1728  1.226    simonb  	if (wide) {
   1729  1.226    simonb 		PRWORD(ovflw, " %*" PRIu64, 9, 1, pool_totals.pt_nout);
   1730  1.226    simonb 		PRWORD(ovflw, " %*" PRIu64, 9, 1, pool_totals.pt_nitems);
   1731  1.226    simonb  	}
   1732  1.226    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 11 : 6, 1, pool_totals.pt_npagealloc);
   1733  1.226    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 11 : 6, 1, pool_totals.pt_npagefree);
   1734  1.253    simonb 	PRWORD(ovflw, " %*" PRIu64, wide ? 9 : 6, 1, pool_totals.pt_npages);
   1735  1.226    simonb 	(void)printf("\n");
   1736   1.51        pk 
   1737  1.152  christos 	inuse /= KILO;
   1738  1.152  christos 	total /= KILO;
   1739  1.153  christos 	(void)printf(
   1740  1.255    simonb 	    "\nIn use %" PRIu64 "K, "
   1741  1.255    simonb 	    "total allocated %" PRIu64 "K; utilization %.1f%%\n",
   1742  1.126    simonb 	    inuse, total, (100.0 * inuse) / total);
   1743    1.1       cgd }
   1744   1.96     enami 
   1745  1.200     joerg static void
   1746  1.200     joerg dopoolcache_sysctl(int verbose)
   1747  1.200     joerg {
   1748  1.200     joerg 	struct pool_sysctl *data, *pp;
   1749  1.200     joerg 	size_t i, len;
   1750  1.200     joerg 	bool first = true;
   1751  1.200     joerg 	int ovflw;
   1752  1.200     joerg 	uint64_t tot;
   1753  1.208  christos 	double p;
   1754  1.200     joerg 
   1755  1.200     joerg 	data = asysctlbyname("kern.pool", &len);
   1756  1.200     joerg 	if (data == NULL)
   1757  1.225     sevan 		err(1, "failed to read kern.pool");
   1758  1.200     joerg 	len /= sizeof(*data);
   1759  1.200     joerg 
   1760  1.200     joerg 	for (i = 0; i < len; ++i) {
   1761  1.200     joerg 		pp = &data[i];
   1762  1.200     joerg 		if (pp->pr_cache_meta_size == 0)
   1763  1.200     joerg 			continue;
   1764  1.200     joerg 
   1765  1.200     joerg 		if (pp->pr_cache_nmiss_global == 0 && !verbose)
   1766  1.200     joerg 			continue;
   1767  1.200     joerg 
   1768  1.200     joerg 		if (first) {
   1769  1.200     joerg 			(void)printf("Pool cache statistics.\n");
   1770  1.200     joerg 			(void)printf("%-*s%*s%*s%*s%*s%*s%*s%*s%*s%*s\n",
   1771  1.200     joerg 			    12, "Name",
   1772  1.200     joerg 			    6, "Spin",
   1773  1.200     joerg 			    6, "GrpSz",
   1774  1.200     joerg 			    5, "Full",
   1775  1.200     joerg 			    5, "Emty",
   1776  1.200     joerg 			    10, "PoolLayer",
   1777  1.200     joerg 			    11, "CacheLayer",
   1778  1.200     joerg 			    6, "Hit%",
   1779  1.200     joerg 			    12, "CpuLayer",
   1780  1.200     joerg 			    6, "Hit%"
   1781  1.200     joerg 			);
   1782  1.200     joerg 			first = false;
   1783  1.200     joerg 		}
   1784  1.200     joerg 
   1785  1.200     joerg 		ovflw = 0;
   1786  1.200     joerg 		PRWORD(ovflw, "%-*s", MIN((int)sizeof(pp->pr_wchan), 13), 1,
   1787  1.200     joerg 		    pp->pr_wchan);
   1788  1.200     joerg 		PRWORD(ovflw, " %*" PRIu64, 6, 1, pp->pr_cache_ncontended);
   1789  1.200     joerg 		PRWORD(ovflw, " %*" PRIu64, 6, 1, pp->pr_cache_meta_size);
   1790  1.200     joerg 		PRWORD(ovflw, " %*" PRIu64, 5, 1, pp->pr_cache_nfull);
   1791  1.200     joerg 		PRWORD(ovflw, " %*" PRIu64, 5, 1, pp->pr_cache_nempty);
   1792  1.200     joerg 		PRWORD(ovflw, " %*" PRIu64, 10, 1, pp->pr_cache_nmiss_global);
   1793  1.200     joerg 
   1794  1.200     joerg 		tot = pp->pr_cache_nhit_global + pp->pr_cache_nmiss_global;
   1795  1.200     joerg 		p = pp->pr_cache_nhit_global * 100.0 / tot;
   1796  1.200     joerg 		PRWORD(ovflw, " %*" PRIu64, 11, 1, tot);
   1797  1.200     joerg 		PRWORD(ovflw, " %*.1f", 6, 1, p);
   1798  1.200     joerg 
   1799  1.200     joerg 		tot = pp->pr_cache_nhit_pcpu + pp->pr_cache_nmiss_pcpu;
   1800  1.200     joerg 		p = pp->pr_cache_nhit_pcpu * 100.0 / tot;
   1801  1.200     joerg 		PRWORD(ovflw, " %*" PRIu64, 12, 1, tot);
   1802  1.200     joerg 		PRWORD(ovflw, " %*.1f", 6, 1, p);
   1803  1.200     joerg 		printf("\n");
   1804  1.200     joerg 	}
   1805  1.200     joerg }
   1806  1.200     joerg 
   1807   1.96     enami void
   1808  1.182      yamt dopoolcache(int verbose)
   1809   1.96     enami {
   1810   1.96     enami 	struct pool_cache pool_cache, *pc = &pool_cache;
   1811  1.154        ad 	pool_cache_cpu_t cache_cpu, *cc = &cache_cpu;
   1812  1.157        ad 	TAILQ_HEAD(,pool) pool_head;
   1813  1.154        ad 	struct pool pool, *pp = &pool;
   1814  1.154        ad 	char name[32];
   1815  1.241        ad 	uint64_t cpuhit, cpumiss, pchit, pcmiss, contended, tot;
   1816  1.241        ad 	uint32_t nfull;
   1817  1.154        ad 	void *addr;
   1818  1.165     lukem 	int first, ovflw;
   1819  1.165     lukem 	size_t i;
   1820  1.154        ad 	double p;
   1821   1.96     enami 
   1822  1.247    rillig 	if (memf == NULL) {
   1823  1.247    rillig 		dopoolcache_sysctl(verbose);
   1824  1.247    rillig 		return;
   1825  1.247    rillig 	}
   1826  1.200     joerg 
   1827  1.154        ad 	kread(namelist, X_POOLHEAD, &pool_head, sizeof(pool_head));
   1828  1.157        ad 	addr = TAILQ_FIRST(&pool_head);
   1829   1.96     enami 
   1830  1.157        ad 	for (first = 1; addr != NULL; addr = TAILQ_NEXT(pp, pr_poollist) ) {
   1831  1.154        ad 		deref_kptr(addr, pp, sizeof(*pp), "pool chain trashed");
   1832  1.154        ad 		if (pp->pr_cache == NULL)
   1833   1.96     enami 			continue;
   1834  1.154        ad 		deref_kptr(pp->pr_wchan, name, sizeof(name),
   1835  1.154        ad 		    "pool wait channel trashed");
   1836  1.154        ad 		deref_kptr(pp->pr_cache, pc, sizeof(*pc), "pool cache trashed");
   1837  1.154        ad 		name[sizeof(name)-1] = '\0';
   1838  1.154        ad 
   1839  1.154        ad 		cpuhit = 0;
   1840  1.154        ad 		cpumiss = 0;
   1841  1.241        ad 		pcmiss = 0;
   1842  1.241        ad 		contended = 0;
   1843  1.241        ad 		nfull = 0;
   1844  1.184       jym 		for (i = 0; i < __arraycount(pc->pc_cpus); i++) {
   1845  1.154        ad 		    	if ((addr = pc->pc_cpus[i]) == NULL)
   1846  1.154        ad 		    		continue;
   1847  1.154        ad 			deref_kptr(addr, cc, sizeof(*cc),
   1848  1.154        ad 			    "pool cache cpu trashed");
   1849  1.154        ad 			cpuhit += cc->cc_hits;
   1850  1.154        ad 			cpumiss += cc->cc_misses;
   1851  1.241        ad 			pcmiss += cc->cc_pcmisses;
   1852  1.241        ad 			nfull += cc->cc_nfull;
   1853  1.241        ad 			contended += cc->cc_contended;
   1854  1.137       chs 		}
   1855  1.241        ad 		pchit = cpumiss - pcmiss;
   1856  1.241        ad 
   1857  1.241        ad 		if (pcmiss == 0 && !verbose)
   1858  1.241        ad 			continue;
   1859  1.154        ad 
   1860  1.154        ad 		if (first) {
   1861  1.154        ad 			(void)printf("Pool cache statistics.\n");
   1862  1.156        ad 			(void)printf("%-*s%*s%*s%*s%*s%*s%*s%*s%*s%*s\n",
   1863  1.154        ad 			    12, "Name",
   1864  1.154        ad 			    6, "Spin",
   1865  1.156        ad 			    6, "GrpSz",
   1866  1.156        ad 			    5, "Full",
   1867  1.156        ad 			    5, "Emty",
   1868  1.156        ad 			    10, "PoolLayer",
   1869  1.156        ad 			    11, "CacheLayer",
   1870  1.154        ad 			    6, "Hit%",
   1871  1.154        ad 			    12, "CpuLayer",
   1872  1.154        ad 			    6, "Hit%"
   1873  1.154        ad 			);
   1874  1.154        ad 			first = 0;
   1875   1.96     enami 		}
   1876  1.154        ad 
   1877  1.154        ad 		ovflw = 0;
   1878  1.154        ad 		PRWORD(ovflw, "%-*s", 13, 1, name);
   1879  1.241        ad 		PRWORD(ovflw, " %*llu", 6, 1, (long long)contended);
   1880  1.156        ad 		PRWORD(ovflw, " %*u", 6, 1, pc->pc_pcgsize);
   1881  1.241        ad 		PRWORD(ovflw, " %*u", 5, 1, nfull);
   1882  1.241        ad 		PRWORD(ovflw, " %*u", 5, 1, 0);
   1883  1.241        ad 		PRWORD(ovflw, " %*llu", 10, 1, (long long)pcmiss);
   1884  1.154        ad 
   1885  1.241        ad 		tot = pchit + pcmiss;
   1886  1.241        ad 		p = pchit * 100.0 / (tot);
   1887  1.156        ad 		PRWORD(ovflw, " %*llu", 11, 1, (long long)tot);
   1888  1.154        ad 		PRWORD(ovflw, " %*.1f", 6, 1, p);
   1889  1.154        ad 
   1890  1.154        ad 		tot = cpuhit + cpumiss;
   1891  1.154        ad 		p = cpuhit * 100.0 / (tot);
   1892  1.154        ad 		PRWORD(ovflw, " %*llu", 12, 1, (long long)tot);
   1893  1.154        ad 		PRWORD(ovflw, " %*.1f", 6, 1, p);
   1894  1.154        ad 		printf("\n");
   1895   1.96     enami 	}
   1896   1.96     enami }
   1897   1.90     lukem 
   1898   1.87     lukem enum hashtype {			/* from <sys/systm.h> */
   1899   1.87     lukem 	HASH_LIST,
   1900  1.229        ad 	HASH_SLIST,
   1901  1.229        ad 	HASH_TAILQ,
   1902  1.229        ad 	HASH_PSLIST
   1903   1.87     lukem };
   1904   1.87     lukem 
   1905   1.87     lukem struct kernel_hash {
   1906   1.90     lukem 	const char *	description;	/* description */
   1907   1.90     lukem 	int		hashsize;	/* nlist index for hash size */
   1908   1.90     lukem 	int		hashtbl;	/* nlist index for hash table */
   1909   1.90     lukem 	enum hashtype	type;		/* type of hash table */
   1910  1.101  sommerfe 	size_t		offset;		/* offset of {LIST,TAILQ}_NEXT */
   1911   1.87     lukem } khashes[] =
   1912   1.87     lukem {
   1913   1.87     lukem 	{
   1914   1.90     lukem 		"buffer hash",
   1915   1.90     lukem 		X_BUFHASH, X_BUFHASHTBL,
   1916   1.90     lukem 		HASH_LIST, offsetof(struct buf, b_hash)
   1917   1.90     lukem 	}, {
   1918   1.90     lukem 		"ipv4 address -> interface hash",
   1919   1.87     lukem 		X_IFADDRHASH, X_IFADDRHASHTBL,
   1920   1.87     lukem 		HASH_LIST, offsetof(struct in_ifaddr, ia_hash),
   1921   1.90     lukem 	}, {
   1922   1.90     lukem 		"user info (uid -> used processes) hash",
   1923   1.90     lukem 		X_UIHASH, X_UIHASHTBL,
   1924  1.258        ad 		HASH_SLIST, offsetof(struct uidinfo, ui_hash),
   1925   1.90     lukem 	}, {
   1926  1.229        ad 		"vnode cache hash",
   1927  1.237        ad 		X_VCACHEHASH, X_VCACHETBL,
   1928  1.229        ad 		HASH_SLIST, offsetof(struct vnode_impl, vi_hash),
   1929  1.229        ad 	}, {
   1930   1.90     lukem 		NULL, -1, -1, 0, 0,
   1931   1.87     lukem 	}
   1932   1.87     lukem };
   1933   1.87     lukem 
   1934   1.87     lukem void
   1935   1.88     lukem dohashstat(int verbose, int todo, const char *hashname)
   1936  1.101  sommerfe {
   1937   1.87     lukem 	LIST_HEAD(, generic)	*hashtbl_list;
   1938  1.229        ad 	SLIST_HEAD(, generic)	*hashtbl_slist;
   1939   1.87     lukem 	TAILQ_HEAD(, generic)	*hashtbl_tailq;
   1940   1.87     lukem 	struct kernel_hash	*curhash;
   1941  1.118    itojun 	void	*hashaddr, *hashbuf, *nhashbuf, *nextaddr;
   1942   1.87     lukem 	size_t	elemsize, hashbufsize, thissize;
   1943  1.165     lukem 	u_long	hashsize, i;
   1944  1.165     lukem 	int	used, items, chain, maxchain;
   1945   1.87     lukem 
   1946  1.247    rillig 	if (memf == NULL) {
   1947  1.247    rillig 		dohashstat_sysctl(verbose, todo, hashname);
   1948  1.247    rillig 		return;
   1949  1.247    rillig 	}
   1950  1.245    simonb 
   1951   1.87     lukem 	hashbuf = NULL;
   1952   1.87     lukem 	hashbufsize = 0;
   1953   1.88     lukem 
   1954   1.88     lukem 	if (todo & HASHLIST) {
   1955  1.153  christos 		(void)printf("Supported hashes:\n");
   1956   1.90     lukem 		for (curhash = khashes; curhash->description; curhash++) {
   1957  1.101  sommerfe 			if (hashnl[curhash->hashsize].n_value == 0 ||
   1958   1.90     lukem 			    hashnl[curhash->hashtbl].n_value == 0)
   1959   1.90     lukem 				continue;
   1960  1.153  christos 			(void)printf("\t%-16s%s\n",
   1961   1.90     lukem 			    hashnl[curhash->hashsize].n_name + 1,
   1962   1.90     lukem 			    curhash->description);
   1963   1.88     lukem 		}
   1964   1.88     lukem 		return;
   1965   1.88     lukem 	}
   1966   1.88     lukem 
   1967   1.88     lukem 	if (hashname != NULL) {
   1968   1.90     lukem 		for (curhash = khashes; curhash->description; curhash++) {
   1969   1.90     lukem 			if (strcmp(hashnl[curhash->hashsize].n_name + 1,
   1970   1.90     lukem 			    hashname) == 0 &&
   1971  1.101  sommerfe 			    hashnl[curhash->hashsize].n_value != 0 &&
   1972   1.90     lukem 			    hashnl[curhash->hashtbl].n_value != 0)
   1973   1.88     lukem 				break;
   1974   1.88     lukem 		}
   1975   1.90     lukem 		if (curhash->description == NULL) {
   1976   1.90     lukem 			warnx("%s: no such hash", hashname);
   1977   1.90     lukem 			return;
   1978   1.90     lukem 		}
   1979   1.88     lukem 	}
   1980   1.88     lukem 
   1981  1.153  christos 	(void)printf(
   1982   1.88     lukem 	    "%-16s %8s %8s %8s %8s %8s %8s\n"
   1983   1.88     lukem 	    "%-16s %8s %8s %8s %8s %8s %8s\n",
   1984   1.88     lukem 	    "", "total", "used", "util", "num", "average", "maximum",
   1985   1.88     lukem 	    "hash table", "buckets", "buckets", "%", "items", "chain",
   1986   1.88     lukem 	    "chain");
   1987   1.87     lukem 
   1988   1.90     lukem 	for (curhash = khashes; curhash->description; curhash++) {
   1989  1.101  sommerfe 		if (hashnl[curhash->hashsize].n_value == 0 ||
   1990   1.90     lukem 		    hashnl[curhash->hashtbl].n_value == 0)
   1991   1.90     lukem 			continue;
   1992   1.88     lukem 		if (hashname != NULL &&
   1993   1.90     lukem 		    strcmp(hashnl[curhash->hashsize].n_name + 1, hashname))
   1994   1.88     lukem 			continue;
   1995  1.243    simonb 		switch (curhash->type) {
   1996  1.243    simonb 		case HASH_LIST:
   1997  1.243    simonb 			elemsize = sizeof(*hashtbl_list);
   1998  1.243    simonb 			break;
   1999  1.243    simonb 		case HASH_SLIST:
   2000  1.243    simonb 			elemsize = sizeof(*hashtbl_slist);
   2001  1.243    simonb 			break;
   2002  1.243    simonb 		case HASH_TAILQ:
   2003  1.243    simonb 			elemsize = sizeof(*hashtbl_tailq);
   2004  1.243    simonb 			break;
   2005  1.243    simonb 		default:
   2006  1.243    simonb 			/* shouldn't get here */
   2007  1.243    simonb 			continue;
   2008  1.243    simonb 		}
   2009   1.90     lukem 		deref_kptr((void *)hashnl[curhash->hashsize].n_value,
   2010   1.90     lukem 		    &hashsize, sizeof(hashsize),
   2011   1.90     lukem 		    hashnl[curhash->hashsize].n_name);
   2012   1.87     lukem 		hashsize++;
   2013   1.90     lukem 		deref_kptr((void *)hashnl[curhash->hashtbl].n_value,
   2014   1.90     lukem 		    &hashaddr, sizeof(hashaddr),
   2015   1.90     lukem 		    hashnl[curhash->hashtbl].n_name);
   2016   1.87     lukem 		if (verbose)
   2017  1.153  christos 			(void)printf(
   2018  1.153  christos 			    "%s %lu, %s %p, offset %ld, elemsize %llu\n",
   2019   1.90     lukem 			    hashnl[curhash->hashsize].n_name + 1, hashsize,
   2020   1.90     lukem 			    hashnl[curhash->hashtbl].n_name + 1, hashaddr,
   2021  1.101  sommerfe 			    (long)curhash->offset,
   2022   1.91       jmc 			    (unsigned long long)elemsize);
   2023   1.87     lukem 		thissize = hashsize * elemsize;
   2024  1.144  christos 		if (hashbuf == NULL || thissize > hashbufsize) {
   2025  1.118    itojun 			if ((nhashbuf = realloc(hashbuf, thissize)) == NULL)
   2026  1.101  sommerfe 				errx(1, "malloc hashbuf %llu",
   2027   1.91       jmc 				    (unsigned long long)hashbufsize);
   2028  1.118    itojun 			hashbuf = nhashbuf;
   2029  1.118    itojun 			hashbufsize = thissize;
   2030   1.87     lukem 		}
   2031   1.87     lukem 		deref_kptr(hashaddr, hashbuf, thissize,
   2032   1.90     lukem 		    hashnl[curhash->hashtbl].n_name);
   2033   1.87     lukem 		used = 0;
   2034   1.87     lukem 		items = maxchain = 0;
   2035  1.135     lukem 		if (curhash->type == HASH_LIST) {
   2036   1.87     lukem 			hashtbl_list = hashbuf;
   2037  1.229        ad 			hashtbl_slist = NULL;
   2038  1.229        ad 			hashtbl_tailq = NULL;
   2039  1.229        ad 		} else if (curhash->type == HASH_SLIST) {
   2040  1.229        ad 			hashtbl_list = NULL;
   2041  1.229        ad 			hashtbl_slist = hashbuf;
   2042  1.135     lukem 			hashtbl_tailq = NULL;
   2043  1.135     lukem 		} else {
   2044  1.135     lukem 			hashtbl_list = NULL;
   2045  1.229        ad 			hashtbl_slist = NULL;
   2046   1.87     lukem 			hashtbl_tailq = hashbuf;
   2047  1.135     lukem 		}
   2048   1.87     lukem 		for (i = 0; i < hashsize; i++) {
   2049   1.87     lukem 			if (curhash->type == HASH_LIST)
   2050   1.87     lukem 				nextaddr = LIST_FIRST(&hashtbl_list[i]);
   2051  1.229        ad 			else if (curhash->type == HASH_SLIST)
   2052  1.229        ad 				nextaddr = SLIST_FIRST(&hashtbl_slist[i]);
   2053   1.87     lukem 			else
   2054   1.87     lukem 				nextaddr = TAILQ_FIRST(&hashtbl_tailq[i]);
   2055   1.87     lukem 			if (nextaddr == NULL)
   2056   1.87     lukem 				continue;
   2057   1.87     lukem 			if (verbose)
   2058  1.165     lukem 				(void)printf("%5lu: %p\n", i, nextaddr);
   2059   1.87     lukem 			used++;
   2060   1.87     lukem 			chain = 0;
   2061   1.87     lukem 			do {
   2062   1.87     lukem 				chain++;
   2063   1.87     lukem 				deref_kptr((char *)nextaddr + curhash->offset,
   2064   1.87     lukem 				    &nextaddr, sizeof(void *),
   2065   1.87     lukem 				    "hash chain corrupted");
   2066   1.87     lukem 				if (verbose > 1)
   2067  1.153  christos 					(void)printf("got nextaddr as %p\n",
   2068   1.87     lukem 					    nextaddr);
   2069   1.87     lukem 			} while (nextaddr != NULL);
   2070   1.87     lukem 			items += chain;
   2071   1.87     lukem 			if (verbose && chain > 1)
   2072  1.153  christos 				(void)printf("\tchain = %d\n", chain);
   2073   1.87     lukem 			if (chain > maxchain)
   2074   1.87     lukem 				maxchain = chain;
   2075   1.87     lukem 		}
   2076  1.153  christos 		(void)printf("%-16s %8ld %8d %8.2f %8d %8.2f %8d\n",
   2077   1.90     lukem 		    hashnl[curhash->hashsize].n_name + 1,
   2078   1.87     lukem 		    hashsize, used, used * 100.0 / hashsize,
   2079   1.93     lukem 		    items, used ? (double)items / used : 0.0, maxchain);
   2080   1.87     lukem 	}
   2081   1.87     lukem }
   2082   1.87     lukem 
   2083  1.245    simonb void
   2084  1.245    simonb dohashstat_sysctl(int verbose, int todo, const char *hashname)
   2085  1.245    simonb {
   2086  1.245    simonb 	struct hashstat_sysctl hash, *data, *hs;
   2087  1.245    simonb 	int mib[3];
   2088  1.245    simonb 	int error;
   2089  1.245    simonb 	size_t i, len, miblen;
   2090  1.245    simonb 
   2091  1.245    simonb 
   2092  1.245    simonb 	miblen = __arraycount(mib);
   2093  1.245    simonb 	error = sysctlnametomib("kern.hashstat", mib, &miblen);
   2094  1.245    simonb 	if (error)
   2095  1.245    simonb 		err(EXIT_FAILURE, "nametomib kern.hashstat failed");
   2096  1.245    simonb 	assert(miblen < 3);
   2097  1.245    simonb 
   2098  1.245    simonb 	if (todo & HASHLIST) {
   2099  1.245    simonb 		mib[miblen] = CTL_DESCRIBE;
   2100  1.245    simonb 		miblen++;
   2101  1.245    simonb 	};
   2102  1.245    simonb 
   2103  1.245    simonb 	if (hashname) {
   2104  1.245    simonb 		mib[miblen] = CTL_QUERY;
   2105  1.245    simonb 		miblen++;
   2106  1.245    simonb 		memset(&hash, 0, sizeof(hash));
   2107  1.245    simonb 		strlcpy(hash.hash_name, hashname, sizeof(hash.hash_name));
   2108  1.245    simonb 		len = sizeof(hash);
   2109  1.245    simonb 		error = sysctl(mib, miblen, &hash, &len, &hash, len);
   2110  1.245    simonb 		if (error == ENOENT) {
   2111  1.245    simonb 			err(1, "hash '%s' not found", hashname);
   2112  1.245    simonb 			return;
   2113  1.245    simonb 		} else if (error) {
   2114  1.245    simonb 			err(1, "sysctl kern.hashstat query failed");
   2115  1.245    simonb 			return;
   2116  1.245    simonb 		}
   2117  1.245    simonb 
   2118  1.245    simonb 		data = &hash;
   2119  1.245    simonb 		len = 1;
   2120  1.245    simonb 	} else {
   2121  1.245    simonb 		data = asysctl(mib, miblen, &len);
   2122  1.245    simonb 		if (data == NULL)
   2123  1.245    simonb 			err(1, "failed to read kern.hashstat");
   2124  1.245    simonb 		len /= sizeof(*data);
   2125  1.245    simonb 	}
   2126  1.245    simonb 
   2127  1.245    simonb 	if (todo & HASHLIST) {
   2128  1.245    simonb 		printf("Supported hashes:\n");
   2129  1.245    simonb 		for (i = 0, hs = data; i < len; i++, hs++) {
   2130  1.245    simonb 			printf("\t%-16s%s\n", hs->hash_name, hs->hash_desc);
   2131  1.245    simonb 		}
   2132  1.245    simonb 	} else {
   2133  1.245    simonb 		printf("%-16s %8s %8s %8s %8s %8s %8s\n"
   2134  1.245    simonb 		    "%-16s %8s %8s %8s %8s %8s %8s\n",
   2135  1.245    simonb 		    "", "total", "used", "util", "num", "average", "maximum",
   2136  1.245    simonb 		    "hash table", "buckets", "buckets", "%", "items", "chain",
   2137  1.245    simonb 		    "chain");
   2138  1.245    simonb 		for (i = 0, hs = data; i < len; i++, hs++) {
   2139  1.245    simonb 			printf("%-16s %8"PRId64" %8"PRId64" %8.2f %8"PRId64
   2140  1.245    simonb 			    " %8.2f %8"PRId64"\n",
   2141  1.245    simonb 			    hs->hash_name, hs->hash_size, hs->hash_used,
   2142  1.245    simonb 			    hs->hash_used * 100.0 / hs->hash_size, hs->hash_items,
   2143  1.245    simonb 			    hs->hash_used ? (double)hs->hash_items / hs->hash_used : 0.0,
   2144  1.245    simonb 			    hs->hash_maxchain);
   2145  1.245    simonb 		}
   2146  1.245    simonb 	}
   2147  1.245    simonb 
   2148  1.245    simonb 	if (!hashname && (data != NULL))
   2149  1.245    simonb 		free(data);
   2150  1.245    simonb }
   2151  1.245    simonb 
   2152    1.1       cgd /*
   2153  1.230   msaitoh  * kreadc like kread but returns 1 if successful, 0 otherwise
   2154  1.147    kardel  */
   2155  1.147    kardel int
   2156  1.147    kardel kreadc(struct nlist *nl, int nlx, void *addr, size_t size)
   2157  1.147    kardel {
   2158  1.147    kardel 	const char *sym;
   2159  1.147    kardel 
   2160  1.147    kardel 	sym = nl[nlx].n_name;
   2161  1.147    kardel 	if (*sym == '_')
   2162  1.147    kardel 		++sym;
   2163  1.147    kardel 	if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0)
   2164  1.147    kardel 		return 0;
   2165  1.147    kardel 	deref_kptr((void *)nl[nlx].n_value, addr, size, sym);
   2166  1.147    kardel 	return 1;
   2167  1.147    kardel }
   2168  1.147    kardel 
   2169  1.147    kardel /*
   2170   1.90     lukem  * kread reads something from the kernel, given its nlist index in namelist[].
   2171    1.1       cgd  */
   2172    1.1       cgd void
   2173  1.133       chs kread(struct nlist *nl, int nlx, void *addr, size_t size)
   2174    1.1       cgd {
   2175   1.50   mycroft 	const char *sym;
   2176    1.1       cgd 
   2177  1.133       chs 	sym = nl[nlx].n_name;
   2178   1.87     lukem 	if (*sym == '_')
   2179   1.87     lukem 		++sym;
   2180  1.133       chs 	if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0)
   2181   1.87     lukem 		errx(1, "symbol %s not defined", sym);
   2182  1.133       chs 	deref_kptr((void *)nl[nlx].n_value, addr, size, sym);
   2183   1.87     lukem }
   2184   1.87     lukem 
   2185   1.87     lukem /*
   2186  1.101  sommerfe  * Dereference the kernel pointer `kptr' and fill in the local copy
   2187   1.87     lukem  * pointed to by `ptr'.  The storage space must be pre-allocated,
   2188   1.87     lukem  * and the size of the copy passed in `len'.
   2189   1.87     lukem  */
   2190   1.87     lukem void
   2191   1.87     lukem deref_kptr(const void *kptr, void *ptr, size_t len, const char *msg)
   2192   1.87     lukem {
   2193   1.87     lukem 
   2194   1.87     lukem 	if (*msg == '_')
   2195   1.87     lukem 		msg++;
   2196  1.165     lukem 	if ((size_t)kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len)
   2197   1.87     lukem 		errx(1, "kptr %lx: %s: %s", (u_long)kptr, msg, kvm_geterr(kd));
   2198    1.1       cgd }
   2199    1.1       cgd 
   2200   1.45   thorpej /*
   2201  1.181       mrg  * Traverse the kernel history buffers, performing the requested action.
   2202   1.45   thorpej  *
   2203   1.45   thorpej  * Note, we assume that if we're not listing, we're dumping.
   2204   1.45   thorpej  */
   2205   1.45   thorpej void
   2206   1.73    simonb hist_traverse(int todo, const char *histname)
   2207   1.45   thorpej {
   2208  1.210  pgoyette 	struct kern_history_head histhead;
   2209  1.210  pgoyette 	struct kern_history hist, *histkva;
   2210  1.210  pgoyette 	char *name = NULL;
   2211  1.210  pgoyette 	size_t namelen = 0;
   2212  1.210  pgoyette 
   2213  1.210  pgoyette 	if (histnl[0].n_value == 0) {
   2214  1.210  pgoyette 		warnx("kernel history is not compiled into the kernel.");
   2215  1.210  pgoyette 		return;
   2216  1.210  pgoyette 	}
   2217  1.210  pgoyette 
   2218  1.210  pgoyette 	deref_kptr((void *)histnl[X_KERN_HISTORIES].n_value, &histhead,
   2219  1.210  pgoyette 	    sizeof(histhead), histnl[X_KERN_HISTORIES].n_name);
   2220  1.210  pgoyette 
   2221  1.210  pgoyette 	if (histhead.lh_first == NULL) {
   2222  1.210  pgoyette 		warnx("No active kernel history logs.");
   2223  1.210  pgoyette 		return;
   2224  1.210  pgoyette 	}
   2225  1.210  pgoyette 
   2226  1.210  pgoyette 	if (todo & HISTLIST)
   2227  1.210  pgoyette 		(void)printf("Active kernel histories:");
   2228  1.210  pgoyette 
   2229  1.210  pgoyette 	for (histkva = LIST_FIRST(&histhead); histkva != NULL;
   2230  1.210  pgoyette 	    histkva = LIST_NEXT(&hist, list)) {
   2231  1.210  pgoyette 		deref_kptr(histkva, &hist, sizeof(hist), "histkva");
   2232  1.210  pgoyette 		if (name == NULL || hist.namelen > namelen) {
   2233  1.210  pgoyette 			if (name != NULL)
   2234  1.210  pgoyette 				free(name);
   2235  1.210  pgoyette 			namelen = hist.namelen;
   2236  1.210  pgoyette 			if ((name = malloc(namelen + 1)) == NULL)
   2237  1.210  pgoyette 				err(1, "malloc history name");
   2238  1.210  pgoyette 		}
   2239  1.210  pgoyette 
   2240  1.210  pgoyette 		deref_kptr(hist.name, name, namelen, "history name");
   2241  1.210  pgoyette 		name[namelen] = '\0';
   2242  1.210  pgoyette 		if (todo & HISTLIST)
   2243  1.210  pgoyette 			(void)printf(" %s", name);
   2244  1.210  pgoyette 		else {
   2245  1.210  pgoyette 			/*
   2246  1.210  pgoyette 			 * If we're dumping all histories, do it, else
   2247  1.210  pgoyette 			 * check to see if this is the one we want.
   2248  1.210  pgoyette 			 */
   2249  1.210  pgoyette 			if (histname == NULL || strcmp(histname, name) == 0) {
   2250  1.210  pgoyette 				if (histname == NULL)
   2251  1.210  pgoyette 					(void)printf(
   2252  1.210  pgoyette 					    "\nkernel history `%s':\n", name);
   2253  1.210  pgoyette 				hist_dodump(&hist);
   2254  1.210  pgoyette 			}
   2255  1.210  pgoyette 		}
   2256  1.210  pgoyette 	}
   2257  1.210  pgoyette 
   2258  1.210  pgoyette 	if (todo & HISTLIST)
   2259  1.210  pgoyette 		(void)putchar('\n');
   2260  1.210  pgoyette 
   2261  1.210  pgoyette 	if (name != NULL)
   2262  1.210  pgoyette 		free(name);
   2263  1.210  pgoyette }
   2264  1.210  pgoyette 
   2265  1.210  pgoyette /*
   2266  1.210  pgoyette  * Actually dump the history buffer at the specified KVA.
   2267  1.210  pgoyette  */
   2268  1.210  pgoyette void
   2269  1.210  pgoyette hist_dodump(struct kern_history *histp)
   2270  1.210  pgoyette {
   2271  1.210  pgoyette 	struct kern_history_ent *histents, *e;
   2272  1.215  pgoyette 	struct timeval tv;
   2273  1.210  pgoyette 	size_t histsize;
   2274  1.210  pgoyette 	char *fmt = NULL, *fn = NULL;
   2275  1.210  pgoyette 	size_t fmtlen = 0, fnlen = 0;
   2276  1.210  pgoyette 	unsigned i;
   2277  1.210  pgoyette 
   2278  1.210  pgoyette 	histsize = sizeof(struct kern_history_ent) * histp->n;
   2279  1.210  pgoyette 
   2280  1.210  pgoyette 	if ((histents = malloc(histsize)) == NULL)
   2281  1.210  pgoyette 		err(1, "malloc history entries");
   2282  1.210  pgoyette 
   2283  1.210  pgoyette 	(void)memset(histents, 0, histsize);
   2284  1.210  pgoyette 
   2285  1.211  pgoyette 	(void)printf("%"PRIu32" entries, next is %"PRIu32"\n",
   2286  1.211  pgoyette 	    histp->n, histp->f);
   2287  1.211  pgoyette 
   2288  1.210  pgoyette 	deref_kptr(histp->e, histents, histsize, "history entries");
   2289  1.210  pgoyette 	i = histp->f;
   2290  1.210  pgoyette 	do {
   2291  1.210  pgoyette 		e = &histents[i];
   2292  1.210  pgoyette 		if (e->fmt != NULL) {
   2293  1.210  pgoyette 			if (fmt == NULL || e->fmtlen > fmtlen) {
   2294  1.227       mrg 				free(fmt);
   2295  1.210  pgoyette 				fmtlen = e->fmtlen;
   2296  1.210  pgoyette 				if ((fmt = malloc(fmtlen + 1)) == NULL)
   2297  1.210  pgoyette 					err(1, "malloc printf format");
   2298  1.210  pgoyette 			}
   2299  1.210  pgoyette 			if (fn == NULL || e->fnlen > fnlen) {
   2300  1.227       mrg 				free(fn);
   2301  1.210  pgoyette 				fnlen = e->fnlen;
   2302  1.210  pgoyette 				if ((fn = malloc(fnlen + 1)) == NULL)
   2303  1.210  pgoyette 					err(1, "malloc function name");
   2304  1.210  pgoyette 			}
   2305  1.210  pgoyette 
   2306  1.210  pgoyette 			deref_kptr(e->fmt, fmt, fmtlen, "printf format");
   2307  1.210  pgoyette 			fmt[fmtlen] = '\0';
   2308  1.227       mrg 			for (unsigned z = 0; z < fmtlen - 1; z++) {
   2309  1.227       mrg 				if (fmt[z] == '%' && fmt[z+1] == 's')
   2310  1.227       mrg 					fmt[z+1] = 'p';
   2311  1.227       mrg 			}
   2312  1.210  pgoyette 
   2313  1.210  pgoyette 			deref_kptr(e->fn, fn, fnlen, "function name");
   2314  1.210  pgoyette 			fn[fnlen] = '\0';
   2315  1.210  pgoyette 
   2316  1.215  pgoyette 			bintime2timeval(&e->bt, &tv);
   2317  1.215  pgoyette 			(void)printf("%06ld.%06ld ", (long int)tv.tv_sec,
   2318  1.215  pgoyette 			    (long int)tv.tv_usec);
   2319  1.256    simonb 			(void)printf("%s#%" PRId32 "@%" PRId32 ": ",
   2320  1.219  pgoyette 			    fn, e->call, e->cpunum);
   2321  1.210  pgoyette 			(void)printf(fmt, e->v[0], e->v[1], e->v[2], e->v[3]);
   2322  1.210  pgoyette 			(void)putchar('\n');
   2323  1.210  pgoyette 		}
   2324  1.210  pgoyette 		i = (i + 1) % histp->n;
   2325  1.210  pgoyette 	} while (i != histp->f);
   2326  1.210  pgoyette 
   2327  1.210  pgoyette 	free(histents);
   2328  1.227       mrg 	free(fmt);
   2329  1.227       mrg 	free(fn);
   2330  1.210  pgoyette }
   2331  1.210  pgoyette 
   2332  1.210  pgoyette void
   2333  1.210  pgoyette hist_traverse_sysctl(int todo, const char *histname)
   2334  1.210  pgoyette {
   2335  1.209  pgoyette 	int error;
   2336  1.209  pgoyette 	int mib[4];
   2337  1.209  pgoyette 	unsigned int i;
   2338  1.209  pgoyette 	size_t len, miblen;
   2339  1.209  pgoyette 	struct sysctlnode query, histnode[32];
   2340  1.209  pgoyette 
   2341  1.209  pgoyette 	/* retrieve names of available histories */
   2342  1.209  pgoyette 	miblen = __arraycount(mib);
   2343  1.209  pgoyette 	error = sysctlnametomib("kern.hist", mib, &miblen);
   2344  1.209  pgoyette 	if (error != 0) {
   2345  1.214  pgoyette 		if (errno == ENOENT) {
   2346  1.214  pgoyette  			warnx("kernel history is not compiled into the kernel.");
   2347  1.214  pgoyette 			return;
   2348  1.214  pgoyette 		} else
   2349  1.245    simonb 			err(EXIT_FAILURE, "nametomib kern.hist failed");
   2350  1.209  pgoyette 	}
   2351  1.260     skrll 
   2352  1.209  pgoyette 	/* get the list of nodenames below kern.hist */
   2353  1.209  pgoyette 	mib[2] = CTL_QUERY;
   2354  1.209  pgoyette 	memset(&query, 0, sizeof(query));
   2355  1.209  pgoyette 	query.sysctl_flags = SYSCTL_VERSION;
   2356  1.209  pgoyette 	len = sizeof(histnode);
   2357  1.209  pgoyette 	error = sysctl(mib, 3, &histnode[0], &len, &query, sizeof(query));
   2358  1.209  pgoyette 	if (error != 0) {
   2359  1.209  pgoyette 		err(1, "query failed");
   2360  1.209  pgoyette 		return;
   2361  1.209  pgoyette 	}
   2362  1.209  pgoyette 	if (len == 0) {
   2363  1.210  pgoyette  		warnx("No active kernel history logs.");
   2364  1.210  pgoyette  		return;
   2365  1.210  pgoyette  	}
   2366  1.260     skrll 
   2367  1.209  pgoyette 	len = len / sizeof(histnode[0]);	/* get # of entries returned */
   2368  1.209  pgoyette 
   2369  1.210  pgoyette  	if (todo & HISTLIST)
   2370  1.210  pgoyette  		(void)printf("Active kernel histories:");
   2371  1.260     skrll 
   2372  1.209  pgoyette 	for (i = 0; i < len; i++) {
   2373  1.210  pgoyette  		if (todo & HISTLIST)
   2374  1.209  pgoyette 			(void)printf(" %s", histnode[i].sysctl_name);
   2375  1.210  pgoyette  		else {
   2376  1.210  pgoyette  			/*
   2377  1.210  pgoyette  			 * If we're dumping all histories, do it, else
   2378  1.210  pgoyette  			 * check to see if this is the one we want.
   2379  1.210  pgoyette  			 */
   2380  1.209  pgoyette 			if (histname == NULL ||
   2381  1.209  pgoyette 			    strcmp(histname, histnode[i].sysctl_name) == 0) {
   2382  1.210  pgoyette  				if (histname == NULL)
   2383  1.210  pgoyette  					(void)printf(
   2384  1.209  pgoyette 					    "\nkernel history `%s':\n",
   2385  1.209  pgoyette 					    histnode[i].sysctl_name);
   2386  1.209  pgoyette 				mib[2] = histnode[i].sysctl_num;
   2387  1.209  pgoyette 				mib[3] = CTL_EOL;
   2388  1.210  pgoyette 				hist_dodump_sysctl(mib, 4);
   2389  1.210  pgoyette  			}
   2390  1.210  pgoyette  		}
   2391  1.210  pgoyette  	}
   2392  1.260     skrll 
   2393  1.210  pgoyette  	if (todo & HISTLIST)
   2394  1.210  pgoyette  		(void)putchar('\n');
   2395  1.219  pgoyette 	else if (mib[2] == CTL_QUERY)
   2396  1.219  pgoyette 		warnx("history %s not found", histname);
   2397  1.210  pgoyette  }
   2398  1.260     skrll 
   2399  1.210  pgoyette  /*
   2400  1.210  pgoyette   * Actually dump the history buffer at the specified KVA.
   2401  1.210  pgoyette   */
   2402  1.221       mrg void
   2403  1.210  pgoyette hist_dodump_sysctl(int mib[], unsigned int miblen)
   2404  1.221       mrg {
   2405  1.209  pgoyette 	struct sysctl_history *hist;
   2406  1.215  pgoyette 	struct timeval tv;
   2407  1.209  pgoyette 	struct sysctl_history_event *e;
   2408  1.210  pgoyette  	size_t histsize;
   2409  1.209  pgoyette 	char *strp;
   2410  1.210  pgoyette  	unsigned i;
   2411   1.45   thorpej 	char *fmt = NULL, *fn = NULL;
   2412  1.260     skrll 
   2413  1.209  pgoyette 	hist = NULL;
   2414  1.209  pgoyette 	histsize = 0;
   2415  1.210  pgoyette  	do {
   2416  1.209  pgoyette 		errno = 0;
   2417  1.209  pgoyette 		if (sysctl(mib, miblen, hist, &histsize, NULL, 0) == 0)
   2418  1.209  pgoyette 			break;
   2419  1.209  pgoyette 		if (errno != ENOMEM)
   2420  1.209  pgoyette 			break;
   2421  1.209  pgoyette 		if ((hist = realloc(hist, histsize)) == NULL)
   2422  1.209  pgoyette 			errx(1, "realloc history buffer");
   2423  1.209  pgoyette 	} while (errno == ENOMEM);
   2424  1.209  pgoyette 	if (errno != 0)
   2425  1.209  pgoyette 		err(1, "sysctl failed");
   2426  1.260     skrll 
   2427  1.219  pgoyette 	strp = (char *)(&hist->sh_events[hist->sh_numentries]);
   2428  1.260     skrll 
   2429  1.209  pgoyette 	(void)printf("%"PRIu32" entries, next is %"PRIu32"\n",
   2430  1.219  pgoyette 	    hist->sh_numentries,
   2431  1.219  pgoyette 	    hist->sh_nextfree);
   2432  1.260     skrll 
   2433  1.219  pgoyette 	i = hist->sh_nextfree;
   2434   1.45   thorpej 
   2435   1.45   thorpej 	do {
   2436  1.209  pgoyette 		e = &hist->sh_events[i];
   2437  1.209  pgoyette 		if (e->she_fmtoffset != 0) {
   2438  1.209  pgoyette 			fmt = &strp[e->she_fmtoffset];
   2439  1.227       mrg 			size_t fmtlen = strlen(fmt);
   2440  1.227       mrg 			for (unsigned z = 0; z < fmtlen - 1; z++) {
   2441  1.227       mrg 				if (fmt[z] == '%' && fmt[z+1] == 's')
   2442  1.227       mrg 					fmt[z+1] = 'p';
   2443  1.227       mrg 			}
   2444  1.209  pgoyette 			fn = &strp[e->she_funcoffset];
   2445  1.215  pgoyette 			bintime2timeval(&e->she_bintime, &tv);
   2446  1.219  pgoyette 			(void)printf("%06ld.%06ld %s#%"PRIu32"@%"PRIu32": ",
   2447  1.215  pgoyette 			    (long int)tv.tv_sec, (long int)tv.tv_usec,
   2448  1.213  pgoyette 			    fn, e->she_callnumber, e->she_cpunum);
   2449  1.209  pgoyette 			(void)printf(fmt, e->she_values[0], e->she_values[1],
   2450  1.209  pgoyette 			     e->she_values[2], e->she_values[3]);
   2451  1.210  pgoyette  			(void)putchar('\n');
   2452  1.210  pgoyette  		}
   2453  1.219  pgoyette 		i = (i + 1) % hist->sh_numentries;
   2454  1.219  pgoyette 	} while (i != hist->sh_nextfree);
   2455  1.260     skrll 
   2456  1.209  pgoyette 	free(hist);
   2457  1.210  pgoyette  }
   2458   1.45   thorpej 
   2459  1.183     joerg static void
   2460   1.73    simonb usage(void)
   2461    1.1       cgd {
   2462   1.47       mrg 
   2463    1.1       cgd 	(void)fprintf(stderr,
   2464  1.250       mrg 	    "usage: %s [-CefHiLlmstUvW] [-c count] [-h hashname]\n"
   2465  1.251       wiz 	    "\t\t[-M core] [-N system] [-n diskcount] [-u histname]\n"
   2466  1.250       mrg 	    "[-w wait] [disks]\n",
   2467  1.250       mrg 	    getprogname());
   2468    1.1       cgd 	exit(1);
   2469    1.1       cgd }
   2470