1 /* 2 * Copyright (c) 1980, 1986, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1980, 1986, 1991 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)vmstat.c 5.33 (Berkeley) 01/27/92"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/time.h> 20 #include <sys/proc.h> 21 #include <sys/user.h> 22 #include <sys/dkstat.h> 23 #include <sys/buf.h> 24 #include <sys/namei.h> 25 #include <sys/malloc.h> 26 #include <sys/signal.h> 27 #include <sys/fcntl.h> 28 #include <sys/ioctl.h> 29 #include <sys/kinfo.h> 30 #include <vm/vm.h> 31 #include <time.h> 32 #include <nlist.h> 33 #include <kvm.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <stdio.h> 37 #include <ctype.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <paths.h> 41 42 #define NEWVM /* XXX till old has been updated or purged */ 43 struct nlist nl[] = { 44 #define X_CPTIME 0 45 { "_cp_time" }, 46 #define X_DK_NDRIVE 1 47 { "_dk_ndrive" }, 48 #define X_SUM 2 49 { "_cnt" }, 50 #define X_BOOTTIME 3 51 { "_boottime" }, 52 #define X_DKXFER 4 53 { "_dk_xfer" }, 54 #define X_HZ 5 55 { "_hz" }, 56 #define X_PHZ 6 57 { "_phz" }, 58 #define X_NCHSTATS 7 59 { "_nchstats" }, 60 #define X_INTRNAMES 8 61 { "_intrnames" }, 62 #define X_EINTRNAMES 9 63 { "_eintrnames" }, 64 #define X_INTRCNT 10 65 { "_intrcnt" }, 66 #define X_EINTRCNT 11 67 { "_eintrcnt" }, 68 #define X_KMEMSTAT 12 69 { "_kmemstats" }, 70 #define X_KMEMBUCKETS 13 71 { "_bucket" }, 72 #ifdef notdef 73 #define X_DEFICIT 14 74 { "_deficit" }, 75 #define X_FORKSTAT 15 76 { "_forkstat" }, 77 #define X_REC 16 78 { "_rectime" }, 79 #define X_PGIN 17 80 { "_pgintime" }, 81 #define X_XSTATS 18 82 { "_xstats" }, 83 #define X_END 18 84 #else 85 #define X_END 14 86 #endif 87 #ifdef hp300 88 #define X_HPDINIT (X_END) 89 { "_hp_dinit" }, 90 #endif 91 #ifdef tahoe 92 #define X_VBDINIT (X_END) 93 { "_vbdinit" }, 94 #define X_CKEYSTATS (X_END+1) 95 { "_ckeystats" }, 96 #define X_DKEYSTATS (X_END+2) 97 { "_dkeystats" }, 98 #endif 99 #ifdef vax 100 #define X_MBDINIT (X_END) 101 { "_mbdinit" }, 102 #define X_UBDINIT (X_END+1) 103 { "_ubdinit" }, 104 #endif 105 { "" }, 106 }; 107 108 struct _disk { 109 long time[CPUSTATES]; 110 long *xfer; 111 } cur, last; 112 113 struct vmmeter sum, osum; 114 char **dr_name; 115 int *dr_select, dk_ndrive, ndrives; 116 117 int winlines = 20; 118 119 #define FORKSTAT 0x01 120 #define INTRSTAT 0x02 121 #define MEMSTAT 0x04 122 #define SUMSTAT 0x08 123 #define TIMESTAT 0x10 124 #define VMSTAT 0x20 125 126 #include "names.c" /* disk names -- machine dependent */ 127 128 void cpustats(), dkstats(), dointr(), domem(), dosum(); 129 void dovmstat(), kread(), usage(); 130 #ifdef notdef 131 void dotimes(), doforkst(); 132 #endif 133 134 main(argc, argv) 135 register int argc; 136 register char **argv; 137 { 138 extern int optind; 139 extern char *optarg; 140 register int c, todo; 141 u_int interval; 142 int reps; 143 char *memf, *nlistf; 144 145 memf = nlistf = NULL; 146 interval = reps = todo = 0; 147 while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) { 148 switch (c) { 149 case 'c': 150 reps = atoi(optarg); 151 break; 152 #ifndef notdef 153 case 'f': 154 todo |= FORKSTAT; 155 break; 156 #endif 157 case 'i': 158 todo |= INTRSTAT; 159 break; 160 case 'M': 161 memf = optarg; 162 break; 163 case 'm': 164 todo |= MEMSTAT; 165 break; 166 case 'N': 167 nlistf = optarg; 168 break; 169 case 's': 170 todo |= SUMSTAT; 171 break; 172 #ifndef notdef 173 case 't': 174 todo |= TIMESTAT; 175 break; 176 #endif 177 case 'w': 178 interval = atoi(optarg); 179 break; 180 case '?': 181 default: 182 usage(); 183 } 184 } 185 argc -= optind; 186 argv += optind; 187 188 if (todo == 0) 189 todo = VMSTAT; 190 191 /* 192 * Discard setgid privileges if not the running kernel so that bad 193 * guys can't print interesting stuff from kernel memory. 194 */ 195 if (nlistf != NULL || memf != NULL) 196 setgid(getgid()); 197 198 if (kvm_openfiles(nlistf, memf, NULL) < 0) { 199 (void)fprintf(stderr, 200 "vmstat: kvm_openfiles: %s\n", kvm_geterr()); 201 exit(1); 202 } 203 204 if ((c = kvm_nlist(nl)) != 0) { 205 if (c > 0) { 206 (void)fprintf(stderr, 207 "vmstat: undefined symbols: "); 208 for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++) 209 if (nl[c].n_type == 0) 210 printf(" %s", nl[c].n_name); 211 (void)fputc('\n', stderr); 212 } else 213 (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n", 214 kvm_geterr()); 215 exit(1); 216 } 217 218 if (todo & VMSTAT) { 219 char **getdrivedata(); 220 struct winsize winsize; 221 222 argv = getdrivedata(argv); 223 winsize.ws_row = 0; 224 (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize); 225 if (winsize.ws_row > 0) 226 winlines = winsize.ws_row; 227 228 } 229 230 #define BACKWARD_COMPATIBILITY 231 #ifdef BACKWARD_COMPATIBILITY 232 if (*argv) { 233 interval = atoi(*argv); 234 if (*++argv) 235 reps = atoi(*argv); 236 } 237 #endif 238 239 if (interval) { 240 if (!reps) 241 reps = -1; 242 } else if (reps) 243 interval = 1; 244 245 #ifdef notdef 246 if (todo & FORKSTAT) 247 doforkst(); 248 #endif 249 if (todo & MEMSTAT) 250 domem(); 251 if (todo & SUMSTAT) 252 dosum(); 253 #ifdef notdef 254 if (todo & TIMESTAT) 255 dotimes(); 256 #endif 257 if (todo & INTRSTAT) 258 dointr(); 259 if (todo & VMSTAT) 260 dovmstat(interval, reps); 261 exit(0); 262 } 263 264 char ** 265 getdrivedata(argv) 266 char **argv; 267 { 268 register int i; 269 register char **cp; 270 char buf[30]; 271 272 kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 273 if (dk_ndrive <= 0) { 274 (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 275 exit(1); 276 } 277 dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 278 dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 279 for (i = 0; i < dk_ndrive; i++) 280 dr_name[i] = NULL; 281 cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 282 last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 283 read_names(); 284 for (i = 0; i < dk_ndrive; i++) 285 if (dr_name[i] == NULL) { 286 (void)sprintf(buf, "??%d", i); 287 dr_name[i] = strdup(buf); 288 } 289 290 /* 291 * Choose drives to be displayed. Priority goes to (in order) drives 292 * supplied as arguments, default drives. If everything isn't filled 293 * in and there are drives not taken care of, display the first few 294 * that fit. 295 */ 296 #define BACKWARD_COMPATIBILITY 297 for (ndrives = 0; *argv; ++argv) { 298 #ifdef BACKWARD_COMPATIBILITY 299 if (isdigit(**argv)) 300 break; 301 #endif 302 for (i = 0; i < dk_ndrive; i++) { 303 if (strcmp(dr_name[i], *argv)) 304 continue; 305 dr_select[i] = 1; 306 ++ndrives; 307 break; 308 } 309 } 310 for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 311 if (dr_select[i]) 312 continue; 313 for (cp = defdrives; *cp; cp++) 314 if (strcmp(dr_name[i], *cp) == 0) { 315 dr_select[i] = 1; 316 ++ndrives; 317 break; 318 } 319 } 320 for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 321 if (dr_select[i]) 322 continue; 323 dr_select[i] = 1; 324 ++ndrives; 325 } 326 return(argv); 327 } 328 329 long 330 getuptime() 331 { 332 static time_t now, boottime; 333 time_t uptime; 334 335 if (boottime == 0) 336 kread(X_BOOTTIME, &boottime, sizeof(boottime)); 337 (void)time(&now); 338 uptime = now - boottime; 339 if (uptime <= 0 || uptime > 60*60*24*365*10) { 340 (void)fprintf(stderr, 341 "vmstat: time makes no sense; namelist must be wrong.\n"); 342 exit(1); 343 } 344 return(uptime); 345 } 346 347 int hz, hdrcnt; 348 349 void 350 dovmstat(interval, reps) 351 u_int interval; 352 int reps; 353 { 354 struct vmtotal total; 355 time_t uptime, halfuptime; 356 void needhdr(); 357 int size; 358 359 uptime = getuptime(); 360 halfuptime = uptime / 2; 361 (void)signal(SIGCONT, needhdr); 362 363 if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 364 kread(X_PHZ, &hz, sizeof(hz)); 365 if (!hz) 366 kread(X_HZ, &hz, sizeof(hz)); 367 368 for (hdrcnt = 1;;) { 369 if (!--hdrcnt) 370 printhdr(); 371 kread(X_CPTIME, cur.time, sizeof(cur.time)); 372 kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 373 kread(X_SUM, &sum, sizeof(sum)); 374 size = sizeof(total); 375 if (getkerninfo(KINFO_METER, &total, &size, 0) < 0) { 376 printf("Can't get kerninfo: %s\n", strerror(errno)); 377 bzero(&total, sizeof(total)); 378 } 379 (void)printf("%2d%2d%2d", 380 total.t_rq, total.t_dw + total.t_pw, total.t_sw); 381 #define pgtok(a) ((a) * sum.v_page_size >> 10) 382 #define rate(x) (((x) + halfuptime) / uptime) /* round */ 383 (void)printf("%6ld%6ld ", 384 pgtok(total.t_avm), pgtok(total.t_free)); 385 #ifdef NEWVM 386 (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults)); 387 (void)printf("%3lu ", 388 rate(sum.v_reactivated - osum.v_reactivated)); 389 (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins)); 390 (void)printf("%3lu %3lu ", 391 rate(sum.v_pageouts - osum.v_pageouts), 0); 392 #else 393 (void)printf("%3lu %2lu ", 394 rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - 395 (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))), 396 rate(sum.v_xsfrec + sum.v_xifrec - 397 osum.v_xsfrec - osum.v_xifrec)); 398 (void)printf("%3lu ", 399 rate(pgtok(sum.v_pgpgin - osum.v_pgpgin))); 400 (void)printf("%3lu %3lu ", 401 rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)), 402 rate(pgtok(sum.v_dfree - osum.v_dfree))); 403 (void)printf("%3d ", pgtok(deficit)); 404 #endif 405 (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan)); 406 dkstats(); 407 (void)printf("%4lu %4lu %3lu ", 408 rate(sum.v_intr - osum.v_intr), 409 rate(sum.v_syscall - osum.v_syscall), 410 rate(sum.v_swtch - osum.v_swtch)); 411 cpustats(); 412 (void)printf("\n"); 413 (void)fflush(stdout); 414 if (reps >= 0 && --reps <= 0) 415 break; 416 osum = sum; 417 uptime = interval; 418 /* 419 * We round upward to avoid losing low-frequency events 420 * (i.e., >= 1 per interval but < 1 per second). 421 */ 422 halfuptime = (uptime + 1) / 2; 423 (void)sleep(interval); 424 } 425 } 426 427 printhdr() 428 { 429 register int i; 430 431 (void)printf(" procs memory page%*s", 20, ""); 432 if (ndrives > 1) 433 (void)printf("disks %*s faults cpu\n", 434 ndrives * 3 - 6, ""); 435 else 436 (void)printf("%*s faults cpu\n", ndrives * 3, ""); 437 #ifndef NEWVM 438 (void)printf(" r b w avm fre re at pi po fr de sr "); 439 #else 440 (void)printf(" r b w avm fre flt re pi po fr sr "); 441 #endif 442 for (i = 0; i < dk_ndrive; i++) 443 if (dr_select[i]) 444 (void)printf("%c%c ", dr_name[i][0], 445 dr_name[i][strlen(dr_name[i]) - 1]); 446 (void)printf(" in sy cs us sy id\n"); 447 hdrcnt = winlines - 2; 448 } 449 450 /* 451 * Force a header to be prepended to the next output. 452 */ 453 void 454 needhdr() 455 { 456 457 hdrcnt = 1; 458 } 459 460 #ifdef notdef 461 void 462 dotimes() 463 { 464 u_int pgintime, rectime; 465 466 kread(X_REC, &rectime, sizeof(rectime)); 467 kread(X_PGIN, &pgintime, sizeof(pgintime)); 468 kread(X_SUM, &sum, sizeof(sum)); 469 (void)printf("%u reclaims, %u total time (usec)\n", 470 sum.v_pgrec, rectime); 471 (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 472 (void)printf("\n"); 473 (void)printf("%u page ins, %u total time (msec)\n", 474 sum.v_pgin, pgintime / 10); 475 (void)printf("average: %8.1f msec / page in\n", 476 pgintime / (sum.v_pgin * 10.0)); 477 } 478 #endif 479 480 pct(top, bot) 481 long top, bot; 482 { 483 if (bot == 0) 484 return(0); 485 return((top * 100) / bot); 486 } 487 488 #define PCT(top, bot) pct((long)(top), (long)(bot)) 489 490 #if defined(tahoe) 491 #include <machine/cpu.h> 492 #endif 493 494 void 495 dosum() 496 { 497 struct nchstats nchstats; 498 #ifndef NEWVM 499 struct xstats xstats; 500 #endif 501 long nchtotal; 502 #if defined(tahoe) 503 struct keystats keystats; 504 #endif 505 506 kread(X_SUM, &sum, sizeof(sum)); 507 (void)printf("%9u cpu context switches\n", sum.v_swtch); 508 (void)printf("%9u device interrupts\n", sum.v_intr); 509 (void)printf("%9u software interrupts\n", sum.v_soft); 510 #ifdef vax 511 (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 512 #endif 513 (void)printf("%9u traps\n", sum.v_trap); 514 (void)printf("%9u system calls\n", sum.v_syscall); 515 (void)printf("%9u total faults taken\n", sum.v_faults); 516 (void)printf("%9u swap ins\n", sum.v_swpin); 517 (void)printf("%9u swap outs\n", sum.v_swpout); 518 (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 519 (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 520 (void)printf("%9u page ins\n", sum.v_pageins); 521 (void)printf("%9u page outs\n", sum.v_pageouts); 522 (void)printf("%9u pages paged in\n", sum.v_pgpgin); 523 (void)printf("%9u pages paged out\n", sum.v_pgpgout); 524 (void)printf("%9u pages reactivated\n", sum.v_reactivated); 525 (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 526 (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 527 (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 528 (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 529 (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 530 #ifdef NEWVM 531 (void)printf("%9u VM object cache lookups\n", sum.v_lookups); 532 (void)printf("%9u VM object hits\n", sum.v_hits); 533 (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 534 (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 535 (void)printf("%9u pages freed by daemon\n", sum.v_dfree); 536 (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree); 537 (void)printf("%9u pages free\n", sum.v_free_count); 538 (void)printf("%9u pages wired down\n", sum.v_wire_count); 539 (void)printf("%9u pages active\n", sum.v_active_count); 540 (void)printf("%9u pages inactive\n", sum.v_inactive_count); 541 (void)printf("%9u bytes per page\n", sum.v_page_size); 542 #else 543 (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 544 (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 545 PCT(sum.v_fastpgrec, sum.v_pgrec)); 546 (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 547 (void)printf("%9u executable fill pages created\n", 548 sum.v_nexfod / CLSIZE); 549 (void)printf("%9u executable fill page faults\n", 550 sum.v_exfod / CLSIZE); 551 (void)printf("%9u swap text pages found in free list\n", 552 sum.v_xsfrec); 553 (void)printf("%9u inode text pages found in free list\n", 554 sum.v_xifrec); 555 (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 556 (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 557 (void)printf("%9u pages freed by the clock daemon\n", 558 sum.v_dfree / CLSIZE); 559 #endif 560 kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 561 nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 562 nchstats.ncs_badhits + nchstats.ncs_falsehits + 563 nchstats.ncs_miss + nchstats.ncs_long; 564 (void)printf("%9ld total name lookups\n", nchtotal); 565 (void)printf( 566 "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 567 "", PCT(nchstats.ncs_goodhits, nchtotal), 568 PCT(nchstats.ncs_neghits, nchtotal), 569 PCT(nchstats.ncs_pass2, nchtotal)); 570 (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 571 PCT(nchstats.ncs_badhits, nchtotal), 572 PCT(nchstats.ncs_falsehits, nchtotal), 573 PCT(nchstats.ncs_long, nchtotal)); 574 #ifndef NEWVM 575 kread(X_XSTATS, &xstats, sizeof(xstats)); 576 (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 577 xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 578 (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 579 xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 580 (void)printf("%9lu total calls to xfree", xstats.free); 581 (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 582 xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 583 #endif 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 603 void 604 doforkst() 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 616 void 617 dkstats() 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 645 void 646 cpustats() 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 ", /* user + nice */ 659 (cur.time[0] + cur.time[1]) * pct); 660 (void)printf("%2.0f ", cur.time[2] * pct); /* system */ 661 (void)printf("%2.0f", cur.time[3] * pct); /* idle */ 662 } 663 664 void 665 dointr() 666 { 667 register long *intrcnt, inttotal, uptime; 668 register int nintr, inamlen; 669 register char *intrname; 670 671 uptime = getuptime(); 672 nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 673 inamlen = nl[X_EINTRNAMES].n_value - nl[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 */ 698 char *kmemnames[] = INITKMEMNAMES; 699 700 void 701 domem() 702 { 703 register struct kmembuckets *kp; 704 register struct kmemstats *ks; 705 register int i; 706 int size; 707 long totuse = 0, totfree = 0, totreq = 0; 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 (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, 720 kp->kb_total - kp->kb_totalfree, 721 kp->kb_totalfree, kp->kb_calls, 722 kp->kb_highwat, kp->kb_couldfree); 723 totfree += size * kp->kb_totalfree; 724 } 725 726 kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 727 (void)printf("\nMemory statistics by type\n"); 728 (void)printf( 729 " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 730 for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 731 if (ks->ks_calls == 0) 732 continue; 733 (void)printf("%10s %6ld %7ldK %8ldK %5ldK %8ld %6u %9u\n", 734 kmemnames[i] ? kmemnames[i] : "undefined", 735 ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 736 (ks->ks_maxused + 1023) / 1024, 737 (ks->ks_limit + 1023) / 1024, ks->ks_calls, 738 ks->ks_limblocks, ks->ks_mapblocks); 739 totuse += ks->ks_memuse; 740 totreq += ks->ks_calls; 741 } 742 (void)printf("\nMemory Totals: In Use Free Requests\n"); 743 (void)printf(" %7ldK %6ldK %8ld\n", 744 (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 745 } 746 747 /* 748 * kread reads something from the kernel, given its nlist index. 749 */ 750 void 751 kread(nlx, addr, size) 752 int nlx; 753 void *addr; 754 size_t size; 755 { 756 char *sym; 757 758 if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 759 sym = nl[nlx].n_name; 760 if (*sym == '_') 761 ++sym; 762 (void)fprintf(stderr, 763 "vmstat: symbol %s not defined\n", sym); 764 exit(1); 765 } 766 if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { 767 sym = nl[nlx].n_name; 768 if (*sym == '_') 769 ++sym; 770 (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); 771 exit(1); 772 } 773 } 774 775 void 776 usage() 777 { 778 (void)fprintf(stderr, 779 #ifndef NEWVM 780 "usage: vmstat [-fimst] [-c count] [-M core] \ 781 [-N system] [-w wait] [disks]\n"); 782 #else 783 "usage: vmstat [-ims] [-c count] [-M core] \ 784 [-N system] [-w wait] [disks]\n"); 785 #endif 786 exit(1); 787 } 788