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