Annotation of src/usr.bin/vmstat/vmstat.c, Revision 1.20
1.11 deraadt 1: /* $NetBSD: vmstat.c,v 1.29.4.1 1996/06/05 00:21:05 cgd Exp $ */
1.20 ! deraadt 2: /* $OpenBSD: vmstat.c,v 1.19 1997/06/30 07:03:06 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.
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:
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>
63: #include <vm/vm.h>
64: #include <time.h>
65: #include <nlist.h>
66: #include <kvm.h>
67: #include <errno.h>
68: #include <unistd.h>
69: #include <signal.h>
70: #include <stdio.h>
71: #include <ctype.h>
72: #include <stdlib.h>
73: #include <string.h>
74: #include <paths.h>
75: #include <limits.h>
1.6 tholo 76: #include "dkstats.h"
1.1 deraadt 77:
78: #define NEWVM /* XXX till old has been updated or purged */
79: struct nlist namelist[] = {
80: #define X_CPTIME 0
81: { "_cp_time" },
82: #define X_DK_NDRIVE 1
83: { "_dk_ndrive" },
84: #define X_SUM 2
85: { "_cnt" },
86: #define X_BOOTTIME 3
87: { "_boottime" },
88: #define X_DKXFER 4
89: { "_dk_xfer" },
90: #define X_HZ 5
91: { "_hz" },
92: #define X_STATHZ 6
93: { "_stathz" },
94: #define X_NCHSTATS 7
95: { "_nchstats" },
96: #define X_INTRNAMES 8
97: { "_intrnames" },
98: #define X_EINTRNAMES 9
99: { "_eintrnames" },
100: #define X_INTRCNT 10
101: { "_intrcnt" },
102: #define X_EINTRCNT 11
103: { "_eintrcnt" },
104: #define X_KMEMSTAT 12
105: { "_kmemstats" },
106: #define X_KMEMBUCKETS 13
107: { "_bucket" },
108: #define X_ALLEVENTS 14
109: { "_allevents" },
1.12 tholo 110: #define X_FORKSTAT 15
111: { "_forkstat" },
1.1 deraadt 112: #ifdef notdef
1.12 tholo 113: #define X_DEFICIT 16
1.1 deraadt 114: { "_deficit" },
115: #define X_REC 17
116: { "_rectime" },
117: #define X_PGIN 18
118: { "_pgintime" },
119: #define X_XSTATS 19
120: { "_xstats" },
121: #define X_END 20
122: #else
1.12 tholo 123: #define X_END 16
1.1 deraadt 124: #endif
125: #ifdef tahoe
126: #define X_VBDINIT (X_END)
127: { "_vbdinit" },
128: #define X_CKEYSTATS (X_END+1)
129: { "_ckeystats" },
130: #define X_DKEYSTATS (X_END+2)
131: { "_dkeystats" },
132: #endif
133: #if defined(pc532)
134: #define X_IVT (X_END)
135: { "_ivt" },
136: #endif
1.12 tholo 137: #if defined(i386)
138: #define X_INTRHAND (X_END)
139: { "_intrhand" },
140: #define X_INTRSTRAY (X_END+1)
141: { "_intrstray" },
142: #endif
1.1 deraadt 143: { "" },
144: };
145:
1.6 tholo 146: /* Objects defined in dkstats.c */
147: extern struct _disk cur;
1.10 deraadt 148: extern char **dr_name;
149: extern int *dk_select, dk_ndrive;
1.1 deraadt 150:
151: struct vmmeter sum, osum;
1.6 tholo 152: int ndrives;
1.1 deraadt 153:
154: int winlines = 20;
155:
156: kvm_t *kd;
157:
158: #define FORKSTAT 0x01
159: #define INTRSTAT 0x02
160: #define MEMSTAT 0x04
161: #define SUMSTAT 0x08
162: #define TIMESTAT 0x10
163: #define VMSTAT 0x20
164:
1.10 deraadt 165: void cpustats __P((void));
166: void dkstats __P((void));
167: void dointr __P((void));
168: void domem __P((void));
169: void dosum __P((void));
170: void dovmstat __P((u_int, int));
171: void kread __P((int, void *, size_t));
172: void usage __P((void));
173: void dotimes __P((void));
174: void doforkst __P((void));
1.1 deraadt 175:
1.10 deraadt 176: char **choosedrives __P((char **));
177:
178: /* Namelist and memory file names. */
179: char *nlistf, *memf;
1.6 tholo 180:
1.1 deraadt 181: main(argc, argv)
182: register int argc;
183: register char **argv;
184: {
185: extern int optind;
186: extern char *optarg;
187: register int c, todo;
188: u_int interval;
189: int reps;
190: char errbuf[_POSIX2_LINE_MAX];
191:
192: memf = nlistf = NULL;
193: interval = reps = todo = 0;
1.16 millert 194: while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != -1) {
1.1 deraadt 195: switch (c) {
196: case 'c':
197: reps = atoi(optarg);
198: break;
199: case 'f':
200: todo |= FORKSTAT;
201: break;
202: case 'i':
203: todo |= INTRSTAT;
204: break;
205: case 'M':
206: memf = optarg;
207: break;
208: case 'm':
209: todo |= MEMSTAT;
210: break;
211: case 'N':
212: nlistf = optarg;
213: break;
214: case 's':
215: todo |= SUMSTAT;
216: break;
217: case 't':
218: todo |= TIMESTAT;
219: break;
220: case 'w':
221: interval = atoi(optarg);
222: break;
223: case '?':
224: default:
225: usage();
226: }
227: }
228: argc -= optind;
229: argv += optind;
230:
231: if (todo == 0)
232: todo = VMSTAT;
233:
234: /*
235: * Discard setgid privileges if not the running kernel so that bad
236: * guys can't print interesting stuff from kernel memory.
237: */
1.15 tholo 238: if (nlistf != NULL || memf != NULL) {
239: setegid(getgid());
1.1 deraadt 240: setgid(getgid());
1.15 tholo 241: }
1.1 deraadt 242:
243: kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
244: if (kd == 0) {
245: (void)fprintf(stderr,
246: "vmstat: kvm_openfiles: %s\n", errbuf);
247: exit(1);
248: }
249:
250: if ((c = kvm_nlist(kd, namelist)) != 0) {
251: if (c > 0) {
252: (void)fprintf(stderr,
253: "vmstat: undefined symbols:");
254: for (c = 0;
255: c < sizeof(namelist)/sizeof(namelist[0]); c++)
256: if (namelist[c].n_type == 0)
257: fprintf(stderr, " %s",
258: namelist[c].n_name);
259: (void)fputc('\n', stderr);
260: } else
261: (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
262: kvm_geterr(kd));
263: exit(1);
264: }
265:
266: if (todo & VMSTAT) {
267: struct winsize winsize;
268:
1.6 tholo 269: dkinit(0); /* Initialize disk stats, no disks selected. */
270: argv = choosedrives(argv); /* Select disks. */
1.1 deraadt 271: winsize.ws_row = 0;
272: (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
273: if (winsize.ws_row > 0)
274: winlines = winsize.ws_row;
275:
276: }
277:
278: #define BACKWARD_COMPATIBILITY
279: #ifdef BACKWARD_COMPATIBILITY
280: if (*argv) {
281: interval = atoi(*argv);
282: if (*++argv)
283: reps = atoi(*argv);
284: }
285: #endif
286:
287: if (interval) {
288: if (!reps)
289: reps = -1;
290: } else if (reps)
291: interval = 1;
292:
293: if (todo & FORKSTAT)
294: doforkst();
295: if (todo & MEMSTAT)
296: domem();
297: if (todo & SUMSTAT)
298: dosum();
299: if (todo & TIMESTAT)
300: dotimes();
301: if (todo & INTRSTAT)
302: dointr();
303: if (todo & VMSTAT)
304: dovmstat(interval, reps);
305: exit(0);
306: }
307:
308: char **
1.6 tholo 309: choosedrives(argv)
1.1 deraadt 310: char **argv;
311: {
312: register int i;
313: register char **cp;
314: char buf[30];
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: }
336: for (i = 0; i < dk_ndrive && ndrives < 4; 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.1 deraadt 346: getuptime()
347: {
1.11 deraadt 348: static time_t now;
349: static struct timeval boottime;
1.1 deraadt 350: time_t uptime;
351:
1.11 deraadt 352: if (boottime.tv_sec == 0)
1.1 deraadt 353: kread(X_BOOTTIME, &boottime, sizeof(boottime));
354: (void)time(&now);
1.11 deraadt 355: uptime = now - boottime.tv_sec;
1.1 deraadt 356: if (uptime <= 0 || uptime > 60*60*24*365*10) {
357: (void)fprintf(stderr,
358: "vmstat: time makes no sense; namelist must be wrong.\n");
359: exit(1);
360: }
361: return(uptime);
362: }
363:
364: int hz, hdrcnt;
365:
366: void
367: dovmstat(interval, reps)
368: u_int interval;
369: int reps;
370: {
371: struct vmtotal total;
372: time_t uptime, halfuptime;
373: void needhdr();
374: int mib[2];
375: size_t size;
376:
377: uptime = getuptime();
378: halfuptime = uptime / 2;
379: (void)signal(SIGCONT, needhdr);
380:
381: if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
382: kread(X_STATHZ, &hz, sizeof(hz));
383: if (!hz)
384: kread(X_HZ, &hz, sizeof(hz));
385:
386: for (hdrcnt = 1;;) {
387: if (!--hdrcnt)
388: printhdr();
1.6 tholo 389: /* Read new disk statistics */
390: dkreadstats();
1.1 deraadt 391: kread(X_SUM, &sum, sizeof(sum));
392: size = sizeof(total);
393: mib[0] = CTL_VM;
394: mib[1] = VM_METER;
395: if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
396: printf("Can't get kerninfo: %s\n", strerror(errno));
397: bzero(&total, sizeof(total));
398: }
399: (void)printf("%2d%2d%2d",
400: total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
1.6 tholo 401: #define pgtok(a) ((a) * (sum.v_page_size >> 10))
1.1 deraadt 402: #define rate(x) (((x) + halfuptime) / uptime) /* round */
403: (void)printf("%6ld%6ld ",
404: pgtok(total.t_avm), pgtok(total.t_free));
405: #ifdef NEWVM
406: (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults));
407: (void)printf("%3lu ",
408: rate(sum.v_reactivated - osum.v_reactivated));
409: (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins));
410: (void)printf("%3lu %3lu ",
411: rate(sum.v_pageouts - osum.v_pageouts), 0);
412: #else
413: (void)printf("%3lu %2lu ",
414: rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) -
415: (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))),
416: rate(sum.v_xsfrec + sum.v_xifrec -
417: osum.v_xsfrec - osum.v_xifrec));
418: (void)printf("%3lu ",
419: rate(pgtok(sum.v_pgpgin - osum.v_pgpgin)));
420: (void)printf("%3lu %3lu ",
421: rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)),
422: rate(pgtok(sum.v_dfree - osum.v_dfree)));
423: (void)printf("%3d ", pgtok(deficit));
424: #endif
425: (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan));
426: dkstats();
427: (void)printf("%4lu %4lu %3lu ",
428: rate(sum.v_intr - osum.v_intr),
429: rate(sum.v_syscall - osum.v_syscall),
430: rate(sum.v_swtch - osum.v_swtch));
431: cpustats();
432: (void)printf("\n");
433: (void)fflush(stdout);
434: if (reps >= 0 && --reps <= 0)
435: break;
436: osum = sum;
437: uptime = interval;
438: /*
439: * We round upward to avoid losing low-frequency events
440: * (i.e., >= 1 per interval but < 1 per second).
441: */
1.14 deraadt 442: halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
1.1 deraadt 443: (void)sleep(interval);
444: }
445: }
446:
447: printhdr()
448: {
449: register int i;
450:
451: (void)printf(" procs memory page%*s", 20, "");
1.6 tholo 452: if (ndrives > 0)
453: #ifdef NEWVM
454: (void)printf("%s %*sfaults cpu\n",
455: ((ndrives > 1) ? "disks" : "disk"),
456: #else
457: (void)printf("disks %*sfaults cpu\n",
458: #endif
459: ((ndrives > 1) ? ndrives * 3 - 4 : 0), "");
1.1 deraadt 460: else
1.6 tholo 461: #ifdef NEWVM
462: (void)printf("%*s faults cpu\n",
1.1 deraadt 463: #else
1.6 tholo 464: (void)printf("%*s faults cpu\n",
465: #endif
466: ndrives * 3, "");
467:
468: #ifdef NEWVM
1.1 deraadt 469: (void)printf(" r b w avm fre flt re pi po fr sr ");
1.6 tholo 470: #else
471: (void)printf(" r b w avm fre re at pi po fr de sr ");
1.1 deraadt 472: #endif
473: for (i = 0; i < dk_ndrive; i++)
1.6 tholo 474: if (dk_select[i])
1.1 deraadt 475: (void)printf("%c%c ", dr_name[i][0],
476: dr_name[i][strlen(dr_name[i]) - 1]);
477: (void)printf(" in sy cs us sy id\n");
478: hdrcnt = winlines - 2;
479: }
480:
481: /*
482: * Force a header to be prepended to the next output.
483: */
484: void
485: needhdr()
486: {
487:
488: hdrcnt = 1;
489: }
490:
491: void
492: dotimes()
493: {
494: u_int pgintime, rectime;
495:
1.12 tholo 496: #ifdef NEWVM
497: pgintime = 0;
498: rectime = 0;
499: #else
1.1 deraadt 500: kread(X_REC, &rectime, sizeof(rectime));
501: kread(X_PGIN, &pgintime, sizeof(pgintime));
1.12 tholo 502: #endif
1.1 deraadt 503: kread(X_SUM, &sum, sizeof(sum));
1.12 tholo 504: (void)printf("%u reactivates, %u total time (usec)\n",
505: sum.v_reactivated, rectime);
506: (void)printf("average: %u usec / reclaim\n", rectime / sum.v_reactivated);
1.1 deraadt 507: (void)printf("\n");
508: (void)printf("%u page ins, %u total time (msec)\n",
1.12 tholo 509: sum.v_pageins, pgintime / 10);
1.1 deraadt 510: (void)printf("average: %8.1f msec / page in\n",
1.12 tholo 511: pgintime / (sum.v_pageins * 10.0));
1.1 deraadt 512: }
513:
514: pct(top, bot)
515: long top, bot;
516: {
517: long ans;
518:
519: if (bot == 0)
520: return(0);
521: ans = (quad_t)top * 100 / bot;
522: return (ans);
523: }
524:
525: #define PCT(top, bot) pct((long)(top), (long)(bot))
526:
527: #if defined(tahoe)
528: #include <machine/cpu.h>
529: #endif
530:
531: void
532: dosum()
533: {
534: struct nchstats nchstats;
535: #ifndef NEWVM
536: struct xstats xstats;
537: #endif
538: long nchtotal;
539: #if defined(tahoe)
540: struct keystats keystats;
541: #endif
542:
543: kread(X_SUM, &sum, sizeof(sum));
544: (void)printf("%9u cpu context switches\n", sum.v_swtch);
545: (void)printf("%9u device interrupts\n", sum.v_intr);
546: (void)printf("%9u software interrupts\n", sum.v_soft);
547: (void)printf("%9u traps\n", sum.v_trap);
548: (void)printf("%9u system calls\n", sum.v_syscall);
549: (void)printf("%9u total faults taken\n", sum.v_faults);
550: (void)printf("%9u swap ins\n", sum.v_swpin);
551: (void)printf("%9u swap outs\n", sum.v_swpout);
552: (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
553: (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
554: (void)printf("%9u page ins\n", sum.v_pageins);
555: (void)printf("%9u page outs\n", sum.v_pageouts);
556: (void)printf("%9u pages paged in\n", sum.v_pgpgin);
557: (void)printf("%9u pages paged out\n", sum.v_pgpgout);
558: (void)printf("%9u pages reactivated\n", sum.v_reactivated);
559: (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
560: (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
561: (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
562: (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
563: (void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
564: #ifdef NEWVM
565: (void)printf("%9u VM object cache lookups\n", sum.v_lookups);
566: (void)printf("%9u VM object hits\n", sum.v_hits);
567: (void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
568: (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
569: (void)printf("%9u pages freed by daemon\n", sum.v_dfree);
570: (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
571: (void)printf("%9u pages free\n", sum.v_free_count);
572: (void)printf("%9u pages wired down\n", sum.v_wire_count);
573: (void)printf("%9u pages active\n", sum.v_active_count);
574: (void)printf("%9u pages inactive\n", sum.v_inactive_count);
575: (void)printf("%9u bytes per page\n", sum.v_page_size);
576: #else
577: (void)printf("%9u sequential process pages freed\n", sum.v_seqfree);
578: (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec,
579: PCT(sum.v_fastpgrec, sum.v_pgrec));
580: (void)printf("%9u reclaims from free list\n", sum.v_pgfrec);
581: (void)printf("%9u executable fill pages created\n",
582: sum.v_nexfod / CLSIZE);
583: (void)printf("%9u executable fill page faults\n",
584: sum.v_exfod / CLSIZE);
585: (void)printf("%9u swap text pages found in free list\n",
586: sum.v_xsfrec);
587: (void)printf("%9u inode text pages found in free list\n",
588: sum.v_xifrec);
589: (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE);
590: (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE);
591: (void)printf("%9u pages freed by the clock daemon\n",
592: sum.v_dfree / CLSIZE);
593: #endif
594: kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
595: nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
596: nchstats.ncs_badhits + nchstats.ncs_falsehits +
597: nchstats.ncs_miss + nchstats.ncs_long;
598: (void)printf("%9ld total name lookups\n", nchtotal);
599: (void)printf(
1.12 tholo 600: "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-directory\n",
1.1 deraadt 601: "", PCT(nchstats.ncs_goodhits, nchtotal),
602: PCT(nchstats.ncs_neghits, nchtotal),
603: PCT(nchstats.ncs_pass2, nchtotal));
604: (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
605: PCT(nchstats.ncs_badhits, nchtotal),
606: PCT(nchstats.ncs_falsehits, nchtotal),
607: PCT(nchstats.ncs_long, nchtotal));
608: #ifndef NEWVM
609: kread(X_XSTATS, &xstats, sizeof(xstats));
610: (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n",
611: xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc));
612: (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "",
613: xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
614: (void)printf("%9lu total calls to xfree", xstats.free);
615: (void)printf(" (sticky %lu cached %lu swapped %lu)\n",
616: xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
617: #endif
618: #if defined(tahoe)
619: kread(X_CKEYSTATS, &keystats, sizeof(keystats));
620: (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
621: keystats.ks_allocs, "code cache keys allocated",
622: PCT(keystats.ks_allocfree, keystats.ks_allocs),
623: PCT(keystats.ks_norefs, keystats.ks_allocs),
624: PCT(keystats.ks_taken, keystats.ks_allocs),
625: PCT(keystats.ks_shared, keystats.ks_allocs));
626: kread(X_DKEYSTATS, &keystats, sizeof(keystats));
627: (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
628: keystats.ks_allocs, "data cache keys allocated",
629: PCT(keystats.ks_allocfree, keystats.ks_allocs),
630: PCT(keystats.ks_norefs, keystats.ks_allocs),
631: PCT(keystats.ks_taken, keystats.ks_allocs),
632: PCT(keystats.ks_shared, keystats.ks_allocs));
633: #endif
634: }
635:
636: void
637: doforkst()
638: {
639: struct forkstat fks;
640:
641: kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
642: (void)printf("%d forks, %d pages, average %.2f\n",
643: fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
644: (void)printf("%d vforks, %d pages, average %.2f\n",
1.12 tholo 645: fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / (fks.cntvfork ? fks.cntvfork : 1));
646: (void)printf("%d rforks, %d pages, average %.2f\n",
647: fks.cntrfork, fks.sizrfork, (double)fks.sizrfork / (fks.cntrfork ? fks.cntrfork : 1));
1.1 deraadt 648: }
649:
650: void
651: dkstats()
652: {
653: register int dn, state;
654: double etime;
655: long tmp;
656:
1.6 tholo 657: /* Calculate disk stat deltas. */
658: dkswap();
1.1 deraadt 659: etime = 0;
660: for (state = 0; state < CPUSTATES; ++state) {
1.6 tholo 661: etime += cur.cp_time[state];
1.1 deraadt 662: }
663: if (etime == 0)
664: etime = 1;
665: etime /= hz;
666: for (dn = 0; dn < dk_ndrive; ++dn) {
1.6 tholo 667: if (!dk_select[dn])
1.1 deraadt 668: continue;
1.6 tholo 669: (void)printf("%2.0f ", cur.dk_xfer[dn] / etime);
1.1 deraadt 670: }
671: }
672:
673: void
674: cpustats()
675: {
676: register int state;
677: double pct, total;
678:
679: total = 0;
680: for (state = 0; state < CPUSTATES; ++state)
1.6 tholo 681: total += cur.cp_time[state];
1.1 deraadt 682: if (total)
683: pct = 100 / total;
684: else
685: pct = 0;
1.6 tholo 686: (void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct);
687: (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct);
688: (void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
1.1 deraadt 689: }
690:
691: #if defined(pc532)
692: /* To get struct iv ...*/
693: #define _KERNEL
694: #include <machine/psl.h>
695: #undef _KERNEL
696: void
697: dointr()
698: {
1.19 deraadt 699: register long i, j, inttotal;
700: time_t uptime;
1.1 deraadt 701: static char iname[64];
702: struct iv ivt[32], *ivp = ivt;
703:
704: iname[63] = '\0';
705: uptime = getuptime();
706: kread(X_IVT, ivp, sizeof(ivt));
707:
708: for (i = 0; i < 2; i++) {
709: (void)printf("%sware interrupts:\n", i ? "\nsoft" : "hard");
710: (void)printf("interrupt total rate\n");
711: inttotal = 0;
712: for (j = 0; j < 16; j++, ivp++) {
713: if (ivp->iv_vec && ivp->iv_use && ivp->iv_cnt) {
714: if (kvm_read(kd, (u_long)ivp->iv_use, iname, 63) != 63) {
715: (void)fprintf(stderr, "vmstat: iv_use: %s\n",
716: kvm_geterr(kd));
717: exit(1);
718: }
719: (void)printf("%-12s %8ld %8ld\n", iname,
720: ivp->iv_cnt, ivp->iv_cnt / uptime);
721: inttotal += ivp->iv_cnt;
722: }
723: }
1.3 deraadt 724: (void)printf("Total %8ld %8ld\n",
1.1 deraadt 725: inttotal, inttotal / uptime);
726: }
1.12 tholo 727: }
728: #elif defined(i386)
729: /* To get struct intrhand */
1.13 tholo 730: #define _KERNEL
1.12 tholo 731: #include <machine/psl.h>
1.13 tholo 732: #undef _KERNEL
1.12 tholo 733: void
734: dointr()
735: {
736: struct intrhand *intrhand[16], *ihp, ih;
1.19 deraadt 737: long inttotal;
738: time_t uptime;
1.12 tholo 739: int intrstray[16];
740: char iname[17];
741: int i;
742:
743: iname[16] = '\0';
744: uptime = getuptime();
745: kread(X_INTRHAND, intrhand, sizeof(intrhand));
746: kread(X_INTRSTRAY, intrstray, sizeof(intrstray));
747:
748: (void)printf("interrupt total rate\n");
749: inttotal = 0;
750: for (i = 0; i < 16; i++) {
751: ihp = intrhand[i];
752: while (ihp) {
753: if (kvm_read(kd, (u_long)ihp, &ih, sizeof(ih)) != sizeof(ih))
754: errx(1, "vmstat: ih: %s", kvm_geterr(kd));
755: if (kvm_read(kd, (u_long)ih.ih_what, iname, 16) != 16)
756: errx(1, "vmstat: ih_what: %s", kvm_geterr(kd));
757: printf("%-16.16s %8ld %8ld\n", iname, ih.ih_count, ih.ih_count / uptime);
758: inttotal += ih.ih_count;
759: ihp = ih.ih_next;
760: }
761: }
762: for (i = 0; i < 16; i++)
763: if (intrstray[i]) {
764: printf("Stray irq %-2d %8ld %8ld\n",
765: i, intrstray[i], intrstray[i] / uptime);
766: inttotal += intrstray[i];
767: }
768: printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
1.1 deraadt 769: }
770: #else
771: void
772: dointr()
773: {
1.19 deraadt 774: register long *intrcnt, inttotal;
775: time_t uptime;
1.1 deraadt 776: register int nintr, inamlen;
777: register char *intrname;
1.9 deraadt 778: struct evcntlist allevents;
779: struct evcnt evcnt, *evptr;
1.1 deraadt 780: struct device dev;
781:
782: uptime = getuptime();
783: nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
784: inamlen =
785: namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
786: intrcnt = malloc((size_t)nintr);
787: intrname = malloc((size_t)inamlen);
788: if (intrcnt == NULL || intrname == NULL) {
789: (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
790: exit(1);
791: }
792: kread(X_INTRCNT, intrcnt, (size_t)nintr);
793: kread(X_INTRNAMES, intrname, (size_t)inamlen);
794: (void)printf("interrupt total rate\n");
795: inttotal = 0;
796: nintr /= sizeof(long);
797: while (--nintr >= 0) {
798: if (*intrcnt)
799: (void)printf("%-14s %8ld %8ld\n", intrname,
800: *intrcnt, *intrcnt / uptime);
801: intrname += strlen(intrname) + 1;
802: inttotal += *intrcnt++;
803: }
804: kread(X_ALLEVENTS, &allevents, sizeof allevents);
1.9 deraadt 805: evptr = allevents.tqh_first;
806: while (evptr) {
807: if (kvm_read(kd, (long)evptr, (void *)&evcnt,
1.1 deraadt 808: sizeof evcnt) != sizeof evcnt) {
809: (void)fprintf(stderr, "vmstat: event chain trashed\n",
810: kvm_geterr(kd));
811: exit(1);
812: }
813: if (strcmp(evcnt.ev_name, "intr") == 0) {
814: if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev,
815: sizeof dev) != sizeof dev) {
816: (void)fprintf(stderr, "vmstat: event chain trashed\n",
817: kvm_geterr(kd));
818: exit(1);
819: }
820: if (evcnt.ev_count)
821: (void)printf("%-14s %8ld %8ld\n", dev.dv_xname,
822: evcnt.ev_count, evcnt.ev_count / uptime);
823: inttotal += evcnt.ev_count++;
824: }
1.9 deraadt 825: evptr = evcnt.ev_list.tqe_next;
1.1 deraadt 826: }
827: (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
828: }
829: #endif
830:
831: /*
832: * These names are defined in <sys/malloc.h>.
833: */
834: char *kmemnames[] = INITKMEMNAMES;
835:
836: void
837: domem()
838: {
839: register struct kmembuckets *kp;
840: register struct kmemstats *ks;
841: register int i, j;
842: int len, size, first;
843: long totuse = 0, totfree = 0, totreq = 0;
844: char *name;
845: struct kmemstats kmemstats[M_LAST];
846: struct kmembuckets buckets[MINBUCKET + 16];
847:
848: kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
1.18 kstailey 849: for (first = 1, i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16;
850: i++, kp++) {
1.1 deraadt 851: if (kp->kb_calls == 0)
852: continue;
1.18 kstailey 853: if (first) {
854: (void)printf("Memory statistics by bucket size\n");
855: (void)printf(
856: " Size In Use Free Requests HighWater Couldfree\n");
857: first = 0;
858: }
1.1 deraadt 859: size = 1 << i;
860: (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
861: kp->kb_total - kp->kb_totalfree,
862: kp->kb_totalfree, kp->kb_calls,
863: kp->kb_highwat, kp->kb_couldfree);
864: totfree += size * kp->kb_totalfree;
1.18 kstailey 865: }
866:
867: /*
868: * If kmem statistics are not being gathered by the kernel,
869: * first will still be 1.
870: */
871: if (first) {
872: printf(
873: "Kmem statistics are not being gathered by the kernel.\n");
874: return;
1.1 deraadt 875: }
876:
877: kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
878: (void)printf("\nMemory usage type by bucket size\n");
879: (void)printf(" Size Type(s)\n");
880: kp = &buckets[MINBUCKET];
881: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
882: if (kp->kb_calls == 0)
883: continue;
884: first = 1;
885: len = 8;
886: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
887: if (ks->ks_calls == 0)
888: continue;
889: if ((ks->ks_size & j) == 0)
890: continue;
891: name = kmemnames[i] ? kmemnames[i] : "undefined";
892: len += 2 + strlen(name);
893: if (first)
894: printf("%8d %s", j, name);
895: else
896: printf(",");
897: if (len >= 80) {
898: printf("\n\t ");
899: len = 10 + strlen(name);
900: }
901: if (!first)
902: printf(" %s", name);
903: first = 0;
904: }
905: printf("\n");
906: }
907:
908: (void)printf(
1.17 kstailey 909: "\nMemory statistics by type Type Kern\n");
1.1 deraadt 910: (void)printf(
1.17 kstailey 911: " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
1.1 deraadt 912: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
913: if (ks->ks_calls == 0)
914: continue;
1.17 kstailey 915: (void)printf("%13s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
1.1 deraadt 916: kmemnames[i] ? kmemnames[i] : "undefined",
917: ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
918: (ks->ks_maxused + 1023) / 1024,
919: (ks->ks_limit + 1023) / 1024, ks->ks_calls,
920: ks->ks_limblocks, ks->ks_mapblocks);
921: first = 1;
922: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
923: if ((ks->ks_size & j) == 0)
924: continue;
925: if (first)
926: printf(" %d", j);
927: else
928: printf(",%d", j);
929: first = 0;
930: }
931: printf("\n");
932: totuse += ks->ks_memuse;
933: totreq += ks->ks_calls;
934: }
935: (void)printf("\nMemory Totals: In Use Free Requests\n");
936: (void)printf(" %7ldK %6ldK %8ld\n",
937: (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
938: }
939:
940: /*
941: * kread reads something from the kernel, given its nlist index.
942: */
943: void
944: kread(nlx, addr, size)
945: int nlx;
946: void *addr;
947: size_t size;
948: {
949: char *sym;
950:
951: if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
952: sym = namelist[nlx].n_name;
953: if (*sym == '_')
954: ++sym;
955: (void)fprintf(stderr,
956: "vmstat: symbol %s not defined\n", sym);
957: exit(1);
958: }
959: if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
960: sym = namelist[nlx].n_name;
961: if (*sym == '_')
962: ++sym;
963: (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd));
964: exit(1);
965: }
966: }
967:
968: void
969: usage()
970: {
971: (void)fprintf(stderr,
972: "usage: vmstat [-fimst] [-c count] [-M core] \
973: [-N system] [-w wait] [disks]\n");
974: exit(1);
975: }
976: