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