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