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