Thu Apr 1 05:33:51 2021 UTC ()
Now that ports that use legacy intrcnt interrupt accounting have event
counters to show that data, for the live kernel case just show INTR
events for "vmstat -i".


(simonb)
diff -r1.243 -r1.244 src/usr.bin/vmstat/vmstat.c

cvs diff -r1.243 -r1.244 src/usr.bin/vmstat/vmstat.c (switch to unified diff)

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