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