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