Deleted Added
full compact
vmstat.c (7347) vmstat.c (7351)
1/*
2 * Copyright (c) 1980, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char copyright[] =
36"@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93";
42#endif /* not lint */
43
44#include <sys/param.h>
45#include <sys/time.h>
46#include <sys/proc.h>
47#include <sys/user.h>
48#include <sys/dkstat.h>
49#include <sys/buf.h>
50#include <sys/namei.h>
51#include <sys/malloc.h>
52#include <sys/signal.h>
53#include <sys/fcntl.h>
54#include <sys/ioctl.h>
55#include <sys/sysctl.h>
56#include <vm/vm.h>
57#include <time.h>
58#include <nlist.h>
59#include <kvm.h>
60#include <errno.h>
61#include <unistd.h>
62#include <stdio.h>
63#include <ctype.h>
64#include <stdlib.h>
65#include <string.h>
66#include <paths.h>
67#include <limits.h>
68
69struct nlist namelist[] = {
70#define X_CPTIME 0
71 { "_cp_time" },
72#define X_DK_NDRIVE 1
73 { "_dk_ndrive" },
74#define X_SUM 2
75 { "_cnt" },
76#define X_BOOTTIME 3
77 { "_boottime" },
78#define X_DKXFER 4
79 { "_dk_xfer" },
80#define X_HZ 5
81 { "_hz" },
82#define X_STATHZ 6
83 { "_stathz" },
84#define X_NCHSTATS 7
85 { "_nchstats" },
86#define X_INTRNAMES 8
87 { "_intrnames" },
88#define X_EINTRNAMES 9
89 { "_eintrnames" },
90#define X_INTRCNT 10
91 { "_intrcnt" },
92#define X_EINTRCNT 11
93 { "_eintrcnt" },
94#define X_KMEMSTAT 12
95 { "_kmemstats" },
96#define X_KMEMBUCKETS 13
97 { "_bucket" },
98#ifdef notdef
99#define X_DEFICIT 14
100 { "_deficit" },
101#define X_FORKSTAT 15
102 { "_forkstat" },
103#define X_REC 16
104 { "_rectime" },
105#define X_PGIN 17
106 { "_pgintime" },
107#define X_XSTATS 18
108 { "_xstats" },
109#define X_END 19
110#else
111#define X_END 14
112#endif
113#if defined(hp300) || defined(luna68k)
114#define X_HPDINIT (X_END)
115 { "_hp_dinit" },
116#endif
117#if defined(i386)
118#define X_DK_NAMES (X_END)
119 { "_dk_names" },
120#endif
121#ifdef mips
122#define X_SCSI_DINIT (X_END)
123 { "_scsi_dinit" },
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#ifdef vax
134#define X_MBDINIT (X_END)
135 { "_mbdinit" },
136#define X_UBDINIT (X_END+1)
137 { "_ubdinit" },
138#endif
139 { "" },
140};
141
142struct _disk {
143 long time[CPUSTATES];
144 long *xfer;
145} cur, last;
146
147struct vmmeter sum, osum;
148char **dr_name;
149int *dr_select, dk_ndrive, ndrives;
150
151int winlines = 20;
152
153kvm_t *kd;
154
155#define FORKSTAT 0x01
156#define INTRSTAT 0x02
157#define MEMSTAT 0x04
158#define SUMSTAT 0x08
159#define TIMESTAT 0x10
160#define VMSTAT 0x20
161
162#include "names.c" /* disk names -- machine dependent */
163
164void cpustats(), dkstats(), dointr(), domem(), dosum();
165void dovmstat(), kread(), usage();
166#ifdef notdef
167void dotimes(), doforkst();
168#endif
169
170main(argc, argv)
171 register int argc;
172 register char **argv;
173{
174 extern int optind;
175 extern char *optarg;
176 register int c, todo;
177 u_int interval;
178 int reps;
179 char *memf, *nlistf;
180 char errbuf[_POSIX2_LINE_MAX];
181
182 memf = nlistf = NULL;
183 interval = reps = todo = 0;
184 while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) {
185 switch (c) {
186 case 'c':
187 reps = atoi(optarg);
188 break;
189#ifndef notdef
190 case 'f':
191 todo |= FORKSTAT;
192 break;
193#endif
194 case 'i':
195 todo |= INTRSTAT;
196 break;
197 case 'M':
198 memf = optarg;
199 break;
200 case 'm':
201 todo |= MEMSTAT;
202 break;
203 case 'N':
204 nlistf = optarg;
205 break;
206 case 's':
207 todo |= SUMSTAT;
208 break;
209#ifndef notdef
210 case 't':
211 todo |= TIMESTAT;
212 break;
213#endif
214 case 'w':
215 interval = atoi(optarg);
216 break;
217 case '?':
218 default:
219 usage();
220 }
221 }
222 argc -= optind;
223 argv += optind;
224
225 if (todo == 0)
226 todo = VMSTAT;
227
228 /*
229 * Discard setgid privileges if not the running kernel so that bad
230 * guys can't print interesting stuff from kernel memory.
231 */
232 if (nlistf != NULL || memf != NULL)
233 setgid(getgid());
234
235 kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
236 if (kd == 0) {
237 (void)fprintf(stderr,
238 "vmstat: kvm_openfiles: %s\n", errbuf);
239 exit(1);
240 }
241
242 if ((c = kvm_nlist(kd, namelist)) != 0) {
243 if (c > 0) {
244 (void)fprintf(stderr,
245 "vmstat: undefined symbols:");
246 for (c = 0;
247 c < sizeof(namelist)/sizeof(namelist[0]); c++)
248 if (namelist[c].n_type == 0)
249 fprintf(stderr, " %s",
250 namelist[c].n_name);
251 (void)fputc('\n', stderr);
252 } else
253 (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
254 kvm_geterr(kd));
255 exit(1);
256 }
257
258 if (todo & VMSTAT) {
259 char **getdrivedata();
260 struct winsize winsize;
261
262 argv = getdrivedata(argv);
263 winsize.ws_row = 0;
264 (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
265 if (winsize.ws_row > 0)
266 winlines = winsize.ws_row;
267
268 }
269
270#define BACKWARD_COMPATIBILITY
271#ifdef BACKWARD_COMPATIBILITY
272 if (*argv) {
273 interval = atoi(*argv);
274 if (*++argv)
275 reps = atoi(*argv);
276 }
277#endif
278
279 if (interval) {
280 if (!reps)
281 reps = -1;
282 } else if (reps)
283 interval = 1;
284
285#ifdef notdef
286 if (todo & FORKSTAT)
287 doforkst();
288#endif
289 if (todo & MEMSTAT)
290 domem();
291 if (todo & SUMSTAT)
292 dosum();
293#ifdef notdef
294 if (todo & TIMESTAT)
295 dotimes();
296#endif
297 if (todo & INTRSTAT)
298 dointr();
299 if (todo & VMSTAT)
300 dovmstat(interval, reps);
301 exit(0);
302}
303
304char **
305getdrivedata(argv)
306 char **argv;
307{
308 register int i;
309 register char **cp;
310 char buf[30];
311
312 kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive));
313 if (dk_ndrive < 0) {
314 (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive);
315 exit(1);
316 }
317 dr_select = calloc((size_t)dk_ndrive, sizeof(int));
318 dr_name = calloc((size_t)dk_ndrive, sizeof(char *));
319 for (i = 0; i < dk_ndrive; i++)
320 dr_name[i] = NULL;
321 cur.xfer = calloc((size_t)dk_ndrive, sizeof(long));
322 last.xfer = calloc((size_t)dk_ndrive, sizeof(long));
323 if (!read_names())
324 exit (1);
325 for (i = 0; i < dk_ndrive; i++)
326 if (dr_name[i] == NULL) {
327 (void)sprintf(buf, "??%d", i);
328 dr_name[i] = strdup(buf);
329 }
330
331 /*
332 * Choose drives to be displayed. Priority goes to (in order) drives
333 * supplied as arguments, default drives. If everything isn't filled
334 * in and there are drives not taken care of, display the first few
335 * that fit.
336 */
337#define BACKWARD_COMPATIBILITY
338 for (ndrives = 0; *argv; ++argv) {
339#ifdef BACKWARD_COMPATIBILITY
340 if (isdigit(**argv))
341 break;
342#endif
343 for (i = 0; i < dk_ndrive; i++) {
344 if (strcmp(dr_name[i], *argv))
345 continue;
346 dr_select[i] = 1;
347 ++ndrives;
348 break;
349 }
350 }
351 for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
352 if (dr_select[i])
353 continue;
354 for (cp = defdrives; *cp; cp++)
355 if (strcmp(dr_name[i], *cp) == 0) {
356 dr_select[i] = 1;
357 ++ndrives;
358 break;
359 }
360 }
361 for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
362 if (dr_select[i])
363 continue;
364 dr_select[i] = 1;
365 ++ndrives;
366 }
367 return(argv);
368}
369
370long
371getuptime()
372{
373 static time_t now, boottime;
374 time_t uptime;
375
376 if (boottime == 0)
377 kread(X_BOOTTIME, &boottime, sizeof(boottime));
378 (void)time(&now);
379 uptime = now - boottime;
380 if (uptime <= 0 || uptime > 60*60*24*365*10) {
381 (void)fprintf(stderr,
382 "vmstat: time makes no sense; namelist must be wrong.\n");
383 exit(1);
384 }
385 return(uptime);
386}
387
388int hz, hdrcnt;
389
390void
391dovmstat(interval, reps)
392 u_int interval;
393 int reps;
394{
395 struct vmtotal total;
396 time_t uptime, halfuptime;
397 void needhdr();
398 int mib[2], size;
399
400 uptime = getuptime();
401 halfuptime = uptime / 2;
402 (void)signal(SIGCONT, needhdr);
403
404 if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
405 kread(X_STATHZ, &hz, sizeof(hz));
406 if (!hz)
407 kread(X_HZ, &hz, sizeof(hz));
408
409 for (hdrcnt = 1;;) {
410 if (!--hdrcnt)
411 printhdr();
412 kread(X_CPTIME, cur.time, sizeof(cur.time));
413 kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive);
414 kread(X_SUM, &sum, sizeof(sum));
415 size = sizeof(total);
416 mib[0] = CTL_VM;
417 mib[1] = VM_METER;
418 if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
419 printf("Can't get kerninfo: %s\n", strerror(errno));
420 bzero(&total, sizeof(total));
421 }
422 (void)printf("%2d%2d%2d",
423 total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
424#define pgtok(a) ((a) * sum.v_page_size >> 10)
425#define rate(x) (((x) + halfuptime) / uptime) /* round */
426 (void)printf("%6ld%6ld ",
427 pgtok(total.t_avm), pgtok(total.t_free));
428 (void)printf("%4lu ", rate(sum.v_vm_faults - osum.v_vm_faults));
429 (void)printf("%3lu ",
430 rate(sum.v_reactivated - osum.v_reactivated));
431 (void)printf("%3lu ", rate(sum.v_swapin + sum.v_vnodein -
432 (osum.v_swapin + osum.v_vnodein)));
433 (void)printf("%3lu ", rate(sum.v_swapout + sum.v_vnodeout -
434 (osum.v_swapout + osum.v_vnodeout)));
435 (void)printf("%3lu ", rate(sum.v_tfree - osum.v_tfree));
436 (void)printf("%3lu ", rate(sum.v_pdpages - osum.v_pdpages));
437 dkstats();
438 (void)printf("%4lu %4lu %3lu ",
439 rate(sum.v_intr - osum.v_intr),
440 rate(sum.v_syscall - osum.v_syscall),
441 rate(sum.v_swtch - osum.v_swtch));
442 cpustats();
443 (void)printf("\n");
444 (void)fflush(stdout);
445 if (reps >= 0 && --reps <= 0)
446 break;
447 osum = sum;
448 uptime = interval;
449 /*
450 * We round upward to avoid losing low-frequency events
451 * (i.e., >= 1 per interval but < 1 per second).
452 */
453 if (interval != 1)
454 halfuptime = (uptime + 1) / 2;
455 else
456 halfuptime = 0;
457 (void)sleep(interval);
458 }
459}
460
461printhdr()
462{
463 register int i;
464
465 (void)printf(" procs memory page%*s", 20, "");
466 if (ndrives > 1)
467 (void)printf("disks %*s faults cpu\n",
468 ndrives * 3 - 6, "");
469 else
470 (void)printf("%*s faults cpu\n", ndrives * 3, "");
471 (void)printf(" r b w avm fre flt re pi po fr sr ");
472 for (i = 0; i < dk_ndrive; i++)
473 if (dr_select[i])
474 (void)printf("%c%c ", dr_name[i][0],
475 dr_name[i][strlen(dr_name[i]) - 1]);
476 (void)printf(" in sy cs us sy id\n");
477 hdrcnt = winlines - 2;
478}
479
480/*
481 * Force a header to be prepended to the next output.
482 */
483void
484needhdr()
485{
486
487 hdrcnt = 1;
488}
489
490#ifdef notdef
491void
492dotimes()
493{
494 u_int pgintime, rectime;
495
496 kread(X_REC, &rectime, sizeof(rectime));
497 kread(X_PGIN, &pgintime, sizeof(pgintime));
498 kread(X_SUM, &sum, sizeof(sum));
499 (void)printf("%u reclaims, %u total time (usec)\n",
500 sum.v_pgrec, rectime);
501 (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec);
502 (void)printf("\n");
503 (void)printf("%u page ins, %u total time (msec)\n",
504 sum.v_pgin, pgintime / 10);
505 (void)printf("average: %8.1f msec / page in\n",
506 pgintime / (sum.v_pgin * 10.0));
507}
508#endif
509
510pct(top, bot)
511 long top, bot;
512{
513 long ans;
514
515 if (bot == 0)
516 return(0);
517 ans = (quad_t)top * 100 / bot;
518 return (ans);
519}
520
521#define PCT(top, bot) pct((long)(top), (long)(bot))
522
523#if defined(tahoe)
524#include <machine/cpu.h>
525#endif
526
527void
528dosum()
529{
530 struct nchstats nchstats;
531 long nchtotal;
532#if defined(tahoe)
533 struct keystats keystats;
534#endif
535
536 kread(X_SUM, &sum, sizeof(sum));
537 (void)printf("%9u cpu context switches\n", sum.v_swtch);
538 (void)printf("%9u device interrupts\n", sum.v_intr);
539 (void)printf("%9u software interrupts\n", sum.v_soft);
540#ifdef vax
541 (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma);
542#endif
543 (void)printf("%9u traps\n", sum.v_trap);
544 (void)printf("%9u system calls\n", sum.v_syscall);
545 (void)printf("%9u swap pager pageins\n", sum.v_swapin);
546 (void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin);
547 (void)printf("%9u swap pager pageouts\n", sum.v_swapout);
548 (void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout);
549 (void)printf("%9u vnode pager pageins\n", sum.v_vnodein);
550 (void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin);
551 (void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout);
552 (void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout);
1/*
2 * Copyright (c) 1980, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char copyright[] =
36"@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
37 The Regents of the University of California. All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93";
42#endif /* not lint */
43
44#include <sys/param.h>
45#include <sys/time.h>
46#include <sys/proc.h>
47#include <sys/user.h>
48#include <sys/dkstat.h>
49#include <sys/buf.h>
50#include <sys/namei.h>
51#include <sys/malloc.h>
52#include <sys/signal.h>
53#include <sys/fcntl.h>
54#include <sys/ioctl.h>
55#include <sys/sysctl.h>
56#include <vm/vm.h>
57#include <time.h>
58#include <nlist.h>
59#include <kvm.h>
60#include <errno.h>
61#include <unistd.h>
62#include <stdio.h>
63#include <ctype.h>
64#include <stdlib.h>
65#include <string.h>
66#include <paths.h>
67#include <limits.h>
68
69struct nlist namelist[] = {
70#define X_CPTIME 0
71 { "_cp_time" },
72#define X_DK_NDRIVE 1
73 { "_dk_ndrive" },
74#define X_SUM 2
75 { "_cnt" },
76#define X_BOOTTIME 3
77 { "_boottime" },
78#define X_DKXFER 4
79 { "_dk_xfer" },
80#define X_HZ 5
81 { "_hz" },
82#define X_STATHZ 6
83 { "_stathz" },
84#define X_NCHSTATS 7
85 { "_nchstats" },
86#define X_INTRNAMES 8
87 { "_intrnames" },
88#define X_EINTRNAMES 9
89 { "_eintrnames" },
90#define X_INTRCNT 10
91 { "_intrcnt" },
92#define X_EINTRCNT 11
93 { "_eintrcnt" },
94#define X_KMEMSTAT 12
95 { "_kmemstats" },
96#define X_KMEMBUCKETS 13
97 { "_bucket" },
98#ifdef notdef
99#define X_DEFICIT 14
100 { "_deficit" },
101#define X_FORKSTAT 15
102 { "_forkstat" },
103#define X_REC 16
104 { "_rectime" },
105#define X_PGIN 17
106 { "_pgintime" },
107#define X_XSTATS 18
108 { "_xstats" },
109#define X_END 19
110#else
111#define X_END 14
112#endif
113#if defined(hp300) || defined(luna68k)
114#define X_HPDINIT (X_END)
115 { "_hp_dinit" },
116#endif
117#if defined(i386)
118#define X_DK_NAMES (X_END)
119 { "_dk_names" },
120#endif
121#ifdef mips
122#define X_SCSI_DINIT (X_END)
123 { "_scsi_dinit" },
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#ifdef vax
134#define X_MBDINIT (X_END)
135 { "_mbdinit" },
136#define X_UBDINIT (X_END+1)
137 { "_ubdinit" },
138#endif
139 { "" },
140};
141
142struct _disk {
143 long time[CPUSTATES];
144 long *xfer;
145} cur, last;
146
147struct vmmeter sum, osum;
148char **dr_name;
149int *dr_select, dk_ndrive, ndrives;
150
151int winlines = 20;
152
153kvm_t *kd;
154
155#define FORKSTAT 0x01
156#define INTRSTAT 0x02
157#define MEMSTAT 0x04
158#define SUMSTAT 0x08
159#define TIMESTAT 0x10
160#define VMSTAT 0x20
161
162#include "names.c" /* disk names -- machine dependent */
163
164void cpustats(), dkstats(), dointr(), domem(), dosum();
165void dovmstat(), kread(), usage();
166#ifdef notdef
167void dotimes(), doforkst();
168#endif
169
170main(argc, argv)
171 register int argc;
172 register char **argv;
173{
174 extern int optind;
175 extern char *optarg;
176 register int c, todo;
177 u_int interval;
178 int reps;
179 char *memf, *nlistf;
180 char errbuf[_POSIX2_LINE_MAX];
181
182 memf = nlistf = NULL;
183 interval = reps = todo = 0;
184 while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) {
185 switch (c) {
186 case 'c':
187 reps = atoi(optarg);
188 break;
189#ifndef notdef
190 case 'f':
191 todo |= FORKSTAT;
192 break;
193#endif
194 case 'i':
195 todo |= INTRSTAT;
196 break;
197 case 'M':
198 memf = optarg;
199 break;
200 case 'm':
201 todo |= MEMSTAT;
202 break;
203 case 'N':
204 nlistf = optarg;
205 break;
206 case 's':
207 todo |= SUMSTAT;
208 break;
209#ifndef notdef
210 case 't':
211 todo |= TIMESTAT;
212 break;
213#endif
214 case 'w':
215 interval = atoi(optarg);
216 break;
217 case '?':
218 default:
219 usage();
220 }
221 }
222 argc -= optind;
223 argv += optind;
224
225 if (todo == 0)
226 todo = VMSTAT;
227
228 /*
229 * Discard setgid privileges if not the running kernel so that bad
230 * guys can't print interesting stuff from kernel memory.
231 */
232 if (nlistf != NULL || memf != NULL)
233 setgid(getgid());
234
235 kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
236 if (kd == 0) {
237 (void)fprintf(stderr,
238 "vmstat: kvm_openfiles: %s\n", errbuf);
239 exit(1);
240 }
241
242 if ((c = kvm_nlist(kd, namelist)) != 0) {
243 if (c > 0) {
244 (void)fprintf(stderr,
245 "vmstat: undefined symbols:");
246 for (c = 0;
247 c < sizeof(namelist)/sizeof(namelist[0]); c++)
248 if (namelist[c].n_type == 0)
249 fprintf(stderr, " %s",
250 namelist[c].n_name);
251 (void)fputc('\n', stderr);
252 } else
253 (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
254 kvm_geterr(kd));
255 exit(1);
256 }
257
258 if (todo & VMSTAT) {
259 char **getdrivedata();
260 struct winsize winsize;
261
262 argv = getdrivedata(argv);
263 winsize.ws_row = 0;
264 (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
265 if (winsize.ws_row > 0)
266 winlines = winsize.ws_row;
267
268 }
269
270#define BACKWARD_COMPATIBILITY
271#ifdef BACKWARD_COMPATIBILITY
272 if (*argv) {
273 interval = atoi(*argv);
274 if (*++argv)
275 reps = atoi(*argv);
276 }
277#endif
278
279 if (interval) {
280 if (!reps)
281 reps = -1;
282 } else if (reps)
283 interval = 1;
284
285#ifdef notdef
286 if (todo & FORKSTAT)
287 doforkst();
288#endif
289 if (todo & MEMSTAT)
290 domem();
291 if (todo & SUMSTAT)
292 dosum();
293#ifdef notdef
294 if (todo & TIMESTAT)
295 dotimes();
296#endif
297 if (todo & INTRSTAT)
298 dointr();
299 if (todo & VMSTAT)
300 dovmstat(interval, reps);
301 exit(0);
302}
303
304char **
305getdrivedata(argv)
306 char **argv;
307{
308 register int i;
309 register char **cp;
310 char buf[30];
311
312 kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive));
313 if (dk_ndrive < 0) {
314 (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive);
315 exit(1);
316 }
317 dr_select = calloc((size_t)dk_ndrive, sizeof(int));
318 dr_name = calloc((size_t)dk_ndrive, sizeof(char *));
319 for (i = 0; i < dk_ndrive; i++)
320 dr_name[i] = NULL;
321 cur.xfer = calloc((size_t)dk_ndrive, sizeof(long));
322 last.xfer = calloc((size_t)dk_ndrive, sizeof(long));
323 if (!read_names())
324 exit (1);
325 for (i = 0; i < dk_ndrive; i++)
326 if (dr_name[i] == NULL) {
327 (void)sprintf(buf, "??%d", i);
328 dr_name[i] = strdup(buf);
329 }
330
331 /*
332 * Choose drives to be displayed. Priority goes to (in order) drives
333 * supplied as arguments, default drives. If everything isn't filled
334 * in and there are drives not taken care of, display the first few
335 * that fit.
336 */
337#define BACKWARD_COMPATIBILITY
338 for (ndrives = 0; *argv; ++argv) {
339#ifdef BACKWARD_COMPATIBILITY
340 if (isdigit(**argv))
341 break;
342#endif
343 for (i = 0; i < dk_ndrive; i++) {
344 if (strcmp(dr_name[i], *argv))
345 continue;
346 dr_select[i] = 1;
347 ++ndrives;
348 break;
349 }
350 }
351 for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
352 if (dr_select[i])
353 continue;
354 for (cp = defdrives; *cp; cp++)
355 if (strcmp(dr_name[i], *cp) == 0) {
356 dr_select[i] = 1;
357 ++ndrives;
358 break;
359 }
360 }
361 for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
362 if (dr_select[i])
363 continue;
364 dr_select[i] = 1;
365 ++ndrives;
366 }
367 return(argv);
368}
369
370long
371getuptime()
372{
373 static time_t now, boottime;
374 time_t uptime;
375
376 if (boottime == 0)
377 kread(X_BOOTTIME, &boottime, sizeof(boottime));
378 (void)time(&now);
379 uptime = now - boottime;
380 if (uptime <= 0 || uptime > 60*60*24*365*10) {
381 (void)fprintf(stderr,
382 "vmstat: time makes no sense; namelist must be wrong.\n");
383 exit(1);
384 }
385 return(uptime);
386}
387
388int hz, hdrcnt;
389
390void
391dovmstat(interval, reps)
392 u_int interval;
393 int reps;
394{
395 struct vmtotal total;
396 time_t uptime, halfuptime;
397 void needhdr();
398 int mib[2], size;
399
400 uptime = getuptime();
401 halfuptime = uptime / 2;
402 (void)signal(SIGCONT, needhdr);
403
404 if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
405 kread(X_STATHZ, &hz, sizeof(hz));
406 if (!hz)
407 kread(X_HZ, &hz, sizeof(hz));
408
409 for (hdrcnt = 1;;) {
410 if (!--hdrcnt)
411 printhdr();
412 kread(X_CPTIME, cur.time, sizeof(cur.time));
413 kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive);
414 kread(X_SUM, &sum, sizeof(sum));
415 size = sizeof(total);
416 mib[0] = CTL_VM;
417 mib[1] = VM_METER;
418 if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
419 printf("Can't get kerninfo: %s\n", strerror(errno));
420 bzero(&total, sizeof(total));
421 }
422 (void)printf("%2d%2d%2d",
423 total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
424#define pgtok(a) ((a) * sum.v_page_size >> 10)
425#define rate(x) (((x) + halfuptime) / uptime) /* round */
426 (void)printf("%6ld%6ld ",
427 pgtok(total.t_avm), pgtok(total.t_free));
428 (void)printf("%4lu ", rate(sum.v_vm_faults - osum.v_vm_faults));
429 (void)printf("%3lu ",
430 rate(sum.v_reactivated - osum.v_reactivated));
431 (void)printf("%3lu ", rate(sum.v_swapin + sum.v_vnodein -
432 (osum.v_swapin + osum.v_vnodein)));
433 (void)printf("%3lu ", rate(sum.v_swapout + sum.v_vnodeout -
434 (osum.v_swapout + osum.v_vnodeout)));
435 (void)printf("%3lu ", rate(sum.v_tfree - osum.v_tfree));
436 (void)printf("%3lu ", rate(sum.v_pdpages - osum.v_pdpages));
437 dkstats();
438 (void)printf("%4lu %4lu %3lu ",
439 rate(sum.v_intr - osum.v_intr),
440 rate(sum.v_syscall - osum.v_syscall),
441 rate(sum.v_swtch - osum.v_swtch));
442 cpustats();
443 (void)printf("\n");
444 (void)fflush(stdout);
445 if (reps >= 0 && --reps <= 0)
446 break;
447 osum = sum;
448 uptime = interval;
449 /*
450 * We round upward to avoid losing low-frequency events
451 * (i.e., >= 1 per interval but < 1 per second).
452 */
453 if (interval != 1)
454 halfuptime = (uptime + 1) / 2;
455 else
456 halfuptime = 0;
457 (void)sleep(interval);
458 }
459}
460
461printhdr()
462{
463 register int i;
464
465 (void)printf(" procs memory page%*s", 20, "");
466 if (ndrives > 1)
467 (void)printf("disks %*s faults cpu\n",
468 ndrives * 3 - 6, "");
469 else
470 (void)printf("%*s faults cpu\n", ndrives * 3, "");
471 (void)printf(" r b w avm fre flt re pi po fr sr ");
472 for (i = 0; i < dk_ndrive; i++)
473 if (dr_select[i])
474 (void)printf("%c%c ", dr_name[i][0],
475 dr_name[i][strlen(dr_name[i]) - 1]);
476 (void)printf(" in sy cs us sy id\n");
477 hdrcnt = winlines - 2;
478}
479
480/*
481 * Force a header to be prepended to the next output.
482 */
483void
484needhdr()
485{
486
487 hdrcnt = 1;
488}
489
490#ifdef notdef
491void
492dotimes()
493{
494 u_int pgintime, rectime;
495
496 kread(X_REC, &rectime, sizeof(rectime));
497 kread(X_PGIN, &pgintime, sizeof(pgintime));
498 kread(X_SUM, &sum, sizeof(sum));
499 (void)printf("%u reclaims, %u total time (usec)\n",
500 sum.v_pgrec, rectime);
501 (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec);
502 (void)printf("\n");
503 (void)printf("%u page ins, %u total time (msec)\n",
504 sum.v_pgin, pgintime / 10);
505 (void)printf("average: %8.1f msec / page in\n",
506 pgintime / (sum.v_pgin * 10.0));
507}
508#endif
509
510pct(top, bot)
511 long top, bot;
512{
513 long ans;
514
515 if (bot == 0)
516 return(0);
517 ans = (quad_t)top * 100 / bot;
518 return (ans);
519}
520
521#define PCT(top, bot) pct((long)(top), (long)(bot))
522
523#if defined(tahoe)
524#include <machine/cpu.h>
525#endif
526
527void
528dosum()
529{
530 struct nchstats nchstats;
531 long nchtotal;
532#if defined(tahoe)
533 struct keystats keystats;
534#endif
535
536 kread(X_SUM, &sum, sizeof(sum));
537 (void)printf("%9u cpu context switches\n", sum.v_swtch);
538 (void)printf("%9u device interrupts\n", sum.v_intr);
539 (void)printf("%9u software interrupts\n", sum.v_soft);
540#ifdef vax
541 (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma);
542#endif
543 (void)printf("%9u traps\n", sum.v_trap);
544 (void)printf("%9u system calls\n", sum.v_syscall);
545 (void)printf("%9u swap pager pageins\n", sum.v_swapin);
546 (void)printf("%9u swap pager pages paged in\n", sum.v_swappgsin);
547 (void)printf("%9u swap pager pageouts\n", sum.v_swapout);
548 (void)printf("%9u swap pager pages paged out\n", sum.v_swappgsout);
549 (void)printf("%9u vnode pager pageins\n", sum.v_vnodein);
550 (void)printf("%9u vnode pager pages paged in\n", sum.v_vnodepgsin);
551 (void)printf("%9u vnode pager pageouts\n", sum.v_vnodeout);
552 (void)printf("%9u vnode pager pages paged out\n", sum.v_vnodepgsout);
553 (void)printf("%9u VM object cache lookups\n", sum.v_lookups);
554 (void)printf("%9u VM object hits\n", sum.v_hits);
555 (void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups);
556 (void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages);
557 (void)printf("%9u pages reactivated\n", sum.v_reactivated);
553 (void)printf("%9u page daemon wakeups\n", sum.v_pdwakeups);
554 (void)printf("%9u pages examined by the page daemon\n", sum.v_pdpages);
555 (void)printf("%9u pages reactivated\n", sum.v_reactivated);
558 (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
559 (void)printf("%9u zero fill pages zeroed\n", sum.v_zfod);
560 (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
556 (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
557 (void)printf("%9u zero fill pages zeroed\n", sum.v_zfod);
558 (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
561 (void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
562 (void)printf("%9u pages freed\n", sum.v_tfree);
563 (void)printf("%9u pages freed by daemon\n", sum.v_dfree);
564 (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
565 (void)printf("%9u pages active\n", sum.v_active_count);
566 (void)printf("%9u pages inactive\n", sum.v_inactive_count);
567 (void)printf("%9u pages in VM cache\n", sum.v_cache_count);
568 (void)printf("%9u pages wired down\n", sum.v_wire_count);
569 (void)printf("%9u pages free\n", sum.v_free_count);
570 (void)printf("%9u bytes per page\n", sum.v_page_size);
571 kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
572 nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
573 nchstats.ncs_badhits + nchstats.ncs_falsehits +
574 nchstats.ncs_miss + nchstats.ncs_long;
575 (void)printf("%9ld total name lookups\n", nchtotal);
576 (void)printf(
577 "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
578 "", PCT(nchstats.ncs_goodhits, nchtotal),
579 PCT(nchstats.ncs_neghits, nchtotal),
580 PCT(nchstats.ncs_pass2, nchtotal));
581 (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
582 PCT(nchstats.ncs_badhits, nchtotal),
583 PCT(nchstats.ncs_falsehits, nchtotal),
584 PCT(nchstats.ncs_long, nchtotal));
585#if defined(tahoe)
586 kread(X_CKEYSTATS, &keystats, sizeof(keystats));
587 (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
588 keystats.ks_allocs, "code cache keys allocated",
589 PCT(keystats.ks_allocfree, keystats.ks_allocs),
590 PCT(keystats.ks_norefs, keystats.ks_allocs),
591 PCT(keystats.ks_taken, keystats.ks_allocs),
592 PCT(keystats.ks_shared, keystats.ks_allocs));
593 kread(X_DKEYSTATS, &keystats, sizeof(keystats));
594 (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
595 keystats.ks_allocs, "data cache keys allocated",
596 PCT(keystats.ks_allocfree, keystats.ks_allocs),
597 PCT(keystats.ks_norefs, keystats.ks_allocs),
598 PCT(keystats.ks_taken, keystats.ks_allocs),
599 PCT(keystats.ks_shared, keystats.ks_allocs));
600#endif
601}
602
603#ifdef notdef
604void
605doforkst()
606{
607 struct forkstat fks;
608
609 kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
610 (void)printf("%d forks, %d pages, average %.2f\n",
611 fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
612 (void)printf("%d vforks, %d pages, average %.2f\n",
613 fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork);
614}
615#endif
616
617void
618dkstats()
619{
620 register int dn, state;
621 double etime;
622 long tmp;
623
624 for (dn = 0; dn < dk_ndrive; ++dn) {
625 tmp = cur.xfer[dn];
626 cur.xfer[dn] -= last.xfer[dn];
627 last.xfer[dn] = tmp;
628 }
629 etime = 0;
630 for (state = 0; state < CPUSTATES; ++state) {
631 tmp = cur.time[state];
632 cur.time[state] -= last.time[state];
633 last.time[state] = tmp;
634 etime += cur.time[state];
635 }
636 if (etime == 0)
637 etime = 1;
638 etime /= hz;
639 for (dn = 0; dn < dk_ndrive; ++dn) {
640 if (!dr_select[dn])
641 continue;
642 (void)printf("%2.0f ", cur.xfer[dn] / etime);
643 }
644}
645
646void
647cpustats()
648{
649 register int state;
650 double pct, total;
651
652 total = 0;
653 for (state = 0; state < CPUSTATES; ++state)
654 total += cur.time[state];
655 if (total)
656 pct = 100 / total;
657 else
658 pct = 0;
659 (void)printf("%2.0f ", (cur.time[CP_USER] + cur.time[CP_NICE]) * pct);
660 (void)printf("%2.0f ", (cur.time[CP_SYS] + cur.time[CP_INTR]) * pct);
661 (void)printf("%2.0f", cur.time[CP_IDLE] * pct);
662}
663
664void
665dointr()
666{
667 register long *intrcnt, inttotal, uptime;
668 register int nintr, inamlen;
669 register char *intrname;
670
671 uptime = getuptime();
672 nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
673 inamlen =
674 namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
675 intrcnt = malloc((size_t)nintr);
676 intrname = malloc((size_t)inamlen);
677 if (intrcnt == NULL || intrname == NULL) {
678 (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
679 exit(1);
680 }
681 kread(X_INTRCNT, intrcnt, (size_t)nintr);
682 kread(X_INTRNAMES, intrname, (size_t)inamlen);
683 (void)printf("interrupt total rate\n");
684 inttotal = 0;
685 nintr /= sizeof(long);
686 while (--nintr >= 0) {
687 if (*intrcnt)
688 (void)printf("%-12s %8ld %8ld\n", intrname,
689 *intrcnt, *intrcnt / uptime);
690 intrname += strlen(intrname) + 1;
691 inttotal += *intrcnt++;
692 }
693 (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
694}
695
696/*
697 * These names are defined in <sys/malloc.h>.
698 */
699char *kmemnames[] = INITKMEMNAMES;
700
701void
702domem()
703{
704 register struct kmembuckets *kp;
705 register struct kmemstats *ks;
706 register int i, j;
707 int len, size, first;
708 long totuse = 0, totfree = 0, totreq = 0;
709 char *name;
710 struct kmemstats kmemstats[M_LAST];
711 struct kmembuckets buckets[MINBUCKET + 16];
712
713 kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
714 (void)printf("Memory statistics by bucket size\n");
715 (void)printf(
716 "Size In Use Free Requests HighWater Couldfree\n");
717 for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
718 if (kp->kb_calls == 0)
719 continue;
720 size = 1 << i;
721 if(size < 1024)
722 (void)printf("%4d",size);
723 else
724 (void)printf("%3dK",size>>10);
725 (void)printf(" %8ld %6ld %10ld %7ld %10ld\n",
726 kp->kb_total - kp->kb_totalfree,
727 kp->kb_totalfree, kp->kb_calls,
728 kp->kb_highwat, kp->kb_couldfree);
729 totfree += size * kp->kb_totalfree;
730 }
731
732 kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
733 (void)printf("\nMemory usage type by bucket size\n");
734 (void)printf("Size Type(s)\n");
735 kp = &buckets[MINBUCKET];
736 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
737 if (kp->kb_calls == 0)
738 continue;
739 first = 1;
740 len = 8;
741 for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
742 if (ks->ks_calls == 0)
743 continue;
744 if ((ks->ks_size & j) == 0)
745 continue;
746 name = kmemnames[i] ? kmemnames[i] : "undefined";
747 len += 2 + strlen(name);
748 if (first && j < 1024)
749 printf("%4d %s", j, name);
750 else if (first)
751 printf("%3dK %s", j>>10, name);
752 else
753 printf(",");
754 if (len >= 79) {
755 printf("\n\t ");
756 len = 10 + strlen(name);
757 }
758 if (!first)
759 printf(" %s", name);
760 first = 0;
761 }
762 printf("\n");
763 }
764
765 (void)printf(
766 "\nMemory statistics by type Type Kern\n");
767 (void)printf(
768" Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
769 for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
770 if (ks->ks_calls == 0)
771 continue;
772 (void)printf("%13s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
773 kmemnames[i] ? kmemnames[i] : "undefined",
774 ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
775 (ks->ks_maxused + 1023) / 1024,
776 (ks->ks_limit + 1023) / 1024, ks->ks_calls,
777 ks->ks_limblocks, ks->ks_mapblocks);
778 first = 1;
779 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
780 if ((ks->ks_size & j) == 0)
781 continue;
782 if (first)
783 printf(" ");
784 else
785 printf(",");
786 if(j<1024)
787 printf("%d",j);
788 else
789 printf("%dK",j>>10);
790 first = 0;
791 }
792 printf("\n");
793 totuse += ks->ks_memuse;
794 totreq += ks->ks_calls;
795 }
796 (void)printf("\nMemory Totals: In Use Free Requests\n");
797 (void)printf(" %7ldK %6ldK %8ld\n",
798 (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
799}
800
801/*
802 * kread reads something from the kernel, given its nlist index.
803 */
804void
805kread(nlx, addr, size)
806 int nlx;
807 void *addr;
808 size_t size;
809{
810 char *sym;
811
812 if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
813 sym = namelist[nlx].n_name;
814 if (*sym == '_')
815 ++sym;
816 (void)fprintf(stderr,
817 "vmstat: symbol %s not defined\n", sym);
818 exit(1);
819 }
820 if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
821 sym = namelist[nlx].n_name;
822 if (*sym == '_')
823 ++sym;
824 (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd));
825 exit(1);
826 }
827}
828
829void
830usage()
831{
832 (void)fprintf(stderr,
833 "usage: vmstat [-ims] [-c count] [-M core] \
834[-N system] [-w wait] [disks]\n");
835 exit(1);
836}
559 (void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
560 (void)printf("%9u pages freed\n", sum.v_tfree);
561 (void)printf("%9u pages freed by daemon\n", sum.v_dfree);
562 (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
563 (void)printf("%9u pages active\n", sum.v_active_count);
564 (void)printf("%9u pages inactive\n", sum.v_inactive_count);
565 (void)printf("%9u pages in VM cache\n", sum.v_cache_count);
566 (void)printf("%9u pages wired down\n", sum.v_wire_count);
567 (void)printf("%9u pages free\n", sum.v_free_count);
568 (void)printf("%9u bytes per page\n", sum.v_page_size);
569 kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
570 nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
571 nchstats.ncs_badhits + nchstats.ncs_falsehits +
572 nchstats.ncs_miss + nchstats.ncs_long;
573 (void)printf("%9ld total name lookups\n", nchtotal);
574 (void)printf(
575 "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
576 "", PCT(nchstats.ncs_goodhits, nchtotal),
577 PCT(nchstats.ncs_neghits, nchtotal),
578 PCT(nchstats.ncs_pass2, nchtotal));
579 (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
580 PCT(nchstats.ncs_badhits, nchtotal),
581 PCT(nchstats.ncs_falsehits, nchtotal),
582 PCT(nchstats.ncs_long, nchtotal));
583#if defined(tahoe)
584 kread(X_CKEYSTATS, &keystats, sizeof(keystats));
585 (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
586 keystats.ks_allocs, "code cache keys allocated",
587 PCT(keystats.ks_allocfree, keystats.ks_allocs),
588 PCT(keystats.ks_norefs, keystats.ks_allocs),
589 PCT(keystats.ks_taken, keystats.ks_allocs),
590 PCT(keystats.ks_shared, keystats.ks_allocs));
591 kread(X_DKEYSTATS, &keystats, sizeof(keystats));
592 (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
593 keystats.ks_allocs, "data cache keys allocated",
594 PCT(keystats.ks_allocfree, keystats.ks_allocs),
595 PCT(keystats.ks_norefs, keystats.ks_allocs),
596 PCT(keystats.ks_taken, keystats.ks_allocs),
597 PCT(keystats.ks_shared, keystats.ks_allocs));
598#endif
599}
600
601#ifdef notdef
602void
603doforkst()
604{
605 struct forkstat fks;
606
607 kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
608 (void)printf("%d forks, %d pages, average %.2f\n",
609 fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
610 (void)printf("%d vforks, %d pages, average %.2f\n",
611 fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork);
612}
613#endif
614
615void
616dkstats()
617{
618 register int dn, state;
619 double etime;
620 long tmp;
621
622 for (dn = 0; dn < dk_ndrive; ++dn) {
623 tmp = cur.xfer[dn];
624 cur.xfer[dn] -= last.xfer[dn];
625 last.xfer[dn] = tmp;
626 }
627 etime = 0;
628 for (state = 0; state < CPUSTATES; ++state) {
629 tmp = cur.time[state];
630 cur.time[state] -= last.time[state];
631 last.time[state] = tmp;
632 etime += cur.time[state];
633 }
634 if (etime == 0)
635 etime = 1;
636 etime /= hz;
637 for (dn = 0; dn < dk_ndrive; ++dn) {
638 if (!dr_select[dn])
639 continue;
640 (void)printf("%2.0f ", cur.xfer[dn] / etime);
641 }
642}
643
644void
645cpustats()
646{
647 register int state;
648 double pct, total;
649
650 total = 0;
651 for (state = 0; state < CPUSTATES; ++state)
652 total += cur.time[state];
653 if (total)
654 pct = 100 / total;
655 else
656 pct = 0;
657 (void)printf("%2.0f ", (cur.time[CP_USER] + cur.time[CP_NICE]) * pct);
658 (void)printf("%2.0f ", (cur.time[CP_SYS] + cur.time[CP_INTR]) * pct);
659 (void)printf("%2.0f", cur.time[CP_IDLE] * pct);
660}
661
662void
663dointr()
664{
665 register long *intrcnt, inttotal, uptime;
666 register int nintr, inamlen;
667 register char *intrname;
668
669 uptime = getuptime();
670 nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
671 inamlen =
672 namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
673 intrcnt = malloc((size_t)nintr);
674 intrname = malloc((size_t)inamlen);
675 if (intrcnt == NULL || intrname == NULL) {
676 (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
677 exit(1);
678 }
679 kread(X_INTRCNT, intrcnt, (size_t)nintr);
680 kread(X_INTRNAMES, intrname, (size_t)inamlen);
681 (void)printf("interrupt total rate\n");
682 inttotal = 0;
683 nintr /= sizeof(long);
684 while (--nintr >= 0) {
685 if (*intrcnt)
686 (void)printf("%-12s %8ld %8ld\n", intrname,
687 *intrcnt, *intrcnt / uptime);
688 intrname += strlen(intrname) + 1;
689 inttotal += *intrcnt++;
690 }
691 (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
692}
693
694/*
695 * These names are defined in <sys/malloc.h>.
696 */
697char *kmemnames[] = INITKMEMNAMES;
698
699void
700domem()
701{
702 register struct kmembuckets *kp;
703 register struct kmemstats *ks;
704 register int i, j;
705 int len, size, first;
706 long totuse = 0, totfree = 0, totreq = 0;
707 char *name;
708 struct kmemstats kmemstats[M_LAST];
709 struct kmembuckets buckets[MINBUCKET + 16];
710
711 kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
712 (void)printf("Memory statistics by bucket size\n");
713 (void)printf(
714 "Size In Use Free Requests HighWater Couldfree\n");
715 for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
716 if (kp->kb_calls == 0)
717 continue;
718 size = 1 << i;
719 if(size < 1024)
720 (void)printf("%4d",size);
721 else
722 (void)printf("%3dK",size>>10);
723 (void)printf(" %8ld %6ld %10ld %7ld %10ld\n",
724 kp->kb_total - kp->kb_totalfree,
725 kp->kb_totalfree, kp->kb_calls,
726 kp->kb_highwat, kp->kb_couldfree);
727 totfree += size * kp->kb_totalfree;
728 }
729
730 kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
731 (void)printf("\nMemory usage type by bucket size\n");
732 (void)printf("Size Type(s)\n");
733 kp = &buckets[MINBUCKET];
734 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
735 if (kp->kb_calls == 0)
736 continue;
737 first = 1;
738 len = 8;
739 for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
740 if (ks->ks_calls == 0)
741 continue;
742 if ((ks->ks_size & j) == 0)
743 continue;
744 name = kmemnames[i] ? kmemnames[i] : "undefined";
745 len += 2 + strlen(name);
746 if (first && j < 1024)
747 printf("%4d %s", j, name);
748 else if (first)
749 printf("%3dK %s", j>>10, name);
750 else
751 printf(",");
752 if (len >= 79) {
753 printf("\n\t ");
754 len = 10 + strlen(name);
755 }
756 if (!first)
757 printf(" %s", name);
758 first = 0;
759 }
760 printf("\n");
761 }
762
763 (void)printf(
764 "\nMemory statistics by type Type Kern\n");
765 (void)printf(
766" Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
767 for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
768 if (ks->ks_calls == 0)
769 continue;
770 (void)printf("%13s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
771 kmemnames[i] ? kmemnames[i] : "undefined",
772 ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
773 (ks->ks_maxused + 1023) / 1024,
774 (ks->ks_limit + 1023) / 1024, ks->ks_calls,
775 ks->ks_limblocks, ks->ks_mapblocks);
776 first = 1;
777 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
778 if ((ks->ks_size & j) == 0)
779 continue;
780 if (first)
781 printf(" ");
782 else
783 printf(",");
784 if(j<1024)
785 printf("%d",j);
786 else
787 printf("%dK",j>>10);
788 first = 0;
789 }
790 printf("\n");
791 totuse += ks->ks_memuse;
792 totreq += ks->ks_calls;
793 }
794 (void)printf("\nMemory Totals: In Use Free Requests\n");
795 (void)printf(" %7ldK %6ldK %8ld\n",
796 (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
797}
798
799/*
800 * kread reads something from the kernel, given its nlist index.
801 */
802void
803kread(nlx, addr, size)
804 int nlx;
805 void *addr;
806 size_t size;
807{
808 char *sym;
809
810 if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
811 sym = namelist[nlx].n_name;
812 if (*sym == '_')
813 ++sym;
814 (void)fprintf(stderr,
815 "vmstat: symbol %s not defined\n", sym);
816 exit(1);
817 }
818 if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
819 sym = namelist[nlx].n_name;
820 if (*sym == '_')
821 ++sym;
822 (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd));
823 exit(1);
824 }
825}
826
827void
828usage()
829{
830 (void)fprintf(stderr,
831 "usage: vmstat [-ims] [-c count] [-M core] \
832[-N system] [-w wait] [disks]\n");
833 exit(1);
834}