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