Annotation of src/usr.bin/vmstat/vmstat.c, Revision 1.86
1.11 deraadt 1: /* $NetBSD: vmstat.c,v 1.29.4.1 1996/06/05 00:21:05 cgd Exp $ */
1.86 ! deraadt 2: /* $OpenBSD: vmstat.c,v 1.85 2004/06/14 00:38:02 deraadt Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1980, 1986, 1991, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.77 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: static char copyright[] =
35: "@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
36: The Regents of the University of California. All rights reserved.\n";
37: #endif /* not lint */
38:
39: #ifndef lint
40: #if 0
41: static char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93";
42: #else
1.86 ! deraadt 43: static const char rcsid[] = "$OpenBSD: vmstat.c,v 1.85 2004/06/14 00:38:02 deraadt Exp $";
1.1 deraadt 44: #endif
45: #endif /* not lint */
1.48 art 46:
1.1 deraadt 47: #include <sys/param.h>
48: #include <sys/time.h>
49: #include <sys/proc.h>
50: #include <sys/user.h>
51: #include <sys/dkstat.h>
52: #include <sys/buf.h>
53: #include <sys/namei.h>
54: #include <sys/malloc.h>
55: #include <sys/fcntl.h>
56: #include <sys/ioctl.h>
57: #include <sys/sysctl.h>
58: #include <sys/device.h>
1.48 art 59: #include <sys/pool.h>
1.1 deraadt 60: #include <time.h>
61: #include <nlist.h>
62: #include <kvm.h>
1.21 millert 63: #include <err.h>
1.1 deraadt 64: #include <errno.h>
65: #include <unistd.h>
66: #include <signal.h>
67: #include <stdio.h>
68: #include <ctype.h>
69: #include <stdlib.h>
70: #include <string.h>
71: #include <paths.h>
72: #include <limits.h>
1.6 tholo 73: #include "dkstats.h"
1.1 deraadt 74:
1.56 angelos 75: #include <uvm/uvm_object.h>
1.29 art 76: #include <uvm/uvm_extern.h>
77:
1.1 deraadt 78: struct nlist namelist[] = {
1.70 deraadt 79: #define X_UVMEXP 0 /* sysctl */
1.29 art 80: { "_uvmexp" },
1.70 deraadt 81: #define X_BOOTTIME 1 /* sysctl */
1.1 deraadt 82: { "_boottime" },
1.70 deraadt 83: #define X_NCHSTATS 2 /* sysctl */
1.1 deraadt 84: { "_nchstats" },
1.70 deraadt 85: #define X_KMEMSTAT 3 /* sysctl */
86: { "_kmemstats" },
87: #define X_KMEMBUCKETS 4 /* sysctl */
88: { "_bucket" },
89: #define X_FORKSTAT 5 /* sysctl */
90: { "_forkstat" },
91: #define X_NSELCOLL 6 /* sysctl */
92: { "_nselcoll" },
93: #define X_POOLHEAD 7 /* sysctl */
94: { "_pool_head" },
95: #define X_ALLEVENTS 8 /* no sysctl */
96: { "_allevents" },
97: #define X_INTRNAMES 9 /* no sysctl */
1.1 deraadt 98: { "_intrnames" },
1.70 deraadt 99: #define X_EINTRNAMES 10 /* no sysctl */
1.1 deraadt 100: { "_eintrnames" },
1.70 deraadt 101: #define X_INTRCNT 11 /* no sysctl */
1.1 deraadt 102: { "_intrcnt" },
1.70 deraadt 103: #define X_EINTRCNT 12 /* no sysctl */
1.1 deraadt 104: { "_eintrcnt" },
1.70 deraadt 105: #define X_END 13 /* no sysctl */
1.28 espie 106: #if defined(__i386__)
1.70 deraadt 107: #define X_INTRHAND (X_END) /* no sysctl */
1.12 tholo 108: { "_intrhand" },
1.83 deraadt 109: #define X_APICINTRHAND (X_END+1) /* no sysctl */
110: { "_apic_intrhand" },
111: #define X_INTRSTRAY (X_END+2) /* no sysctl */
1.12 tholo 112: { "_intrstray" },
113: #endif
1.1 deraadt 114: { "" },
115: };
116:
1.6 tholo 117: /* Objects defined in dkstats.c */
1.73 tdeval 118: extern struct _disk cur, last;
1.10 deraadt 119: extern char **dr_name;
120: extern int *dk_select, dk_ndrive;
1.1 deraadt 121:
1.29 art 122: struct uvmexp uvmexp, ouvmexp;
1.6 tholo 123: int ndrives;
1.1 deraadt 124:
125: int winlines = 20;
126:
127: kvm_t *kd;
128:
129: #define FORKSTAT 0x01
130: #define INTRSTAT 0x02
131: #define MEMSTAT 0x04
132: #define SUMSTAT 0x08
133: #define TIMESTAT 0x10
134: #define VMSTAT 0x20
135:
1.66 millert 136: void cpustats(void);
137: void dkstats(void);
138: void dointr(void);
139: void domem(void);
140: void dopool(void);
141: void dosum(void);
142: void dovmstat(u_int, int);
143: void kread(int, void *, size_t);
144: void usage(void);
145: void dotimes(void);
146: void doforkst(void);
147: void printhdr(void);
1.1 deraadt 148:
1.66 millert 149: char **choosedrives(char **);
1.10 deraadt 150:
151: /* Namelist and memory file names. */
152: char *nlistf, *memf;
1.6 tholo 153:
1.50 art 154: extern char *__progname;
155:
1.65 art 156: int verbose = 0;
157:
1.84 deraadt 158: int ncpu;
159:
1.21 millert 160: int
1.72 deraadt 161: main(int argc, char *argv[])
1.1 deraadt 162: {
163: extern int optind;
164: extern char *optarg;
1.84 deraadt 165: int mib[2];
166: size_t size;
1.62 mpech 167: int c, todo;
1.1 deraadt 168: u_int interval;
169: int reps;
1.25 deraadt 170: char errbuf[_POSIX2_LINE_MAX];
1.1 deraadt 171:
172: interval = reps = todo = 0;
1.65 art 173: while ((c = getopt(argc, argv, "c:fiM:mN:stw:v")) != -1) {
1.1 deraadt 174: switch (c) {
175: case 'c':
176: reps = atoi(optarg);
177: break;
178: case 'f':
179: todo |= FORKSTAT;
180: break;
181: case 'i':
182: todo |= INTRSTAT;
183: break;
184: case 'M':
185: memf = optarg;
186: break;
187: case 'm':
188: todo |= MEMSTAT;
189: break;
190: case 'N':
191: nlistf = optarg;
192: break;
193: case 's':
194: todo |= SUMSTAT;
195: break;
196: case 't':
197: todo |= TIMESTAT;
198: break;
199: case 'w':
200: interval = atoi(optarg);
201: break;
1.65 art 202: case 'v':
203: verbose = 1;
204: break;
1.1 deraadt 205: case '?':
206: default:
207: usage();
208: }
209: }
210: argc -= optind;
211: argv += optind;
212:
213: if (todo == 0)
214: todo = VMSTAT;
215:
1.56 angelos 216: if (nlistf != NULL || memf != NULL) {
217: setegid(getgid());
218: setgid(getgid());
219: }
220:
1.1 deraadt 221: /*
222: * Discard setgid privileges if not the running kernel so that bad
223: * guys can't print interesting stuff from kernel memory.
224: */
1.56 angelos 225: #if notyet
1.15 tholo 226: if (nlistf != NULL || memf != NULL) {
1.56 angelos 227: #endif
228: kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
229: if (kd == 0)
230: errx(1, "kvm_openfiles: %s", errbuf);
231:
232: if ((c = kvm_nlist(kd, namelist)) != 0) {
233: setgid(getgid());
234: setegid(getegid());
235:
1.85 deraadt 236: #ifdef __i386__
237: if (c == 1 && namelist[X_APICINTRHAND].n_value == 0)
1.86 ! deraadt 238: ;
1.85 deraadt 239: else
240: #endif
1.56 angelos 241: if (c > 0) {
242: (void)fprintf(stderr,
243: "%s: undefined symbols:", __progname);
244: for (c = 0;
245: c < sizeof(namelist)/sizeof(namelist[0]);
246: c++)
247: if (namelist[c].n_type == 0)
248: fprintf(stderr, " %s",
249: namelist[c].n_name);
250: (void)fputc('\n', stderr);
251: exit(1);
252: } else
253: errx(1, "kvm_nlist: %s", kvm_geterr(kd));
254: }
255: #ifdef notyet
1.15 tholo 256: }
1.59 heko 257: #endif /* notyet */
1.1 deraadt 258:
1.56 angelos 259: setegid(getegid());
260: setgid(getgid());
1.1 deraadt 261:
1.84 deraadt 262: mib[0] = CTL_HW;
263: mib[1] = HW_NCPU;
264: size = sizeof(ncpu);
265: (void) sysctl(mib, 2, &ncpu, &size, NULL, 0);
266:
1.1 deraadt 267: if (todo & VMSTAT) {
268: struct winsize winsize;
269:
1.6 tholo 270: dkinit(0); /* Initialize disk stats, no disks selected. */
271: argv = choosedrives(argv); /* Select disks. */
1.1 deraadt 272: winsize.ws_row = 0;
273: (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
274: if (winsize.ws_row > 0)
275: winlines = winsize.ws_row;
276:
277: }
1.25 deraadt 278:
1.1 deraadt 279: #define BACKWARD_COMPATIBILITY
280: #ifdef BACKWARD_COMPATIBILITY
281: if (*argv) {
282: interval = atoi(*argv);
283: if (*++argv)
284: reps = atoi(*argv);
285: }
286: #endif
287:
288: if (interval) {
289: if (!reps)
290: reps = -1;
291: } else if (reps)
292: interval = 1;
293:
294: if (todo & FORKSTAT)
295: doforkst();
1.48 art 296: if (todo & MEMSTAT) {
1.1 deraadt 297: domem();
1.48 art 298: dopool();
299: }
1.1 deraadt 300: if (todo & SUMSTAT)
301: dosum();
302: if (todo & TIMESTAT)
303: dotimes();
304: if (todo & INTRSTAT)
305: dointr();
306: if (todo & VMSTAT)
307: dovmstat(interval, reps);
308: exit(0);
309: }
310:
311: char **
1.72 deraadt 312: choosedrives(char **argv)
1.1 deraadt 313: {
1.62 mpech 314: int i;
1.1 deraadt 315:
316: /*
317: * Choose drives to be displayed. Priority goes to (in order) drives
318: * supplied as arguments, default drives. If everything isn't filled
319: * in and there are drives not taken care of, display the first few
320: * that fit.
321: */
322: #define BACKWARD_COMPATIBILITY
323: for (ndrives = 0; *argv; ++argv) {
324: #ifdef BACKWARD_COMPATIBILITY
325: if (isdigit(**argv))
326: break;
327: #endif
328: for (i = 0; i < dk_ndrive; i++) {
329: if (strcmp(dr_name[i], *argv))
330: continue;
1.6 tholo 331: dk_select[i] = 1;
1.1 deraadt 332: ++ndrives;
333: break;
334: }
335: }
1.64 deraadt 336: for (i = 0; i < dk_ndrive && ndrives < 2; i++) {
1.6 tholo 337: if (dk_select[i])
1.1 deraadt 338: continue;
1.6 tholo 339: dk_select[i] = 1;
1.1 deraadt 340: ++ndrives;
341: }
342: return(argv);
343: }
344:
1.19 deraadt 345: time_t
1.72 deraadt 346: getuptime(void)
1.1 deraadt 347: {
1.11 deraadt 348: static time_t now;
349: static struct timeval boottime;
1.1 deraadt 350: time_t uptime;
1.50 art 351: int mib[2];
352: size_t size;
1.1 deraadt 353:
1.50 art 354: if (boottime.tv_sec == 0) {
1.56 angelos 355: if (nlistf == NULL && memf == NULL) {
1.50 art 356: size = sizeof(boottime);
357: mib[0] = CTL_KERN;
358: mib[1] = KERN_BOOTTIME;
359: if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
1.56 angelos 360: warn("could not get kern.boottime");
1.50 art 361: bzero(&boottime, sizeof(boottime));
362: }
1.56 angelos 363: } else {
364: kread(X_BOOTTIME, &boottime, sizeof(boottime));
1.50 art 365: }
366: }
1.1 deraadt 367: (void)time(&now);
1.11 deraadt 368: uptime = now - boottime.tv_sec;
1.50 art 369: if (uptime <= 0 || uptime > 60*60*24*365*10)
370: errx(1, "time makes no sense; namelist must be wrong");
371:
1.1 deraadt 372: return(uptime);
373: }
374:
375: int hz, hdrcnt;
376:
377: void
1.72 deraadt 378: dovmstat(u_int interval, int reps)
1.1 deraadt 379: {
380: struct vmtotal total;
381: time_t uptime, halfuptime;
1.78 deraadt 382: void needhdr(int);
1.1 deraadt 383: int mib[2];
1.50 art 384: struct clockinfo clkinfo;
1.1 deraadt 385: size_t size;
386:
387: uptime = getuptime();
388: halfuptime = uptime / 2;
389: (void)signal(SIGCONT, needhdr);
390:
1.50 art 391: mib[0] = CTL_KERN;
392: mib[1] = KERN_CLOCKRATE;
393: size = sizeof(clkinfo);
394: if (sysctl(mib, 2, &clkinfo, &size, NULL, 0) < 0) {
1.56 angelos 395: warn("could not read kern.clockrate");
1.50 art 396: return;
397: }
398: hz = clkinfo.stathz;
1.1 deraadt 399:
400: for (hdrcnt = 1;;) {
1.6 tholo 401: /* Read new disk statistics */
402: dkreadstats();
1.73 tdeval 403: if (!--hdrcnt || last.dk_ndrive != cur.dk_ndrive)
404: printhdr();
1.56 angelos 405: if (nlistf == NULL && memf == NULL) {
406: size = sizeof(struct uvmexp);
1.52 angelos 407: mib[0] = CTL_VM;
408: mib[1] = VM_UVMEXP;
409: if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
1.56 angelos 410: warn("could not get vm.uvmexp");
411: bzero(&uvmexp, sizeof(struct uvmexp));
1.52 angelos 412: }
1.56 angelos 413: } else {
414: kread(X_UVMEXP, &uvmexp, sizeof(struct uvmexp));
1.52 angelos 415: }
1.1 deraadt 416: size = sizeof(total);
417: mib[0] = CTL_VM;
418: mib[1] = VM_METER;
419: if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
1.56 angelos 420: warn("could not read vm.vmmeter");
1.1 deraadt 421: bzero(&total, sizeof(total));
422: }
1.22 millert 423: (void)printf("%2u%2u%2u",
1.1 deraadt 424: total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
1.29 art 425: #define rate(x) (((x) + halfuptime) / uptime) /* round */
426: #define pgtok(a) ((a) * ((int)uvmexp.pagesize >> 10))
1.35 hugh 427: (void)printf("%7u%7u ",
1.1 deraadt 428: pgtok(total.t_avm), pgtok(total.t_free));
1.64 deraadt 429: (void)printf("%5u ", rate(uvmexp.faults - ouvmexp.faults));
1.29 art 430: (void)printf("%3u ", rate(uvmexp.pdreact - ouvmexp.pdreact));
431: (void)printf("%3u ", rate(uvmexp.pageins - ouvmexp.pageins));
432: (void)printf("%3u %3u ",
433: rate(uvmexp.pdpageouts - ouvmexp.pdpageouts), 0);
434: (void)printf("%3u ", rate(uvmexp.pdscans - ouvmexp.pdscans));
435: dkstats();
1.64 deraadt 436: (void)printf("%4u %5u %4u ",
1.29 art 437: rate(uvmexp.intrs - ouvmexp.intrs),
438: rate(uvmexp.syscalls - ouvmexp.syscalls),
439: rate(uvmexp.swtch - ouvmexp.swtch));
1.1 deraadt 440: cpustats();
441: (void)printf("\n");
442: (void)fflush(stdout);
443: if (reps >= 0 && --reps <= 0)
444: break;
1.29 art 445: ouvmexp = uvmexp;
1.1 deraadt 446: uptime = interval;
447: /*
448: * We round upward to avoid losing low-frequency events
449: * (i.e., >= 1 per interval but < 1 per second).
450: */
1.14 deraadt 451: halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
1.1 deraadt 452: (void)sleep(interval);
453: }
454: }
455:
1.21 millert 456: void
1.72 deraadt 457: printhdr(void)
1.1 deraadt 458: {
1.62 mpech 459: int i;
1.1 deraadt 460:
1.67 ho 461: (void)printf(" procs memory page%*s", 20, "");
1.6 tholo 462: if (ndrives > 0)
1.79 tedu 463: (void)printf("%s %*straps cpu\n",
1.6 tholo 464: ((ndrives > 1) ? "disks" : "disk"),
1.64 deraadt 465: ((ndrives > 1) ? ndrives * 4 - 4 : 0), "");
1.1 deraadt 466: else
1.79 tedu 467: (void)printf("%*s traps cpu\n",
1.6 tholo 468: ndrives * 3, "");
469:
1.64 deraadt 470: (void)printf(" r b w avm fre flt re pi po fr sr ");
1.1 deraadt 471: for (i = 0; i < dk_ndrive; i++)
1.6 tholo 472: if (dk_select[i])
1.67 ho 473: (void)printf("%c%c%c ", dr_name[i][0],
1.64 deraadt 474: dr_name[i][1],
1.1 deraadt 475: dr_name[i][strlen(dr_name[i]) - 1]);
1.79 tedu 476: (void)printf(" int sys cs us sy id\n");
1.1 deraadt 477: hdrcnt = winlines - 2;
478: }
479:
480: /*
481: * Force a header to be prepended to the next output.
482: */
483: void
1.78 deraadt 484: needhdr(int signo)
1.1 deraadt 485: {
486:
487: hdrcnt = 1;
488: }
489:
490: void
1.72 deraadt 491: dotimes(void)
1.1 deraadt 492: {
493: u_int pgintime, rectime;
1.52 angelos 494: int mib[2];
495: size_t size;
1.1 deraadt 496:
1.56 angelos 497: /* XXX Why are these set to 0 ? This doesn't look right. */
1.12 tholo 498: pgintime = 0;
499: rectime = 0;
1.56 angelos 500:
501: if (nlistf == NULL && memf == NULL) {
502: size = sizeof(struct uvmexp);
1.52 angelos 503: mib[0] = CTL_VM;
504: mib[1] = VM_UVMEXP;
505: if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
1.56 angelos 506: warn("could not read vm.uvmexp");
507: bzero(&uvmexp, sizeof(struct uvmexp));
1.52 angelos 508: }
1.56 angelos 509: } else {
510: kread(X_UVMEXP, &uvmexp, sizeof(struct uvmexp));
1.52 angelos 511: }
512:
1.29 art 513: (void)printf("%u reactivates, %u total time (usec)\n",
514: uvmexp.pdreact, rectime);
515: (void)printf("average: %u usec / reclaim\n", rectime / uvmexp.pdreact);
516: (void)printf("\n");
517: (void)printf("%u page ins, %u total time (msec)\n",
518: uvmexp.pageins, pgintime / 10);
519: (void)printf("average: %8.1f msec / page in\n",
520: pgintime / (uvmexp.pageins * 10.0));
1.1 deraadt 521: }
522:
1.21 millert 523: int
1.72 deraadt 524: pct(long top, long bot)
1.1 deraadt 525: {
526: long ans;
527:
528: if (bot == 0)
529: return(0);
530: ans = (quad_t)top * 100 / bot;
531: return (ans);
532: }
533:
534: #define PCT(top, bot) pct((long)(top), (long)(bot))
535:
536: void
1.72 deraadt 537: dosum(void)
1.1 deraadt 538: {
539: struct nchstats nchstats;
540: long nchtotal;
1.52 angelos 541: size_t size;
542: int mib[2], nselcoll;
1.1 deraadt 543:
1.56 angelos 544: if (nlistf == NULL && memf == NULL) {
545: size = sizeof(struct uvmexp);
1.52 angelos 546: mib[0] = CTL_VM;
547: mib[1] = VM_UVMEXP;
548: if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
1.56 angelos 549: warn("could not read vm.uvmexp");
550: bzero(&uvmexp, sizeof(struct uvmexp));
1.52 angelos 551: }
1.56 angelos 552: } else {
553: kread(X_UVMEXP, &uvmexp, sizeof(struct uvmexp));
1.52 angelos 554: }
555:
1.32 art 556: /* vm_page constants */
1.35 hugh 557: (void)printf("%11u bytes per page\n", uvmexp.pagesize);
1.32 art 558:
559: /* vm_page counters */
1.35 hugh 560: (void)printf("%11u pages managed\n", uvmexp.npages);
561: (void)printf("%11u pages free\n", uvmexp.free);
562: (void)printf("%11u pages active\n", uvmexp.active);
563: (void)printf("%11u pages inactive\n", uvmexp.inactive);
564: (void)printf("%11u pages being paged out\n", uvmexp.paging);
565: (void)printf("%11u pages wired\n", uvmexp.wired);
1.71 art 566: (void)printf("%11u pages zeroed\n", uvmexp.zeropages);
1.35 hugh 567: (void)printf("%11u pages reserved for pagedaemon\n",
1.48 art 568: uvmexp.reserve_pagedaemon);
1.35 hugh 569: (void)printf("%11u pages reserved for kernel\n",
1.48 art 570: uvmexp.reserve_kernel);
1.32 art 571:
572: /* swap */
1.35 hugh 573: (void)printf("%11u swap pages\n", uvmexp.swpages);
574: (void)printf("%11u swap pages in use\n", uvmexp.swpginuse);
575: (void)printf("%11u total anon's in system\n", uvmexp.nanon);
576: (void)printf("%11u free anon's\n", uvmexp.nfreeanon);
1.32 art 577:
578: /* stat counters */
1.35 hugh 579: (void)printf("%11u page faults\n", uvmexp.faults);
580: (void)printf("%11u traps\n", uvmexp.traps);
581: (void)printf("%11u interrupts\n", uvmexp.intrs);
582: (void)printf("%11u cpu context switches\n", uvmexp.swtch);
583: (void)printf("%11u software interrupts\n", uvmexp.softs);
584: (void)printf("%11u syscalls\n", uvmexp.syscalls);
585: (void)printf("%11u pagein operations\n", uvmexp.pageins);
586: (void)printf("%11u swap ins\n", uvmexp.swapins);
587: (void)printf("%11u swap outs\n", uvmexp.swapouts);
588: (void)printf("%11u forks\n", uvmexp.forks);
589: (void)printf("%11u forks where vmspace is shared\n",
1.48 art 590: uvmexp.forks_sharevm);
1.32 art 591:
592: /* daemon counters */
1.64 deraadt 593: (void)printf("%11u number of times the pagedaemon woke up\n",
1.48 art 594: uvmexp.pdwoke);
1.35 hugh 595: (void)printf("%11u revolutions of the clock hand\n", uvmexp.pdrevs);
596: (void)printf("%11u pages freed by pagedaemon\n", uvmexp.pdfreed);
597: (void)printf("%11u pages scanned by pagedaemon\n", uvmexp.pdscans);
598: (void)printf("%11u pages reactivated by pagedaemon\n", uvmexp.pdreact);
599: (void)printf("%11u busy pages found by pagedaemon\n", uvmexp.pdbusy);
1.29 art 600:
1.56 angelos 601: if (nlistf == NULL && memf == NULL) {
1.52 angelos 602: size = sizeof(nchstats);
603: mib[0] = CTL_KERN;
604: mib[1] = KERN_NCHSTATS;
605: if (sysctl(mib, 2, &nchstats, &size, NULL, 0) < 0) {
1.56 angelos 606: warn("could not read kern.nchstats");
1.52 angelos 607: bzero(&nchstats, sizeof(nchstats));
608: }
1.56 angelos 609: } else {
610: kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
1.52 angelos 611: }
612:
1.1 deraadt 613: nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
614: nchstats.ncs_badhits + nchstats.ncs_falsehits +
615: nchstats.ncs_miss + nchstats.ncs_long;
1.35 hugh 616: (void)printf("%11ld total name lookups\n", nchtotal);
1.52 angelos 617: (void)printf("%11s cache hits (%d%% pos + %d%% neg) system %d%% "
618: "per-directory\n",
1.1 deraadt 619: "", PCT(nchstats.ncs_goodhits, nchtotal),
620: PCT(nchstats.ncs_neghits, nchtotal),
621: PCT(nchstats.ncs_pass2, nchtotal));
1.35 hugh 622: (void)printf("%11s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
1.1 deraadt 623: PCT(nchstats.ncs_badhits, nchtotal),
624: PCT(nchstats.ncs_falsehits, nchtotal),
625: PCT(nchstats.ncs_long, nchtotal));
1.52 angelos 626:
1.56 angelos 627: if (nlistf == NULL && memf == NULL) {
1.52 angelos 628: size = sizeof(nselcoll);
629: mib[0] = CTL_KERN;
630: mib[1] = KERN_NSELCOLL;
631: if (sysctl(mib, 2, &nselcoll, &size, NULL, 0) < 0) {
1.56 angelos 632: warn("could not read kern.nselcoll");
1.52 angelos 633: nselcoll = 0;
634: }
1.56 angelos 635: } else {
636: kread(X_NSELCOLL, &nselcoll, sizeof(nselcoll));
1.52 angelos 637: }
1.50 art 638: (void)printf("%11d select collisions\n", nselcoll);
1.1 deraadt 639: }
640:
641: void
1.72 deraadt 642: doforkst(void)
1.1 deraadt 643: {
644: struct forkstat fks;
1.52 angelos 645: size_t size;
646: int mib[2];
647:
1.56 angelos 648: if (nlistf == NULL && memf == NULL) {
1.52 angelos 649: size = sizeof(struct forkstat);
650: mib[0] = CTL_KERN;
651: mib[1] = KERN_FORKSTAT;
652: if (sysctl(mib, 2, &fks, &size, NULL, 0) < 0) {
1.56 angelos 653: warn("could not read kern.forkstat");
1.52 angelos 654: bzero(&fks, sizeof(struct forkstat));
655: }
1.56 angelos 656: } else {
657: kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
1.52 angelos 658: }
1.1 deraadt 659:
660: (void)printf("%d forks, %d pages, average %.2f\n",
661: fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
662: (void)printf("%d vforks, %d pages, average %.2f\n",
1.72 deraadt 663: fks.cntvfork, fks.sizvfork,
664: (double)fks.sizvfork / (fks.cntvfork ? fks.cntvfork : 1));
1.12 tholo 665: (void)printf("%d rforks, %d pages, average %.2f\n",
1.72 deraadt 666: fks.cntrfork, fks.sizrfork,
667: (double)fks.sizrfork / (fks.cntrfork ? fks.cntrfork : 1));
1.36 niklas 668: (void)printf("%d kthread creations, %d pages, average %.2f\n",
1.72 deraadt 669: fks.cntkthread, fks.sizkthread,
670: (double)fks.sizkthread / (fks.cntkthread ? fks.cntkthread : 1));
1.1 deraadt 671: }
672:
673: void
1.72 deraadt 674: dkstats(void)
1.1 deraadt 675: {
1.62 mpech 676: int dn, state;
1.1 deraadt 677: double etime;
678:
1.6 tholo 679: /* Calculate disk stat deltas. */
680: dkswap();
1.1 deraadt 681: etime = 0;
682: for (state = 0; state < CPUSTATES; ++state) {
1.6 tholo 683: etime += cur.cp_time[state];
1.1 deraadt 684: }
685: if (etime == 0)
686: etime = 1;
687: etime /= hz;
1.84 deraadt 688: etime /= ncpu;
1.1 deraadt 689: for (dn = 0; dn < dk_ndrive; ++dn) {
1.6 tholo 690: if (!dk_select[dn])
1.1 deraadt 691: continue;
1.82 tedu 692: (void)printf("%3.0f ",
693: (cur.dk_rxfer[dn] + cur.dk_rxfer[dn]) / etime);
1.1 deraadt 694: }
695: }
696:
697: void
1.72 deraadt 698: cpustats(void)
1.1 deraadt 699: {
1.62 mpech 700: int state;
1.1 deraadt 701: double pct, total;
702:
703: total = 0;
704: for (state = 0; state < CPUSTATES; ++state)
1.6 tholo 705: total += cur.cp_time[state];
1.1 deraadt 706: if (total)
707: pct = 100 / total;
708: else
709: pct = 0;
1.6 tholo 710: (void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct);
711: (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct);
712: (void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
1.1 deraadt 713: }
714:
1.53 deraadt 715: #if defined(__i386__)
1.12 tholo 716: /* To get struct intrhand */
1.13 tholo 717: #define _KERNEL
1.12 tholo 718: #include <machine/psl.h>
1.56 angelos 719: #include <machine/cpu.h>
1.13 tholo 720: #undef _KERNEL
1.12 tholo 721: void
1.72 deraadt 722: dointr(void)
1.12 tholo 723: {
724: struct intrhand *intrhand[16], *ihp, ih;
1.83 deraadt 725: struct intrhand *apicintrhand[256];
1.56 angelos 726: u_long inttotal = 0;
1.19 deraadt 727: time_t uptime;
1.50 art 728: u_long intrstray[16];
1.34 deraadt 729: char iname[17], fname[31];
1.58 pvalchev 730: int i;
1.12 tholo 731:
732: iname[16] = '\0';
733: uptime = getuptime();
734:
1.27 alex 735: (void)printf("interrupt total rate\n");
1.56 angelos 736:
1.85 deraadt 737: kread(X_INTRHAND, intrhand, sizeof(intrhand));
738: kread(X_INTRSTRAY, intrstray, sizeof(intrstray));
739:
740: for (i = 0; i < 16; i++) {
741: ihp = intrhand[i];
742: while (ihp) {
743: if (kvm_read(kd, (u_long)ihp, &ih,
744: sizeof(ih)) != sizeof(ih))
745: errx(1, "vmstat: ih: %s",
746: kvm_geterr(kd));
747: if (kvm_read(kd, (u_long)ih.ih_what, iname,
748: 16) != 16)
749: errx(1, "vmstat: ih_what: %s",
750: kvm_geterr(kd));
751: snprintf(fname, sizeof fname, "irq%d/%s", i,
752: iname);
753: printf("%-16.16s %10lu %8lu\n", fname,
754: ih.ih_count, ih.ih_count / uptime);
755: inttotal += ih.ih_count;
756: ihp = ih.ih_next;
1.83 deraadt 757: }
758: }
1.85 deraadt 759: if (namelist[X_APICINTRHAND].n_value) {
1.83 deraadt 760: kread(X_APICINTRHAND, apicintrhand, sizeof(apicintrhand));
761:
762: for (i = 0; i < 256; i++) {
763: ihp = apicintrhand[i];
764: while (ihp) {
765: if (kvm_read(kd, (u_long)ihp, &ih,
766: sizeof(ih)) != sizeof(ih))
767: errx(1, "vmstat: ih: %s",
768: kvm_geterr(kd));
769: if (kvm_read(kd, (u_long)ih.ih_what, iname,
770: 16) != 16)
771: errx(1, "vmstat: ih_what: %s",
772: kvm_geterr(kd));
773: snprintf(fname, sizeof fname, "irq%d/%s", i,
774: iname);
775: printf("%-16.16s %10lu %8lu\n", fname,
776: ih.ih_count, ih.ih_count / uptime);
1.56 angelos 777: inttotal += ih.ih_count;
778: ihp = ih.ih_next;
779: }
1.12 tholo 780: }
781: }
1.56 angelos 782:
1.12 tholo 783: for (i = 0; i < 16; i++)
784: if (intrstray[i]) {
1.50 art 785: printf("Stray irq %-2d %10lu %8lu\n",
1.53 deraadt 786: i, intrstray[i], intrstray[i] / uptime);
1.12 tholo 787: inttotal += intrstray[i];
788: }
1.50 art 789: printf("Total %10lu %8lu\n", inttotal, inttotal / uptime);
1.1 deraadt 790: }
791: #else
1.74 art 792: static void dointr_sysctl(void);
793: static void dointr_kvm(void);
794:
1.1 deraadt 795: void
1.72 deraadt 796: dointr(void)
1.74 art 797: {
798: if (nlistf == NULL && memf == NULL)
799: dointr_sysctl();
800: else
801: dointr_kvm();
802: }
803:
804: static void
805: dointr_sysctl(void)
806: {
807: struct evcntlist allevents;
808: struct evcnt evcnt, *evptr;
809: struct device dev;
810:
811: time_t uptime;
812: long inttotal;
813: int nintr;
814: char intrname[128];
815: int mib[4];
816: size_t siz;
817: int i;
818:
819: uptime = getuptime();
820:
821: mib[0] = CTL_KERN;
822: mib[1] = KERN_INTRCNT;
823: mib[2] = KERN_INTRCNT_NUM;
824: siz = sizeof(nintr);
825: if (sysctl(mib, 3, &nintr, &siz, NULL, 0) < 0) {
826: warnx("could not read kern.intrcnt.nintrcnt");
827: return;
828: }
829:
830: inttotal = 0;
831: for (i = 0; i < nintr; i++) {
832: int cnt;
833:
834: mib[0] = CTL_KERN;
835: mib[1] = KERN_INTRCNT;
836: mib[2] = KERN_INTRCNT_NAME;
837: mib[3] = i;
838: siz = sizeof(intrname);
839: if (sysctl(mib, 4, intrname, &siz, NULL, 0) < 0) {
840: warnx("could not read kern.intrcnt.name.%d", i);
841: return ;
842: }
843:
844: mib[0] = CTL_KERN;
845: mib[1] = KERN_INTRCNT;
846: mib[2] = KERN_INTRCNT_CNT;
847: mib[3] = i;
848: siz = sizeof(cnt);
849: if (sysctl(mib, 4, &cnt, &siz, NULL, 0) < 0) {
1.75 grange 850: warnx("could not read kern.intrcnt.cnt.%d", i);
1.74 art 851: return ;
852: }
853: if (cnt)
1.81 otto 854: (void)printf("%-14s %12d %8ld\n", intrname,
855: cnt, (long)cnt / uptime);
1.74 art 856: inttotal += cnt;
857: }
858:
859: kread(X_ALLEVENTS, &allevents, sizeof allevents);
860: evptr = allevents.tqh_first;
861: while (evptr) {
862: if (kvm_read(kd, (long)evptr, (void *)&evcnt,
863: sizeof evcnt) != sizeof evcnt)
864: errx(1, "event chain trashed: %s", kvm_geterr(kd));
865: if (strcmp(evcnt.ev_name, "intr") == 0) {
866: if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev,
867: sizeof dev) != sizeof dev)
868: errx(1, "event chain trashed: %s", kvm_geterr(kd));
869: if (evcnt.ev_count)
870: (void)printf("%-14s %12d %8ld\n", dev.dv_xname,
871: evcnt.ev_count, (long)(evcnt.ev_count / uptime));
872: inttotal += evcnt.ev_count++;
873: }
874: evptr = evcnt.ev_list.tqe_next;
875: }
876: (void)printf("Total %12ld %8ld\n", inttotal, inttotal / uptime);
877: }
878:
879: static void
880: dointr_kvm(void)
1.1 deraadt 881: {
1.62 mpech 882: long *intrcnt, inttotal;
1.19 deraadt 883: time_t uptime;
1.62 mpech 884: int nintr, inamlen;
885: char *intrname;
1.9 deraadt 886: struct evcntlist allevents;
887: struct evcnt evcnt, *evptr;
1.1 deraadt 888: struct device dev;
889:
890: uptime = getuptime();
891: nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
892: inamlen =
893: namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
894: intrcnt = malloc((size_t)nintr);
895: intrname = malloc((size_t)inamlen);
1.50 art 896: if (intrcnt == NULL || intrname == NULL)
897: err(1, "malloc");
1.1 deraadt 898: kread(X_INTRCNT, intrcnt, (size_t)nintr);
899: kread(X_INTRNAMES, intrname, (size_t)inamlen);
1.27 alex 900: (void)printf("interrupt total rate\n");
1.1 deraadt 901: inttotal = 0;
902: nintr /= sizeof(long);
903: while (--nintr >= 0) {
904: if (*intrcnt)
1.27 alex 905: (void)printf("%-14s %12ld %8ld\n", intrname,
1.1 deraadt 906: *intrcnt, *intrcnt / uptime);
907: intrname += strlen(intrname) + 1;
908: inttotal += *intrcnt++;
909: }
910: kread(X_ALLEVENTS, &allevents, sizeof allevents);
1.9 deraadt 911: evptr = allevents.tqh_first;
912: while (evptr) {
913: if (kvm_read(kd, (long)evptr, (void *)&evcnt,
1.50 art 914: sizeof evcnt) != sizeof evcnt)
915: errx(1, "event chain trashed: %s", kvm_geterr(kd));
1.1 deraadt 916: if (strcmp(evcnt.ev_name, "intr") == 0) {
917: if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev,
1.50 art 918: sizeof dev) != sizeof dev)
919: errx(1, "event chain trashed: %s", kvm_geterr(kd));
1.1 deraadt 920: if (evcnt.ev_count)
1.33 art 921: (void)printf("%-14s %12d %8ld\n", dev.dv_xname,
922: evcnt.ev_count, (long)(evcnt.ev_count / uptime));
1.1 deraadt 923: inttotal += evcnt.ev_count++;
924: }
1.9 deraadt 925: evptr = evcnt.ev_list.tqe_next;
1.1 deraadt 926: }
1.27 alex 927: (void)printf("Total %12ld %8ld\n", inttotal, inttotal / uptime);
1.1 deraadt 928: }
929: #endif
930:
931: /*
932: * These names are defined in <sys/malloc.h>.
933: */
934: char *kmemnames[] = INITKMEMNAMES;
935:
936: void
1.72 deraadt 937: domem(void)
1.1 deraadt 938: {
1.62 mpech 939: struct kmembuckets *kp;
940: struct kmemstats *ks;
941: int i, j;
1.1 deraadt 942: int len, size, first;
1.50 art 943: u_long totuse = 0, totfree = 0;
944: quad_t totreq = 0;
1.1 deraadt 945: char *name;
946: struct kmemstats kmemstats[M_LAST];
947: struct kmembuckets buckets[MINBUCKET + 16];
1.50 art 948: int mib[4];
949: size_t siz;
950: char buf[BUFSIZ], *bufp, *ap;
951:
952: if (memf == NULL && nlistf == NULL) {
1.53 deraadt 953: mib[0] = CTL_KERN;
1.50 art 954: mib[1] = KERN_MALLOCSTATS;
955: mib[2] = KERN_MALLOC_BUCKETS;
956: siz = sizeof(buf);
957: if (sysctl(mib, 3, buf, &siz, NULL, 0) < 0) {
1.56 angelos 958: warnx("could not read kern.malloc.buckets");
1.50 art 959: return;
960: }
961:
962: bufp = buf;
963: mib[2] = KERN_MALLOC_BUCKET;
964: siz = sizeof(struct kmembuckets);
965: i = 0;
966: while ((ap = strsep(&bufp, ",")) != NULL) {
1.53 deraadt 967: mib[3] = atoi(ap);
1.50 art 968:
969: if (sysctl(mib, 4, &buckets[MINBUCKET + i], &siz,
1.53 deraadt 970: NULL, 0) < 0) {
1.56 angelos 971: warn("could not read kern.malloc.bucket.%d", mib[3]);
1.50 art 972: return;
973: }
974: i++;
975: }
976: } else {
1.53 deraadt 977: kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
1.50 art 978: }
1.1 deraadt 979:
1.18 kstailey 980: for (first = 1, i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16;
981: i++, kp++) {
1.65 art 982: if (kp->kb_calls == 0 && !verbose)
1.1 deraadt 983: continue;
1.18 kstailey 984: if (first) {
985: (void)printf("Memory statistics by bucket size\n");
986: (void)printf(
1.50 art 987: " Size In Use Free Requests HighWater Couldfree\n");
1.18 kstailey 988: first = 0;
989: }
1.1 deraadt 990: size = 1 << i;
1.60 art 991: (void)printf("%8d %8llu %6llu %18llu %7llu %10llu\n", size,
992: (unsigned long long)(kp->kb_total - kp->kb_totalfree),
993: (unsigned long long)kp->kb_totalfree,
994: (unsigned long long)kp->kb_calls,
995: (unsigned long long)kp->kb_highwat,
996: (unsigned long long)kp->kb_couldfree);
1.1 deraadt 997: totfree += size * kp->kb_totalfree;
1.18 kstailey 998: }
999:
1000: /*
1001: * If kmem statistics are not being gathered by the kernel,
1002: * first will still be 1.
1003: */
1004: if (first) {
1005: printf(
1006: "Kmem statistics are not being gathered by the kernel.\n");
1007: return;
1.1 deraadt 1008: }
1009:
1.52 angelos 1010: if (memf == NULL && nlistf == NULL) {
1011: bzero(kmemstats, sizeof(kmemstats));
1012: for (i = 0; i < M_LAST; i++) {
1.53 deraadt 1013: mib[0] = CTL_KERN;
1.52 angelos 1014: mib[1] = KERN_MALLOCSTATS;
1015: mib[2] = KERN_MALLOC_KMEMSTATS;
1016: mib[3] = i;
1017: siz = sizeof(struct kmemstats);
1018:
1019: /*
1020: * Skip errors -- these are presumed to be unallocated
1021: * entries.
1022: */
1023: if (sysctl(mib, 4, &kmemstats[i], &siz, NULL, 0) < 0)
1024: continue;
1025: }
1026: } else {
1027: kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
1028: }
1029:
1.1 deraadt 1030: (void)printf("\nMemory usage type by bucket size\n");
1031: (void)printf(" Size Type(s)\n");
1032: kp = &buckets[MINBUCKET];
1033: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
1034: if (kp->kb_calls == 0)
1035: continue;
1036: first = 1;
1037: len = 8;
1038: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
1039: if (ks->ks_calls == 0)
1040: continue;
1041: if ((ks->ks_size & j) == 0)
1042: continue;
1043: name = kmemnames[i] ? kmemnames[i] : "undefined";
1044: len += 2 + strlen(name);
1045: if (first)
1046: printf("%8d %s", j, name);
1047: else
1048: printf(",");
1049: if (len >= 80) {
1050: printf("\n\t ");
1051: len = 10 + strlen(name);
1052: }
1053: if (!first)
1054: printf(" %s", name);
1055: first = 0;
1056: }
1057: printf("\n");
1058: }
1059:
1060: (void)printf(
1.26 deraadt 1061: "\nMemory statistics by type Type Kern\n");
1.1 deraadt 1062: (void)printf(
1.26 deraadt 1063: " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
1.1 deraadt 1064: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
1065: if (ks->ks_calls == 0)
1066: continue;
1.24 mickey 1067: (void)printf("%14s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
1.1 deraadt 1068: kmemnames[i] ? kmemnames[i] : "undefined",
1069: ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
1070: (ks->ks_maxused + 1023) / 1024,
1071: (ks->ks_limit + 1023) / 1024, ks->ks_calls,
1072: ks->ks_limblocks, ks->ks_mapblocks);
1073: first = 1;
1074: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
1075: if ((ks->ks_size & j) == 0)
1076: continue;
1077: if (first)
1078: printf(" %d", j);
1079: else
1080: printf(",%d", j);
1081: first = 0;
1082: }
1083: printf("\n");
1084: totuse += ks->ks_memuse;
1085: totreq += ks->ks_calls;
1086: }
1087: (void)printf("\nMemory Totals: In Use Free Requests\n");
1.50 art 1088: (void)printf(" %7luK %6luK %8qu\n",
1.1 deraadt 1089: (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
1090: }
1091:
1.54 art 1092: static void
1093: print_pool(struct pool *pp, char *name)
1094: {
1095: static int first = 1;
1096: int ovflw;
1097: char maxp[32];
1098:
1099: if (first) {
1100: (void)printf("Memory resource pool statistics\n");
1101: (void)printf(
1102: "%-11s%5s%9s%5s%9s%6s%6s%6s%6s%6s%6s%5s\n",
1103: "Name",
1104: "Size",
1105: "Requests",
1106: "Fail",
1107: "Releases",
1108: "Pgreq",
1109: "Pgrel",
1110: "Npage",
1111: "Hiwat",
1112: "Minpg",
1113: "Maxpg",
1114: "Idle");
1115: first = 0;
1116: }
1.65 art 1117:
1118: /* Skip unused pools unless verbose output. */
1119: if (pp->pr_nget == 0 && !verbose)
1120: return;
1121:
1.54 art 1122: if (pp->pr_maxpages == UINT_MAX)
1.69 deraadt 1123: snprintf(maxp, sizeof maxp, "inf");
1.54 art 1124: else
1.69 deraadt 1125: snprintf(maxp, sizeof maxp, "%u", pp->pr_maxpages);
1.54 art 1126: /*
1127: * Print single word. `ovflow' is number of characters didn't fit
1128: * on the last word. `fmt' is a format string to print this word.
1129: * It must contain asterisk for field width. `width' is a width
1130: * occupied by this word. `fixed' is a number of constant chars in
1131: * `fmt'. `val' is a value to be printed using format string `fmt'.
1132: */
1133: #define PRWORD(ovflw, fmt, width, fixed, val) do { \
1134: (ovflw) += printf((fmt), \
1135: (width) - (fixed) - (ovflw) > 0 ? \
1136: (width) - (fixed) - (ovflw) : 0, \
1137: (val)) - (width); \
1138: if ((ovflw) < 0) \
1139: (ovflw) = 0; \
1140: } while (/* CONSTCOND */0)
1141:
1142: ovflw = 0;
1143: PRWORD(ovflw, "%-*s", 11, 0, name);
1144: PRWORD(ovflw, " %*u", 5, 1, pp->pr_size);
1145: PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nget);
1146: PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nfail);
1147: PRWORD(ovflw, " %*lu", 9, 1, pp->pr_nput);
1148: PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagealloc);
1149: PRWORD(ovflw, " %*lu", 6, 1, pp->pr_npagefree);
1150: PRWORD(ovflw, " %*d", 6, 1, pp->pr_npages);
1151: PRWORD(ovflw, " %*d", 6, 1, pp->pr_hiwat);
1152: PRWORD(ovflw, " %*d", 6, 1, pp->pr_minpages);
1153: PRWORD(ovflw, " %*s", 6, 1, maxp);
1154: PRWORD(ovflw, " %*lu\n", 5, 1, pp->pr_nidle);
1155: }
1156:
1.55 art 1157: static void dopool_kvm(void);
1158: static void dopool_sysctl(void);
1159:
1.48 art 1160: void
1161: dopool(void)
1162: {
1.55 art 1163: if (nlistf == NULL && memf == NULL)
1164: dopool_sysctl();
1165: else
1166: dopool_kvm();
1167: }
1168:
1169: void
1170: dopool_sysctl(void)
1171: {
1.63 art 1172: long total = 0, inuse = 0;
1.55 art 1173: struct pool pool;
1174: size_t size;
1175: int mib[4];
1176: int npools, i;
1177:
1178: mib[0] = CTL_KERN;
1179: mib[1] = KERN_POOL;
1180: mib[2] = KERN_POOL_NPOOLS;
1181: size = sizeof(npools);
1182: if (sysctl(mib, 3, &npools, &size, NULL, 0) < 0) {
1183: printf("Can't figure out number of pools in kernel: %s\n",
1184: strerror(errno));
1185: return;
1186: }
1187:
1188: for (i = 1; npools; i++) {
1189: char name[32];
1190:
1191: mib[0] = CTL_KERN;
1192: mib[1] = KERN_POOL;
1193: mib[2] = KERN_POOL_POOL;
1194: mib[3] = i;
1195: size = sizeof(struct pool);
1196: if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) {
1197: if (errno == ENOENT)
1198: continue;
1199: printf("error getting pool: %s\n", strerror(errno));
1200: return;
1201: }
1202: npools--;
1203: mib[2] = KERN_POOL_NAME;
1204: size = sizeof(name);
1205: if (sysctl(mib, 4, &name, &size, NULL, 0) < 0) {
1206: printf("error getting pool name: %s\n",
1207: strerror(errno));
1208: return;
1209: }
1210: print_pool(&pool, name);
1.63 art 1211:
1212: inuse += (pool.pr_nget - pool.pr_nput) * pool.pr_size;
1213: total += pool.pr_npages * getpagesize(); /* XXX */
1.55 art 1214: }
1.63 art 1215:
1216: inuse /= 1024;
1217: total /= 1024;
1218: printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n",
1219: inuse, total, (double)(100 * inuse) / total);
1.55 art 1220: }
1221:
1222: void
1223: dopool_kvm(void)
1224: {
1.48 art 1225: long addr;
1226: long total = 0, inuse = 0;
1227: TAILQ_HEAD(,pool) pool_head;
1228: struct pool pool, *pp = &pool;
1229:
1230: kread(X_POOLHEAD, &pool_head, sizeof(pool_head));
1231: addr = (long)TAILQ_FIRST(&pool_head);
1232:
1.55 art 1233: while (addr != 0) {
1.54 art 1234: char name[32];
1.56 angelos 1235:
1.48 art 1236: if (kvm_read(kd, addr, (void *)pp, sizeof *pp) != sizeof *pp) {
1237: (void)fprintf(stderr,
1238: "vmstat: pool chain trashed: %s\n",
1239: kvm_geterr(kd));
1240: exit(1);
1241: }
1242: if (kvm_read(kd, (long)pp->pr_wchan, name, sizeof name) < 0) {
1243: (void)fprintf(stderr,
1244: "vmstat: pool name trashed: %s\n",
1245: kvm_geterr(kd));
1246: exit(1);
1247: }
1.56 angelos 1248:
1.48 art 1249: name[31] = '\0';
1250:
1.54 art 1251: print_pool(pp, name);
1.48 art 1252:
1253: inuse += (pp->pr_nget - pp->pr_nput) * pp->pr_size;
1.63 art 1254: total += pp->pr_npages * getpagesize(); /* XXX */
1.56 angelos 1255:
1.48 art 1256: addr = (long)TAILQ_NEXT(pp, pr_poollist);
1257: }
1258:
1259: inuse /= 1024;
1260: total /= 1024;
1261: printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n",
1262: inuse, total, (double)(100 * inuse) / total);
1263: }
1264:
1.1 deraadt 1265: /*
1266: * kread reads something from the kernel, given its nlist index.
1267: */
1268: void
1.72 deraadt 1269: kread(int nlx, void *addr, size_t size)
1.1 deraadt 1270: {
1271: char *sym;
1272:
1273: if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
1274: sym = namelist[nlx].n_name;
1275: if (*sym == '_')
1276: ++sym;
1.50 art 1277: errx(1, "symbol %s not defined", sym);
1.1 deraadt 1278: }
1279: if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
1280: sym = namelist[nlx].n_name;
1281: if (*sym == '_')
1282: ++sym;
1.50 art 1283: errx(1, "%s: %s", sym, kvm_geterr(kd));
1.1 deraadt 1284: }
1285: }
1286:
1287: void
1.72 deraadt 1288: usage(void)
1.1 deraadt 1289: {
1.50 art 1290: (void)fprintf(stderr, "usage: %s [-fimst] [-c count] [-M core] "
1291: "[-N system] [-w wait] [disks]\n", __progname);
1.1 deraadt 1292: exit(1);
1293: }