Annotation of src/usr.bin/vmstat/vmstat.c, Revision 1.14
1.11 deraadt 1: /* $NetBSD: vmstat.c,v 1.29.4.1 1996/06/05 00:21:05 cgd Exp $ */
1.14 ! deraadt 2: /* $OpenBSD: vmstat.c,v 1.13 1996/06/24 23:51:59 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
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;
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) {
265: struct winsize winsize;
266:
1.6 tholo 267: dkinit(0); /* Initialize disk stats, no disks selected. */
268: argv = choosedrives(argv); /* Select disks. */
1.1 deraadt 269: winsize.ws_row = 0;
270: (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
271: if (winsize.ws_row > 0)
272: winlines = winsize.ws_row;
273:
274: }
275:
276: #define BACKWARD_COMPATIBILITY
277: #ifdef BACKWARD_COMPATIBILITY
278: if (*argv) {
279: interval = atoi(*argv);
280: if (*++argv)
281: reps = atoi(*argv);
282: }
283: #endif
284:
285: if (interval) {
286: if (!reps)
287: reps = -1;
288: } else if (reps)
289: interval = 1;
290:
291: if (todo & FORKSTAT)
292: doforkst();
293: if (todo & MEMSTAT)
294: domem();
295: if (todo & SUMSTAT)
296: dosum();
297: if (todo & TIMESTAT)
298: dotimes();
299: if (todo & INTRSTAT)
300: dointr();
301: if (todo & VMSTAT)
302: dovmstat(interval, reps);
303: exit(0);
304: }
305:
306: char **
1.6 tholo 307: choosedrives(argv)
1.1 deraadt 308: char **argv;
309: {
310: register int i;
311: register char **cp;
312: char buf[30];
313:
314: /*
315: * Choose drives to be displayed. Priority goes to (in order) drives
316: * supplied as arguments, default drives. If everything isn't filled
317: * in and there are drives not taken care of, display the first few
318: * that fit.
319: */
320: #define BACKWARD_COMPATIBILITY
321: for (ndrives = 0; *argv; ++argv) {
322: #ifdef BACKWARD_COMPATIBILITY
323: if (isdigit(**argv))
324: break;
325: #endif
326: for (i = 0; i < dk_ndrive; i++) {
327: if (strcmp(dr_name[i], *argv))
328: continue;
1.6 tholo 329: dk_select[i] = 1;
1.1 deraadt 330: ++ndrives;
331: break;
332: }
333: }
334: for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
1.6 tholo 335: if (dk_select[i])
1.1 deraadt 336: continue;
1.6 tholo 337: dk_select[i] = 1;
1.1 deraadt 338: ++ndrives;
339: }
340: return(argv);
341: }
342:
343: long
344: getuptime()
345: {
1.11 deraadt 346: static time_t now;
347: static struct timeval boottime;
1.1 deraadt 348: time_t uptime;
349:
1.11 deraadt 350: if (boottime.tv_sec == 0)
1.1 deraadt 351: kread(X_BOOTTIME, &boottime, sizeof(boottime));
352: (void)time(&now);
1.11 deraadt 353: uptime = now - boottime.tv_sec;
1.1 deraadt 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: */
1.14 ! deraadt 440: halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
1.1 deraadt 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.12 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.12 tholo 500: #endif
1.1 deraadt 501: kread(X_SUM, &sum, sizeof(sum));
1.12 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.12 tholo 507: sum.v_pageins, pgintime / 10);
1.1 deraadt 508: (void)printf("average: %8.1f msec / page in\n",
1.12 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.12 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.12 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.12 tholo 724: }
725: #elif defined(i386)
726: /* To get struct intrhand */
1.13 tholo 727: #define _KERNEL
1.12 tholo 728: #include <machine/psl.h>
1.13 tholo 729: #undef _KERNEL
1.12 tholo 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;
1.9 deraadt 773: struct evcntlist allevents;
774: struct evcnt evcnt, *evptr;
1.1 deraadt 775: struct device dev;
776:
777: uptime = getuptime();
778: nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
779: inamlen =
780: namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
781: intrcnt = malloc((size_t)nintr);
782: intrname = malloc((size_t)inamlen);
783: if (intrcnt == NULL || intrname == NULL) {
784: (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
785: exit(1);
786: }
787: kread(X_INTRCNT, intrcnt, (size_t)nintr);
788: kread(X_INTRNAMES, intrname, (size_t)inamlen);
789: (void)printf("interrupt total rate\n");
790: inttotal = 0;
791: nintr /= sizeof(long);
792: while (--nintr >= 0) {
793: if (*intrcnt)
794: (void)printf("%-14s %8ld %8ld\n", intrname,
795: *intrcnt, *intrcnt / uptime);
796: intrname += strlen(intrname) + 1;
797: inttotal += *intrcnt++;
798: }
799: kread(X_ALLEVENTS, &allevents, sizeof allevents);
1.9 deraadt 800: evptr = allevents.tqh_first;
801: while (evptr) {
802: if (kvm_read(kd, (long)evptr, (void *)&evcnt,
1.1 deraadt 803: sizeof evcnt) != sizeof evcnt) {
804: (void)fprintf(stderr, "vmstat: event chain trashed\n",
805: kvm_geterr(kd));
806: exit(1);
807: }
808: if (strcmp(evcnt.ev_name, "intr") == 0) {
809: if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev,
810: sizeof dev) != sizeof dev) {
811: (void)fprintf(stderr, "vmstat: event chain trashed\n",
812: kvm_geterr(kd));
813: exit(1);
814: }
815: if (evcnt.ev_count)
816: (void)printf("%-14s %8ld %8ld\n", dev.dv_xname,
817: evcnt.ev_count, evcnt.ev_count / uptime);
818: inttotal += evcnt.ev_count++;
819: }
1.9 deraadt 820: evptr = evcnt.ev_list.tqe_next;
1.1 deraadt 821: }
822: (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
823: }
824: #endif
825:
826: /*
827: * These names are defined in <sys/malloc.h>.
828: */
829: char *kmemnames[] = INITKMEMNAMES;
830:
831: void
832: domem()
833: {
834: register struct kmembuckets *kp;
835: register struct kmemstats *ks;
836: register int i, j;
837: int len, size, first;
838: long totuse = 0, totfree = 0, totreq = 0;
839: char *name;
840: struct kmemstats kmemstats[M_LAST];
841: struct kmembuckets buckets[MINBUCKET + 16];
842:
843: kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
844: (void)printf("Memory statistics by bucket size\n");
845: (void)printf(
846: " Size In Use Free Requests HighWater Couldfree\n");
847: for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
848: if (kp->kb_calls == 0)
849: continue;
850: size = 1 << i;
851: (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
852: kp->kb_total - kp->kb_totalfree,
853: kp->kb_totalfree, kp->kb_calls,
854: kp->kb_highwat, kp->kb_couldfree);
855: totfree += size * kp->kb_totalfree;
856: }
857:
858: kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
859: (void)printf("\nMemory usage type by bucket size\n");
860: (void)printf(" Size Type(s)\n");
861: kp = &buckets[MINBUCKET];
862: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
863: if (kp->kb_calls == 0)
864: continue;
865: first = 1;
866: len = 8;
867: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
868: if (ks->ks_calls == 0)
869: continue;
870: if ((ks->ks_size & j) == 0)
871: continue;
872: name = kmemnames[i] ? kmemnames[i] : "undefined";
873: len += 2 + strlen(name);
874: if (first)
875: printf("%8d %s", j, name);
876: else
877: printf(",");
878: if (len >= 80) {
879: printf("\n\t ");
880: len = 10 + strlen(name);
881: }
882: if (!first)
883: printf(" %s", name);
884: first = 0;
885: }
886: printf("\n");
887: }
888:
889: (void)printf(
890: "\nMemory statistics by type Type Kern\n");
891: (void)printf(
892: " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
893: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
894: if (ks->ks_calls == 0)
895: continue;
896: (void)printf("%12s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
897: kmemnames[i] ? kmemnames[i] : "undefined",
898: ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
899: (ks->ks_maxused + 1023) / 1024,
900: (ks->ks_limit + 1023) / 1024, ks->ks_calls,
901: ks->ks_limblocks, ks->ks_mapblocks);
902: first = 1;
903: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
904: if ((ks->ks_size & j) == 0)
905: continue;
906: if (first)
907: printf(" %d", j);
908: else
909: printf(",%d", j);
910: first = 0;
911: }
912: printf("\n");
913: totuse += ks->ks_memuse;
914: totreq += ks->ks_calls;
915: }
916: (void)printf("\nMemory Totals: In Use Free Requests\n");
917: (void)printf(" %7ldK %6ldK %8ld\n",
918: (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
919: }
920:
921: /*
922: * kread reads something from the kernel, given its nlist index.
923: */
924: void
925: kread(nlx, addr, size)
926: int nlx;
927: void *addr;
928: size_t size;
929: {
930: char *sym;
931:
932: if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
933: sym = namelist[nlx].n_name;
934: if (*sym == '_')
935: ++sym;
936: (void)fprintf(stderr,
937: "vmstat: symbol %s not defined\n", sym);
938: exit(1);
939: }
940: if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
941: sym = namelist[nlx].n_name;
942: if (*sym == '_')
943: ++sym;
944: (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd));
945: exit(1);
946: }
947: }
948:
949: void
950: usage()
951: {
952: (void)fprintf(stderr,
953: #ifndef NEWVM
954: "usage: vmstat [-fimst] [-c count] [-M core] \
955: [-N system] [-w wait] [disks]\n");
956: #else
957: "usage: vmstat [-ims] [-c count] [-M core] \
958: [-N system] [-w wait] [disks]\n");
959: #endif
960: exit(1);
961: }
962: