1 /* $NetBSD: vmstat.c,v 1.31 1996/08/08 04:11:27 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1986, 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef lint 37 static char copyright[] = 38 "@(#) Copyright (c) 1980, 1986, 1991, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"; 40 #endif /* not lint */ 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "@(#)vmstat.c 8.1 (Berkeley) 6/6/93"; 45 #else 46 static char rcsid[] = "$NetBSD: vmstat.c,v 1.31 1996/08/08 04:11:27 mycroft Exp $"; 47 #endif 48 #endif /* not lint */ 49 50 #include <sys/param.h> 51 #include <sys/time.h> 52 #include <sys/proc.h> 53 #include <sys/user.h> 54 #include <sys/dkstat.h> 55 #include <sys/buf.h> 56 #include <sys/namei.h> 57 #include <sys/malloc.h> 58 #include <sys/fcntl.h> 59 #include <sys/ioctl.h> 60 #include <sys/sysctl.h> 61 #include <sys/device.h> 62 #include <vm/vm.h> 63 #include <time.h> 64 #include <nlist.h> 65 #include <kvm.h> 66 #include <errno.h> 67 #include <unistd.h> 68 #include <signal.h> 69 #include <stdio.h> 70 #include <ctype.h> 71 #include <stdlib.h> 72 #include <string.h> 73 #include <paths.h> 74 #include <limits.h> 75 #include "dkstats.h" 76 77 #define NEWVM /* XXX till old has been updated or purged */ 78 struct nlist namelist[] = { 79 #define X_CPTIME 0 80 { "_cp_time" }, 81 #define X_SUM 1 82 { "_cnt" }, 83 #define X_BOOTTIME 2 84 { "_boottime" }, 85 #define X_HZ 3 86 { "_hz" }, 87 #define X_STATHZ 4 88 { "_stathz" }, 89 #define X_NCHSTATS 5 90 { "_nchstats" }, 91 #define X_INTRNAMES 6 92 { "_intrnames" }, 93 #define X_EINTRNAMES 7 94 { "_eintrnames" }, 95 #define X_INTRCNT 8 96 { "_intrcnt" }, 97 #define X_EINTRCNT 9 98 { "_eintrcnt" }, 99 #define X_KMEMSTAT 10 100 { "_kmemstats" }, 101 #define X_KMEMBUCKETS 11 102 { "_bucket" }, 103 #define X_ALLEVENTS 12 104 { "_allevents" }, 105 #ifdef notdef 106 #define X_DEFICIT 13 107 { "_deficit" }, 108 #define X_FORKSTAT 14 109 { "_forkstat" }, 110 #define X_REC 15 111 { "_rectime" }, 112 #define X_PGIN 16 113 { "_pgintime" }, 114 #define X_XSTATS 17 115 { "_xstats" }, 116 #define X_END 18 117 #else 118 #define X_END 13 119 #endif 120 #ifdef tahoe 121 #define X_VBDINIT (X_END) 122 { "_vbdinit" }, 123 #define X_CKEYSTATS (X_END+1) 124 { "_ckeystats" }, 125 #define X_DKEYSTATS (X_END+2) 126 { "_dkeystats" }, 127 #endif 128 #if defined(pc532) 129 #define X_IVT (X_END) 130 { "_ivt" }, 131 #endif 132 { "" }, 133 }; 134 135 /* Objects defined in dkstats.c */ 136 extern struct _disk cur; 137 extern char **dr_name; 138 extern int *dk_select, dk_ndrive; 139 140 struct vmmeter sum, osum; 141 int ndrives; 142 143 int winlines = 20; 144 145 kvm_t *kd; 146 147 #define FORKSTAT 0x01 148 #define INTRSTAT 0x02 149 #define MEMSTAT 0x04 150 #define SUMSTAT 0x08 151 #define TIMESTAT 0x10 152 #define VMSTAT 0x20 153 154 void cpustats __P((void)); 155 void dkstats __P((void)); 156 void dointr __P((void)); 157 void domem __P((void)); 158 void dosum __P((void)); 159 void dovmstat __P((u_int, int)); 160 void kread __P((int, void *, size_t)); 161 void usage __P((void)); 162 #ifdef notdef 163 void dotimes __P((void)); 164 void doforkst __P((void)); 165 #endif 166 167 char **choosedrives __P((char **)); 168 169 /* Namelist and memory file names. */ 170 char *nlistf, *memf; 171 172 main(argc, argv) 173 register int argc; 174 register char **argv; 175 { 176 extern int optind; 177 extern char *optarg; 178 register int c, todo; 179 u_int interval; 180 int reps; 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 struct winsize winsize; 261 262 dkinit(0); /* Initialize disk stats, no disks selected. */ 263 argv = choosedrives(argv); /* Select disks. */ 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 305 char ** 306 choosedrives(argv) 307 char **argv; 308 { 309 register int i; 310 register char **cp; 311 char buf[30]; 312 313 /* 314 * Choose drives to be displayed. Priority goes to (in order) drives 315 * supplied as arguments, default drives. If everything isn't filled 316 * in and there are drives not taken care of, display the first few 317 * that fit. 318 */ 319 #define BACKWARD_COMPATIBILITY 320 for (ndrives = 0; *argv; ++argv) { 321 #ifdef BACKWARD_COMPATIBILITY 322 if (isdigit(**argv)) 323 break; 324 #endif 325 for (i = 0; i < dk_ndrive; i++) { 326 if (strcmp(dr_name[i], *argv)) 327 continue; 328 dk_select[i] = 1; 329 ++ndrives; 330 break; 331 } 332 } 333 for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 334 if (dk_select[i]) 335 continue; 336 dk_select[i] = 1; 337 ++ndrives; 338 } 339 return(argv); 340 } 341 342 long 343 getuptime() 344 { 345 static time_t now; 346 static struct timeval boottime; 347 time_t uptime; 348 349 if (boottime.tv_sec == 0) 350 kread(X_BOOTTIME, &boottime, sizeof(boottime)); 351 (void)time(&now); 352 uptime = now - boottime.tv_sec; 353 if (uptime <= 0 || uptime > 60*60*24*365*10) { 354 (void)fprintf(stderr, 355 "vmstat: time makes no sense; namelist must be wrong.\n"); 356 exit(1); 357 } 358 return(uptime); 359 } 360 361 int hz, hdrcnt; 362 363 void 364 dovmstat(interval, reps) 365 u_int interval; 366 int reps; 367 { 368 struct vmtotal total; 369 time_t uptime, halfuptime; 370 void needhdr(); 371 int mib[2]; 372 size_t size; 373 374 uptime = getuptime(); 375 halfuptime = uptime / 2; 376 (void)signal(SIGCONT, needhdr); 377 378 if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0) 379 kread(X_STATHZ, &hz, sizeof(hz)); 380 if (!hz) 381 kread(X_HZ, &hz, sizeof(hz)); 382 383 for (hdrcnt = 1;;) { 384 if (!--hdrcnt) 385 printhdr(); 386 /* Read new disk statistics */ 387 dkreadstats(); 388 kread(X_SUM, &sum, sizeof(sum)); 389 size = sizeof(total); 390 mib[0] = CTL_VM; 391 mib[1] = VM_METER; 392 if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) { 393 printf("Can't get kerninfo: %s\n", strerror(errno)); 394 bzero(&total, sizeof(total)); 395 } 396 (void)printf("%2d%2d%2d", 397 total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); 398 #define pgtok(a) ((a) * (sum.v_page_size >> 10)) 399 #define rate(x) (((x) + halfuptime) / uptime) /* round */ 400 (void)printf("%6ld%6ld ", 401 pgtok(total.t_avm), pgtok(total.t_free)); 402 #ifdef NEWVM 403 (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults)); 404 (void)printf("%3lu ", 405 rate(sum.v_reactivated - osum.v_reactivated)); 406 (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins)); 407 (void)printf("%3lu %3lu ", 408 rate(sum.v_pageouts - osum.v_pageouts), 0); 409 #else 410 (void)printf("%3lu %2lu ", 411 rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) - 412 (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))), 413 rate(sum.v_xsfrec + sum.v_xifrec - 414 osum.v_xsfrec - osum.v_xifrec)); 415 (void)printf("%3lu ", 416 rate(pgtok(sum.v_pgpgin - osum.v_pgpgin))); 417 (void)printf("%3lu %3lu ", 418 rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)), 419 rate(pgtok(sum.v_dfree - osum.v_dfree))); 420 (void)printf("%3d ", pgtok(deficit)); 421 #endif 422 (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan)); 423 dkstats(); 424 (void)printf("%4lu %4lu %3lu ", 425 rate(sum.v_intr - osum.v_intr), 426 rate(sum.v_syscall - osum.v_syscall), 427 rate(sum.v_swtch - osum.v_swtch)); 428 cpustats(); 429 (void)printf("\n"); 430 (void)fflush(stdout); 431 if (reps >= 0 && --reps <= 0) 432 break; 433 osum = sum; 434 uptime = interval; 435 /* 436 * We round upward to avoid losing low-frequency events 437 * (i.e., >= 1 per interval but < 1 per second). 438 */ 439 halfuptime = (uptime + 1) / 2; 440 (void)sleep(interval); 441 } 442 } 443 444 printhdr() 445 { 446 register int i; 447 448 (void)printf(" procs memory page%*s", 20, ""); 449 if (ndrives > 0) 450 #ifdef NEWVM 451 (void)printf("%s %*sfaults cpu\n", 452 ((ndrives > 1) ? "disks" : "disk"), 453 #else 454 (void)printf("disks %*sfaults cpu\n", 455 #endif 456 ((ndrives > 1) ? ndrives * 3 - 4 : 0), ""); 457 else 458 #ifdef NEWVM 459 (void)printf("%*s faults cpu\n", 460 #else 461 (void)printf("%*s faults cpu\n", 462 #endif 463 ndrives * 3, ""); 464 465 #ifdef NEWVM 466 (void)printf(" r b w avm fre flt re pi po fr sr "); 467 #else 468 (void)printf(" r b w avm fre re at pi po fr de sr "); 469 #endif 470 for (i = 0; i < dk_ndrive; i++) 471 if (dk_select[i]) 472 (void)printf("%c%c ", dr_name[i][0], 473 dr_name[i][strlen(dr_name[i]) - 1]); 474 (void)printf(" in sy cs us sy id\n"); 475 hdrcnt = winlines - 2; 476 } 477 478 /* 479 * Force a header to be prepended to the next output. 480 */ 481 void 482 needhdr() 483 { 484 485 hdrcnt = 1; 486 } 487 488 #ifdef notdef 489 void 490 dotimes() 491 { 492 u_int pgintime, rectime; 493 494 kread(X_REC, &rectime, sizeof(rectime)); 495 kread(X_PGIN, &pgintime, sizeof(pgintime)); 496 kread(X_SUM, &sum, sizeof(sum)); 497 (void)printf("%u reclaims, %u total time (usec)\n", 498 sum.v_pgrec, rectime); 499 (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 500 (void)printf("\n"); 501 (void)printf("%u page ins, %u total time (msec)\n", 502 sum.v_pgin, pgintime / 10); 503 (void)printf("average: %8.1f msec / page in\n", 504 pgintime / (sum.v_pgin * 10.0)); 505 } 506 #endif 507 508 pct(top, bot) 509 long top, bot; 510 { 511 long ans; 512 513 if (bot == 0) 514 return(0); 515 ans = (quad_t)top * 100 / bot; 516 return (ans); 517 } 518 519 #define PCT(top, bot) pct((long)(top), (long)(bot)) 520 521 #if defined(tahoe) 522 #include <machine/cpu.h> 523 #endif 524 525 void 526 dosum() 527 { 528 struct nchstats nchstats; 529 #ifndef NEWVM 530 struct xstats xstats; 531 #endif 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 (void)printf("%9u traps\n", sum.v_trap); 542 (void)printf("%9u system calls\n", sum.v_syscall); 543 (void)printf("%9u total faults taken\n", sum.v_faults); 544 (void)printf("%9u swap ins\n", sum.v_swpin); 545 (void)printf("%9u swap outs\n", sum.v_swpout); 546 (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 547 (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 548 (void)printf("%9u page ins\n", sum.v_pageins); 549 (void)printf("%9u page outs\n", sum.v_pageouts); 550 (void)printf("%9u pages paged in\n", sum.v_pgpgin); 551 (void)printf("%9u pages paged out\n", sum.v_pgpgout); 552 (void)printf("%9u pages reactivated\n", sum.v_reactivated); 553 (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 554 (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 555 (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 556 (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 557 (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 558 #ifdef NEWVM 559 (void)printf("%9u VM object cache lookups\n", sum.v_lookups); 560 (void)printf("%9u VM object hits\n", sum.v_hits); 561 (void)printf("%9u total VM faults taken\n", sum.v_vm_faults); 562 (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults); 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 free\n", sum.v_free_count); 566 (void)printf("%9u pages wired down\n", sum.v_wire_count); 567 (void)printf("%9u pages active\n", sum.v_active_count); 568 (void)printf("%9u pages inactive\n", sum.v_inactive_count); 569 (void)printf("%9u bytes per page\n", sum.v_page_size); 570 #else 571 (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 572 (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 573 PCT(sum.v_fastpgrec, sum.v_pgrec)); 574 (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 575 (void)printf("%9u executable fill pages created\n", 576 sum.v_nexfod / CLSIZE); 577 (void)printf("%9u executable fill page faults\n", 578 sum.v_exfod / CLSIZE); 579 (void)printf("%9u swap text pages found in free list\n", 580 sum.v_xsfrec); 581 (void)printf("%9u inode text pages found in free list\n", 582 sum.v_xifrec); 583 (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 584 (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 585 (void)printf("%9u pages freed by the clock daemon\n", 586 sum.v_dfree / CLSIZE); 587 #endif 588 kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 589 nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 590 nchstats.ncs_badhits + nchstats.ncs_falsehits + 591 nchstats.ncs_miss + nchstats.ncs_long; 592 (void)printf("%9ld total name lookups\n", nchtotal); 593 (void)printf( 594 "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 595 "", PCT(nchstats.ncs_goodhits, nchtotal), 596 PCT(nchstats.ncs_neghits, nchtotal), 597 PCT(nchstats.ncs_pass2, nchtotal)); 598 (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 599 PCT(nchstats.ncs_badhits, nchtotal), 600 PCT(nchstats.ncs_falsehits, nchtotal), 601 PCT(nchstats.ncs_long, nchtotal)); 602 #ifndef NEWVM 603 kread(X_XSTATS, &xstats, sizeof(xstats)); 604 (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 605 xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 606 (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 607 xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 608 (void)printf("%9lu total calls to xfree", xstats.free); 609 (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 610 xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 611 #endif 612 #if defined(tahoe) 613 kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 614 (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 615 keystats.ks_allocs, "code cache keys allocated", 616 PCT(keystats.ks_allocfree, keystats.ks_allocs), 617 PCT(keystats.ks_norefs, keystats.ks_allocs), 618 PCT(keystats.ks_taken, keystats.ks_allocs), 619 PCT(keystats.ks_shared, keystats.ks_allocs)); 620 kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 621 (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 622 keystats.ks_allocs, "data cache keys allocated", 623 PCT(keystats.ks_allocfree, keystats.ks_allocs), 624 PCT(keystats.ks_norefs, keystats.ks_allocs), 625 PCT(keystats.ks_taken, keystats.ks_allocs), 626 PCT(keystats.ks_shared, keystats.ks_allocs)); 627 #endif 628 } 629 630 #ifdef notdef 631 void 632 doforkst() 633 { 634 struct forkstat fks; 635 636 kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 637 (void)printf("%d forks, %d pages, average %.2f\n", 638 fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 639 (void)printf("%d vforks, %d pages, average %.2f\n", 640 fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 641 } 642 #endif 643 644 void 645 dkstats() 646 { 647 register int dn, state; 648 double etime; 649 long tmp; 650 651 /* Calculate disk stat deltas. */ 652 dkswap(); 653 etime = 0; 654 for (state = 0; state < CPUSTATES; ++state) { 655 etime += cur.cp_time[state]; 656 } 657 if (etime == 0) 658 etime = 1; 659 etime /= hz; 660 for (dn = 0; dn < dk_ndrive; ++dn) { 661 if (!dk_select[dn]) 662 continue; 663 (void)printf("%2.0f ", cur.dk_xfer[dn] / etime); 664 } 665 } 666 667 void 668 cpustats() 669 { 670 register int state; 671 double pct, total; 672 673 total = 0; 674 for (state = 0; state < CPUSTATES; ++state) 675 total += cur.cp_time[state]; 676 if (total) 677 pct = 100 / total; 678 else 679 pct = 0; 680 (void)printf("%2.0f ", (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pct); 681 (void)printf("%2.0f ", (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pct); 682 (void)printf("%2.0f", cur.cp_time[CP_IDLE] * pct); 683 } 684 685 #if defined(pc532) 686 /* To get struct iv ...*/ 687 #define _KERNEL 688 #include <machine/psl.h> 689 #undef _KERNEL 690 void 691 dointr() 692 { 693 register long i, j, inttotal, uptime; 694 static char iname[64]; 695 struct iv ivt[32], *ivp = ivt; 696 697 iname[63] = '\0'; 698 uptime = getuptime(); 699 kread(X_IVT, ivp, sizeof(ivt)); 700 701 for (i = 0; i < 2; i++) { 702 (void)printf("%sware interrupts:\n", i ? "\nsoft" : "hard"); 703 (void)printf("interrupt total rate\n"); 704 inttotal = 0; 705 for (j = 0; j < 16; j++, ivp++) { 706 if (ivp->iv_vec && ivp->iv_use && ivp->iv_cnt) { 707 if (kvm_read(kd, (u_long)ivp->iv_use, iname, 63) != 63) { 708 (void)fprintf(stderr, "vmstat: iv_use: %s\n", 709 kvm_geterr(kd)); 710 exit(1); 711 } 712 (void)printf("%-12s %8ld %8ld\n", iname, 713 ivp->iv_cnt, ivp->iv_cnt / uptime); 714 inttotal += ivp->iv_cnt; 715 } 716 } 717 (void)printf("Total %8ld %8ld\n", 718 inttotal, inttotal / uptime); 719 } 720 } 721 #else 722 void 723 dointr() 724 { 725 register long *intrcnt, inttotal, uptime; 726 register int nintr, inamlen; 727 register char *intrname; 728 struct evcntlist allevents; 729 struct evcnt evcnt, *evptr; 730 struct device dev; 731 732 uptime = getuptime(); 733 nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value; 734 inamlen = 735 namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value; 736 intrcnt = malloc((size_t)nintr); 737 intrname = malloc((size_t)inamlen); 738 if (intrcnt == NULL || intrname == NULL) { 739 (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 740 exit(1); 741 } 742 kread(X_INTRCNT, intrcnt, (size_t)nintr); 743 kread(X_INTRNAMES, intrname, (size_t)inamlen); 744 (void)printf("interrupt total rate\n"); 745 inttotal = 0; 746 nintr /= sizeof(long); 747 while (--nintr >= 0) { 748 if (*intrcnt) 749 (void)printf("%-14s %8ld %8ld\n", intrname, 750 *intrcnt, *intrcnt / uptime); 751 intrname += strlen(intrname) + 1; 752 inttotal += *intrcnt++; 753 } 754 kread(X_ALLEVENTS, &allevents, sizeof allevents); 755 evptr = allevents.tqh_first; 756 while (evptr) { 757 if (kvm_read(kd, (long)evptr, (void *)&evcnt, 758 sizeof evcnt) != sizeof evcnt) { 759 (void)fprintf(stderr, "vmstat: event chain trashed\n", 760 kvm_geterr(kd)); 761 exit(1); 762 } 763 if (strcmp(evcnt.ev_name, "intr") == 0) { 764 if (kvm_read(kd, (long)evcnt.ev_dev, (void *)&dev, 765 sizeof dev) != sizeof dev) { 766 (void)fprintf(stderr, "vmstat: event chain trashed\n", 767 kvm_geterr(kd)); 768 exit(1); 769 } 770 if (evcnt.ev_count) 771 (void)printf("%-14s %8ld %8ld\n", dev.dv_xname, 772 evcnt.ev_count, evcnt.ev_count / uptime); 773 inttotal += evcnt.ev_count++; 774 } 775 evptr = evcnt.ev_list.tqe_next; 776 } 777 (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 778 } 779 #endif 780 781 /* 782 * These names are defined in <sys/malloc.h>. 783 */ 784 char *kmemnames[] = INITKMEMNAMES; 785 786 void 787 domem() 788 { 789 register struct kmembuckets *kp; 790 register struct kmemstats *ks; 791 register int i, j; 792 int len, size, first; 793 long totuse = 0, totfree = 0, totreq = 0; 794 char *name; 795 struct kmemstats kmemstats[M_LAST]; 796 struct kmembuckets buckets[MINBUCKET + 16]; 797 798 kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 799 (void)printf("Memory statistics by bucket size\n"); 800 (void)printf( 801 " Size In Use Free Requests HighWater Couldfree\n"); 802 for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 803 if (kp->kb_calls == 0) 804 continue; 805 size = 1 << i; 806 (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size, 807 kp->kb_total - kp->kb_totalfree, 808 kp->kb_totalfree, kp->kb_calls, 809 kp->kb_highwat, kp->kb_couldfree); 810 totfree += size * kp->kb_totalfree; 811 } 812 813 kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 814 (void)printf("\nMemory usage type by bucket size\n"); 815 (void)printf(" Size Type(s)\n"); 816 kp = &buckets[MINBUCKET]; 817 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) { 818 if (kp->kb_calls == 0) 819 continue; 820 first = 1; 821 len = 8; 822 for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 823 if (ks->ks_calls == 0) 824 continue; 825 if ((ks->ks_size & j) == 0) 826 continue; 827 name = kmemnames[i] ? kmemnames[i] : "undefined"; 828 len += 2 + strlen(name); 829 if (first) 830 printf("%8d %s", j, name); 831 else 832 printf(","); 833 if (len >= 80) { 834 printf("\n\t "); 835 len = 10 + strlen(name); 836 } 837 if (!first) 838 printf(" %s", name); 839 first = 0; 840 } 841 printf("\n"); 842 } 843 844 (void)printf( 845 "\nMemory statistics by type Type Kern\n"); 846 (void)printf( 847 " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n"); 848 for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 849 if (ks->ks_calls == 0) 850 continue; 851 (void)printf("%12s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u", 852 kmemnames[i] ? kmemnames[i] : "undefined", 853 ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 854 (ks->ks_maxused + 1023) / 1024, 855 (ks->ks_limit + 1023) / 1024, ks->ks_calls, 856 ks->ks_limblocks, ks->ks_mapblocks); 857 first = 1; 858 for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) { 859 if ((ks->ks_size & j) == 0) 860 continue; 861 if (first) 862 printf(" %d", j); 863 else 864 printf(",%d", j); 865 first = 0; 866 } 867 printf("\n"); 868 totuse += ks->ks_memuse; 869 totreq += ks->ks_calls; 870 } 871 (void)printf("\nMemory Totals: In Use Free Requests\n"); 872 (void)printf(" %7ldK %6ldK %8ld\n", 873 (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq); 874 } 875 876 /* 877 * kread reads something from the kernel, given its nlist index. 878 */ 879 void 880 kread(nlx, addr, size) 881 int nlx; 882 void *addr; 883 size_t size; 884 { 885 char *sym; 886 887 if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) { 888 sym = namelist[nlx].n_name; 889 if (*sym == '_') 890 ++sym; 891 (void)fprintf(stderr, 892 "vmstat: symbol %s not defined\n", sym); 893 exit(1); 894 } 895 if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) { 896 sym = namelist[nlx].n_name; 897 if (*sym == '_') 898 ++sym; 899 (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd)); 900 exit(1); 901 } 902 } 903 904 void 905 usage() 906 { 907 (void)fprintf(stderr, 908 #ifndef NEWVM 909 "usage: vmstat [-fimst] [-c count] [-M core] \ 910 [-N system] [-w wait] [disks]\n"); 911 #else 912 "usage: vmstat [-ims] [-c count] [-M core] \ 913 [-N system] [-w wait] [disks]\n"); 914 #endif 915 exit(1); 916 } 917 918