Annotation of src/usr.bin/vmstat/vmstat.c, Revision 1.10
1.10 ! deraadt 1: /* $NetBSD: vmstat.c,v 1.29 1996/05/10 23:19:32 thorpej Exp $ */
1.1 deraadt 2:
3: /*
4: * Copyright (c) 1980, 1986, 1991, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: static char copyright[] =
38: "@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
39: The Regents of the University of California. All rights reserved.\n";
40: #endif /* not lint */
41:
42: #ifndef lint
43: #if 0
44: static char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93";
45: #else
1.10 ! deraadt 46: static char rcsid[] = "$NetBSD: vmstat.c,v 1.29 1996/05/10 23:19:32 thorpej Exp $";
1.1 deraadt 47: #endif
48: #endif /* not lint */
49:
50: #include <sys/param.h>
51: #include <sys/time.h>
52: #include <sys/proc.h>
53: #include <sys/user.h>
54: #include <sys/dkstat.h>
55: #include <sys/buf.h>
56: #include <sys/namei.h>
57: #include <sys/malloc.h>
58: #include <sys/fcntl.h>
59: #include <sys/ioctl.h>
60: #include <sys/sysctl.h>
61: #include <sys/device.h>
62: #include <vm/vm.h>
63: #include <time.h>
64: #include <nlist.h>
65: #include <kvm.h>
66: #include <errno.h>
67: #include <unistd.h>
68: #include <signal.h>
69: #include <stdio.h>
70: #include <ctype.h>
71: #include <stdlib.h>
72: #include <string.h>
73: #include <paths.h>
74: #include <limits.h>
1.6 tholo 75: #include "dkstats.h"
1.1 deraadt 76:
77: #define NEWVM /* XXX till old has been updated or purged */
78: struct nlist namelist[] = {
79: #define X_CPTIME 0
80: { "_cp_time" },
81: #define X_DK_NDRIVE 1
82: { "_dk_ndrive" },
83: #define X_SUM 2
84: { "_cnt" },
85: #define X_BOOTTIME 3
86: { "_boottime" },
87: #define X_DKXFER 4
88: { "_dk_xfer" },
89: #define X_HZ 5
90: { "_hz" },
91: #define X_STATHZ 6
92: { "_stathz" },
93: #define X_NCHSTATS 7
94: { "_nchstats" },
95: #define X_INTRNAMES 8
96: { "_intrnames" },
97: #define X_EINTRNAMES 9
98: { "_eintrnames" },
99: #define X_INTRCNT 10
100: { "_intrcnt" },
101: #define X_EINTRCNT 11
102: { "_eintrcnt" },
103: #define X_KMEMSTAT 12
104: { "_kmemstats" },
105: #define X_KMEMBUCKETS 13
106: { "_bucket" },
107: #define X_ALLEVENTS 14
108: { "_allevents" },
109: #ifdef notdef
1.10 ! deraadt 110: #define X_DEFICIT 15
1.1 deraadt 111: { "_deficit" },
1.10 ! deraadt 112: #define X_FORKSTAT 16
! 113: { "_forkstat" },
1.1 deraadt 114: #define X_REC 17
115: { "_rectime" },
116: #define X_PGIN 18
117: { "_pgintime" },
118: #define X_XSTATS 19
119: { "_xstats" },
120: #define X_END 20
121: #else
1.10 ! deraadt 122: #define X_END 15
1.1 deraadt 123: #endif
124: #ifdef tahoe
125: #define X_VBDINIT (X_END)
126: { "_vbdinit" },
127: #define X_CKEYSTATS (X_END+1)
128: { "_ckeystats" },
129: #define X_DKEYSTATS (X_END+2)
130: { "_dkeystats" },
131: #endif
132: #if defined(pc532)
133: #define X_IVT (X_END)
134: { "_ivt" },
135: #endif
136: { "" },
137: };
138:
1.6 tholo 139: /* Objects defined in dkstats.c */
140: extern struct _disk cur;
1.10 ! deraadt 141: extern char **dr_name;
! 142: extern int *dk_select, dk_ndrive;
1.1 deraadt 143:
144: struct vmmeter sum, osum;
1.6 tholo 145: int ndrives;
1.1 deraadt 146:
147: int winlines = 20;
148:
149: kvm_t *kd;
150:
151: #define FORKSTAT 0x01
152: #define INTRSTAT 0x02
153: #define MEMSTAT 0x04
154: #define SUMSTAT 0x08
155: #define TIMESTAT 0x10
156: #define VMSTAT 0x20
157:
1.10 ! deraadt 158: void cpustats __P((void));
! 159: void dkstats __P((void));
! 160: void dointr __P((void));
! 161: void domem __P((void));
! 162: void dosum __P((void));
! 163: void dovmstat __P((u_int, int));
! 164: void kread __P((int, void *, size_t));
! 165: void usage __P((void));
! 166: #ifdef notdef
! 167: void dotimes __P((void));
! 168: void doforkst __P((void));
! 169: #endif
1.1 deraadt 170:
1.10 ! deraadt 171: char **choosedrives __P((char **));
! 172:
! 173: /* Namelist and memory file names. */
! 174: char *nlistf, *memf;
1.6 tholo 175:
1.1 deraadt 176: main(argc, argv)
177: register int argc;
178: register char **argv;
179: {
180: extern int optind;
181: extern char *optarg;
182: register int c, todo;
183: u_int interval;
184: int reps;
185: char errbuf[_POSIX2_LINE_MAX];
186:
187: memf = nlistf = NULL;
188: interval = reps = todo = 0;
189: while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) {
190: switch (c) {
191: case 'c':
192: reps = atoi(optarg);
193: break;
1.10 ! deraadt 194: #ifndef notdef
1.1 deraadt 195: case 'f':
196: todo |= FORKSTAT;
197: break;
1.10 ! deraadt 198: #endif
1.1 deraadt 199: case 'i':
200: todo |= INTRSTAT;
201: break;
202: case 'M':
203: memf = optarg;
204: break;
205: case 'm':
206: todo |= MEMSTAT;
207: break;
208: case 'N':
209: nlistf = optarg;
210: break;
211: case 's':
212: todo |= SUMSTAT;
213: break;
1.10 ! deraadt 214: #ifndef notdef
1.1 deraadt 215: case 't':
216: todo |= TIMESTAT;
217: break;
1.10 ! deraadt 218: #endif
1.1 deraadt 219: case 'w':
220: interval = atoi(optarg);
221: break;
222: case '?':
223: default:
224: usage();
225: }
226: }
227: argc -= optind;
228: argv += optind;
229:
230: if (todo == 0)
231: todo = VMSTAT;
232:
233: /*
234: * Discard setgid privileges if not the running kernel so that bad
235: * guys can't print interesting stuff from kernel memory.
236: */
237: if (nlistf != NULL || memf != NULL)
238: setgid(getgid());
239:
240: kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
241: if (kd == 0) {
242: (void)fprintf(stderr,
243: "vmstat: kvm_openfiles: %s\n", errbuf);
244: exit(1);
245: }
246:
247: if ((c = kvm_nlist(kd, namelist)) != 0) {
248: if (c > 0) {
249: (void)fprintf(stderr,
250: "vmstat: undefined symbols:");
251: for (c = 0;
252: c < sizeof(namelist)/sizeof(namelist[0]); c++)
253: if (namelist[c].n_type == 0)
254: fprintf(stderr, " %s",
255: namelist[c].n_name);
256: (void)fputc('\n', stderr);
257: } else
258: (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
259: kvm_geterr(kd));
260: exit(1);
261: }
262:
263: if (todo & VMSTAT) {
264: struct winsize winsize;
265:
1.6 tholo 266: dkinit(0); /* Initialize disk stats, no disks selected. */
267: argv = choosedrives(argv); /* Select disks. */
1.1 deraadt 268: winsize.ws_row = 0;
269: (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
270: if (winsize.ws_row > 0)
271: winlines = winsize.ws_row;
272:
273: }
274:
275: #define BACKWARD_COMPATIBILITY
276: #ifdef BACKWARD_COMPATIBILITY
277: if (*argv) {
278: interval = atoi(*argv);
279: if (*++argv)
280: reps = atoi(*argv);
281: }
282: #endif
283:
284: if (interval) {
285: if (!reps)
286: reps = -1;
287: } else if (reps)
288: interval = 1;
289:
1.10 ! deraadt 290: #ifdef notdef
1.1 deraadt 291: if (todo & FORKSTAT)
292: doforkst();
1.10 ! deraadt 293: #endif
1.1 deraadt 294: if (todo & MEMSTAT)
295: domem();
296: if (todo & SUMSTAT)
297: dosum();
1.10 ! deraadt 298: #ifdef notdef
1.1 deraadt 299: if (todo & TIMESTAT)
300: dotimes();
1.10 ! deraadt 301: #endif
1.1 deraadt 302: if (todo & INTRSTAT)
303: dointr();
304: if (todo & VMSTAT)
305: dovmstat(interval, reps);
306: exit(0);
307: }
308:
309: char **
1.6 tholo 310: choosedrives(argv)
1.1 deraadt 311: char **argv;
312: {
313: register int i;
314: register char **cp;
315: char buf[30];
316:
317: /*
318: * Choose drives to be displayed. Priority goes to (in order) drives
319: * supplied as arguments, default drives. If everything isn't filled
320: * in and there are drives not taken care of, display the first few
321: * that fit.
322: */
323: #define BACKWARD_COMPATIBILITY
324: for (ndrives = 0; *argv; ++argv) {
325: #ifdef BACKWARD_COMPATIBILITY
326: if (isdigit(**argv))
327: break;
328: #endif
329: for (i = 0; i < dk_ndrive; i++) {
330: if (strcmp(dr_name[i], *argv))
331: continue;
1.6 tholo 332: dk_select[i] = 1;
1.1 deraadt 333: ++ndrives;
334: break;
335: }
336: }
337: for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
1.6 tholo 338: if (dk_select[i])
1.1 deraadt 339: continue;
1.6 tholo 340: dk_select[i] = 1;
1.1 deraadt 341: ++ndrives;
342: }
343: return(argv);
344: }
345:
346: long
347: getuptime()
348: {
349: static time_t now, boottime;
350: time_t uptime;
351:
352: if (boottime == 0)
353: kread(X_BOOTTIME, &boottime, sizeof(boottime));
354: (void)time(&now);
355: uptime = now - boottime;
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: */
442: halfuptime = (uptime + 1) / 2;
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:
1.10 ! deraadt 491: #ifdef notdef
1.1 deraadt 492: void
493: dotimes()
494: {
495: u_int pgintime, rectime;
496:
497: kread(X_REC, &rectime, sizeof(rectime));
498: kread(X_PGIN, &pgintime, sizeof(pgintime));
499: kread(X_SUM, &sum, sizeof(sum));
1.10 ! deraadt 500: (void)printf("%u reclaims, %u total time (usec)\n",
! 501: sum.v_pgrec, rectime);
! 502: (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec);
1.1 deraadt 503: (void)printf("\n");
504: (void)printf("%u page ins, %u total time (msec)\n",
1.10 ! deraadt 505: sum.v_pgin, pgintime / 10);
1.1 deraadt 506: (void)printf("average: %8.1f msec / page in\n",
1.10 ! deraadt 507: pgintime / (sum.v_pgin * 10.0));
1.1 deraadt 508: }
1.10 ! deraadt 509: #endif
1.1 deraadt 510:
511: pct(top, bot)
512: long top, bot;
513: {
514: long ans;
515:
516: if (bot == 0)
517: return(0);
518: ans = (quad_t)top * 100 / bot;
519: return (ans);
520: }
521:
522: #define PCT(top, bot) pct((long)(top), (long)(bot))
523:
524: #if defined(tahoe)
525: #include <machine/cpu.h>
526: #endif
527:
528: void
529: dosum()
530: {
531: struct nchstats nchstats;
532: #ifndef NEWVM
533: struct xstats xstats;
534: #endif
535: long nchtotal;
536: #if defined(tahoe)
537: struct keystats keystats;
538: #endif
539:
540: kread(X_SUM, &sum, sizeof(sum));
541: (void)printf("%9u cpu context switches\n", sum.v_swtch);
542: (void)printf("%9u device interrupts\n", sum.v_intr);
543: (void)printf("%9u software interrupts\n", sum.v_soft);
544: (void)printf("%9u traps\n", sum.v_trap);
545: (void)printf("%9u system calls\n", sum.v_syscall);
546: (void)printf("%9u total faults taken\n", sum.v_faults);
547: (void)printf("%9u swap ins\n", sum.v_swpin);
548: (void)printf("%9u swap outs\n", sum.v_swpout);
549: (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
550: (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
551: (void)printf("%9u page ins\n", sum.v_pageins);
552: (void)printf("%9u page outs\n", sum.v_pageouts);
553: (void)printf("%9u pages paged in\n", sum.v_pgpgin);
554: (void)printf("%9u pages paged out\n", sum.v_pgpgout);
555: (void)printf("%9u pages reactivated\n", sum.v_reactivated);
556: (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
557: (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
558: (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
559: (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
560: (void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
561: #ifdef NEWVM
562: (void)printf("%9u VM object cache lookups\n", sum.v_lookups);
563: (void)printf("%9u VM object hits\n", sum.v_hits);
564: (void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
565: (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
566: (void)printf("%9u pages freed by daemon\n", sum.v_dfree);
567: (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
568: (void)printf("%9u pages free\n", sum.v_free_count);
569: (void)printf("%9u pages wired down\n", sum.v_wire_count);
570: (void)printf("%9u pages active\n", sum.v_active_count);
571: (void)printf("%9u pages inactive\n", sum.v_inactive_count);
572: (void)printf("%9u bytes per page\n", sum.v_page_size);
573: #else
574: (void)printf("%9u sequential process pages freed\n", sum.v_seqfree);
575: (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec,
576: PCT(sum.v_fastpgrec, sum.v_pgrec));
577: (void)printf("%9u reclaims from free list\n", sum.v_pgfrec);
578: (void)printf("%9u executable fill pages created\n",
579: sum.v_nexfod / CLSIZE);
580: (void)printf("%9u executable fill page faults\n",
581: sum.v_exfod / CLSIZE);
582: (void)printf("%9u swap text pages found in free list\n",
583: sum.v_xsfrec);
584: (void)printf("%9u inode text pages found in free list\n",
585: sum.v_xifrec);
586: (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE);
587: (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE);
588: (void)printf("%9u pages freed by the clock daemon\n",
589: sum.v_dfree / CLSIZE);
590: #endif
591: kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
592: nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
593: nchstats.ncs_badhits + nchstats.ncs_falsehits +
594: nchstats.ncs_miss + nchstats.ncs_long;
595: (void)printf("%9ld total name lookups\n", nchtotal);
596: (void)printf(
1.10 ! deraadt 597: "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
1.1 deraadt 598: "", PCT(nchstats.ncs_goodhits, nchtotal),
599: PCT(nchstats.ncs_neghits, nchtotal),
600: PCT(nchstats.ncs_pass2, nchtotal));
601: (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
602: PCT(nchstats.ncs_badhits, nchtotal),
603: PCT(nchstats.ncs_falsehits, nchtotal),
604: PCT(nchstats.ncs_long, nchtotal));
605: #ifndef NEWVM
606: kread(X_XSTATS, &xstats, sizeof(xstats));
607: (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n",
608: xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc));
609: (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "",
610: xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
611: (void)printf("%9lu total calls to xfree", xstats.free);
612: (void)printf(" (sticky %lu cached %lu swapped %lu)\n",
613: xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
614: #endif
615: #if defined(tahoe)
616: kread(X_CKEYSTATS, &keystats, sizeof(keystats));
617: (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
618: keystats.ks_allocs, "code cache keys allocated",
619: PCT(keystats.ks_allocfree, keystats.ks_allocs),
620: PCT(keystats.ks_norefs, keystats.ks_allocs),
621: PCT(keystats.ks_taken, keystats.ks_allocs),
622: PCT(keystats.ks_shared, keystats.ks_allocs));
623: kread(X_DKEYSTATS, &keystats, sizeof(keystats));
624: (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
625: keystats.ks_allocs, "data cache keys allocated",
626: PCT(keystats.ks_allocfree, keystats.ks_allocs),
627: PCT(keystats.ks_norefs, keystats.ks_allocs),
628: PCT(keystats.ks_taken, keystats.ks_allocs),
629: PCT(keystats.ks_shared, keystats.ks_allocs));
630: #endif
631: }
632:
1.10 ! deraadt 633: #ifdef notdef
1.1 deraadt 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.10 ! deraadt 643: fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork);
1.1 deraadt 644: }
1.10 ! deraadt 645: #endif
1.1 deraadt 646:
647: void
648: dkstats()
649: {
650: register int dn, state;
651: double etime;
652: long tmp;
653:
1.6 tholo 654: /* Calculate disk stat deltas. */
655: dkswap();
1.1 deraadt 656: etime = 0;
657: for (state = 0; state < CPUSTATES; ++state) {
1.6 tholo 658: etime += cur.cp_time[state];
1.1 deraadt 659: }
660: if (etime == 0)
661: etime = 1;
662: etime /= hz;
663: for (dn = 0; dn < dk_ndrive; ++dn) {
1.6 tholo 664: if (!dk_select[dn])
1.1 deraadt 665: continue;
1.6 tholo 666: (void)printf("%2.0f ", cur.dk_xfer[dn] / etime);
1.1 deraadt 667: }
668: }
669:
670: void
671: cpustats()
672: {
673: register int state;
674: double pct, total;
675:
676: total = 0;
677: for (state = 0; state < CPUSTATES; ++state)
1.6 tholo 678: total += cur.cp_time[state];
1.1 deraadt 679: if (total)
680: pct = 100 / total;
681: else
682: pct = 0;
1.6 tholo 683: (void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct);
684: (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct);
685: (void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct);
1.1 deraadt 686: }
687:
688: #if defined(pc532)
689: /* To get struct iv ...*/
690: #define _KERNEL
691: #include <machine/psl.h>
692: #undef _KERNEL
693: void
694: dointr()
695: {
696: register long i, j, inttotal, uptime;
697: static char iname[64];
698: struct iv ivt[32], *ivp = ivt;
699:
700: iname[63] = '\0';
701: uptime = getuptime();
702: kread(X_IVT, ivp, sizeof(ivt));
703:
704: for (i = 0; i < 2; i++) {
705: (void)printf("%sware interrupts:\n", i ? "\nsoft" : "hard");
706: (void)printf("interrupt total rate\n");
707: inttotal = 0;
708: for (j = 0; j < 16; j++, ivp++) {
709: if (ivp->iv_vec && ivp->iv_use && ivp->iv_cnt) {
710: if (kvm_read(kd, (u_long)ivp->iv_use, iname, 63) != 63) {
711: (void)fprintf(stderr, "vmstat: iv_use: %s\n",
712: kvm_geterr(kd));
713: exit(1);
714: }
715: (void)printf("%-12s %8ld %8ld\n", iname,
716: ivp->iv_cnt, ivp->iv_cnt / uptime);
717: inttotal += ivp->iv_cnt;
718: }
719: }
1.3 deraadt 720: (void)printf("Total %8ld %8ld\n",
1.1 deraadt 721: inttotal, inttotal / uptime);
722: }
723: }
724: #else
725: void
726: dointr()
727: {
728: register long *intrcnt, inttotal, uptime;
729: register int nintr, inamlen;
730: register char *intrname;
1.9 deraadt 731: struct evcntlist allevents;
732: struct evcnt evcnt, *evptr;
1.1 deraadt 733: struct device dev;
734:
735: uptime = getuptime();
736: nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
737: inamlen =
738: namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
739: intrcnt = malloc((size_t)nintr);
740: intrname = malloc((size_t)inamlen);
741: if (intrcnt == NULL || intrname == NULL) {
742: (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
743: exit(1);
744: }
745: kread(X_INTRCNT, intrcnt, (size_t)nintr);
746: kread(X_INTRNAMES, intrname, (size_t)inamlen);
747: (void)printf("interrupt total rate\n");
748: inttotal = 0;
749: nintr /= sizeof(long);
750: while (--nintr >= 0) {
751: if (*intrcnt)
752: (void)printf("%-14s %8ld %8ld\n", intrname,
753: *intrcnt, *intrcnt / uptime);
754: intrname += strlen(intrname) + 1;
755: inttotal += *intrcnt++;
756: }
757: kread(X_ALLEVENTS, &allevents, sizeof allevents);
1.9 deraadt 758: evptr = allevents.tqh_first;
759: while (evptr) {
760: if (kvm_read(kd, (long)evptr, (void *)&evcnt,
1.1 deraadt 761: sizeof evcnt) != sizeof evcnt) {
762: (void)fprintf(stderr, "vmstat: event chain trashed\n",
763: kvm_geterr(kd));
764: exit(1);
765: }
766: if (strcmp(evcnt.ev_name, "intr") == 0) {
767: if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev,
768: sizeof dev) != sizeof dev) {
769: (void)fprintf(stderr, "vmstat: event chain trashed\n",
770: kvm_geterr(kd));
771: exit(1);
772: }
773: if (evcnt.ev_count)
774: (void)printf("%-14s %8ld %8ld\n", dev.dv_xname,
775: evcnt.ev_count, evcnt.ev_count / uptime);
776: inttotal += evcnt.ev_count++;
777: }
1.9 deraadt 778: evptr = evcnt.ev_list.tqe_next;
1.1 deraadt 779: }
780: (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
781: }
782: #endif
783:
784: /*
785: * These names are defined in <sys/malloc.h>.
786: */
787: char *kmemnames[] = INITKMEMNAMES;
788:
789: void
790: domem()
791: {
792: register struct kmembuckets *kp;
793: register struct kmemstats *ks;
794: register int i, j;
795: int len, size, first;
796: long totuse = 0, totfree = 0, totreq = 0;
797: char *name;
798: struct kmemstats kmemstats[M_LAST];
799: struct kmembuckets buckets[MINBUCKET + 16];
800:
801: kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
802: (void)printf("Memory statistics by bucket size\n");
803: (void)printf(
804: " Size In Use Free Requests HighWater Couldfree\n");
805: for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
806: if (kp->kb_calls == 0)
807: continue;
808: size = 1 << i;
809: (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
810: kp->kb_total - kp->kb_totalfree,
811: kp->kb_totalfree, kp->kb_calls,
812: kp->kb_highwat, kp->kb_couldfree);
813: totfree += size * kp->kb_totalfree;
814: }
815:
816: kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
817: (void)printf("\nMemory usage type by bucket size\n");
818: (void)printf(" Size Type(s)\n");
819: kp = &buckets[MINBUCKET];
820: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
821: if (kp->kb_calls == 0)
822: continue;
823: first = 1;
824: len = 8;
825: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
826: if (ks->ks_calls == 0)
827: continue;
828: if ((ks->ks_size & j) == 0)
829: continue;
830: name = kmemnames[i] ? kmemnames[i] : "undefined";
831: len += 2 + strlen(name);
832: if (first)
833: printf("%8d %s", j, name);
834: else
835: printf(",");
836: if (len >= 80) {
837: printf("\n\t ");
838: len = 10 + strlen(name);
839: }
840: if (!first)
841: printf(" %s", name);
842: first = 0;
843: }
844: printf("\n");
845: }
846:
847: (void)printf(
848: "\nMemory statistics by type Type Kern\n");
849: (void)printf(
850: " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
851: for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
852: if (ks->ks_calls == 0)
853: continue;
854: (void)printf("%12s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
855: kmemnames[i] ? kmemnames[i] : "undefined",
856: ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
857: (ks->ks_maxused + 1023) / 1024,
858: (ks->ks_limit + 1023) / 1024, ks->ks_calls,
859: ks->ks_limblocks, ks->ks_mapblocks);
860: first = 1;
861: for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
862: if ((ks->ks_size & j) == 0)
863: continue;
864: if (first)
865: printf(" %d", j);
866: else
867: printf(",%d", j);
868: first = 0;
869: }
870: printf("\n");
871: totuse += ks->ks_memuse;
872: totreq += ks->ks_calls;
873: }
874: (void)printf("\nMemory Totals: In Use Free Requests\n");
875: (void)printf(" %7ldK %6ldK %8ld\n",
876: (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
877: }
878:
879: /*
880: * kread reads something from the kernel, given its nlist index.
881: */
882: void
883: kread(nlx, addr, size)
884: int nlx;
885: void *addr;
886: size_t size;
887: {
888: char *sym;
889:
890: if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
891: sym = namelist[nlx].n_name;
892: if (*sym == '_')
893: ++sym;
894: (void)fprintf(stderr,
895: "vmstat: symbol %s not defined\n", sym);
896: exit(1);
897: }
898: if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
899: sym = namelist[nlx].n_name;
900: if (*sym == '_')
901: ++sym;
902: (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd));
903: exit(1);
904: }
905: }
906:
907: void
908: usage()
909: {
910: (void)fprintf(stderr,
911: #ifndef NEWVM
912: "usage: vmstat [-fimst] [-c count] [-M core] \
913: [-N system] [-w wait] [disks]\n");
914: #else
915: "usage: vmstat [-ims] [-c count] [-M core] \
916: [-N system] [-w wait] [disks]\n");
917: #endif
918: exit(1);
919: }
920: