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