121585Sdist /* 236580Sbostic * Copyright (c) 1980 The Regents of the University of California. 336580Sbostic * All rights reserved. 436580Sbostic * 542784Sbostic * %sccs.include.redist.c% 621585Sdist */ 721585Sdist 810826Ssam #ifndef lint 921585Sdist char copyright[] = 1036580Sbostic "@(#) Copyright (c) 1980 The Regents of the University of California.\n\ 1121585Sdist All rights reserved.\n"; 1236580Sbostic #endif /* not lint */ 1310826Ssam 1421585Sdist #ifndef lint 15*45834Sbostic static char sccsid[] = "@(#)vmstat.c 5.23 (Berkeley) 12/18/90"; 1636580Sbostic #endif /* not lint */ 1721585Sdist 181155Sbill #include <sys/param.h> 1918761Ssam #include <sys/file.h> 201155Sbill #include <sys/vm.h> 2129664Ssam #include <sys/dkstat.h> 223162Stoy #include <sys/buf.h> 2317262Smckusick #include <sys/namei.h> 2425708Ssam #include <sys/text.h> 2533610Smckusick #include <sys/malloc.h> 2637912Sbostic #include <ctype.h> 27*45834Sbostic #include <errno.h> 28*45834Sbostic #include <kvm.h> 2937912Sbostic #include <nlist.h> 30*45834Sbostic #include <stdio.h> 31*45834Sbostic #include <stdlib.h> 32*45834Sbostic #include <string.h> 3337912Sbostic #include <paths.h> 341155Sbill 351155Sbill struct nlist nl[] = { 361448Sbill #define X_CPTIME 0 371448Sbill { "_cp_time" }, 381448Sbill #define X_RATE 1 391155Sbill { "_rate" }, 401448Sbill #define X_TOTAL 2 411155Sbill { "_total" }, 421448Sbill #define X_DEFICIT 3 431155Sbill { "_deficit" }, 441448Sbill #define X_FORKSTAT 4 451155Sbill { "_forkstat" }, 461448Sbill #define X_SUM 5 471155Sbill { "_sum" }, 481448Sbill #define X_FIRSTFREE 6 491155Sbill { "_firstfree" }, 501448Sbill #define X_MAXFREE 7 511155Sbill { "_maxfree" }, 529249Ssam #define X_BOOTTIME 8 539249Ssam { "_boottime" }, 541448Sbill #define X_DKXFER 9 551448Sbill { "_dk_xfer" }, 5610826Ssam #define X_REC 10 571155Sbill { "_rectime" }, 5810826Ssam #define X_PGIN 11 591155Sbill { "_pgintime" }, 6010826Ssam #define X_HZ 12 613162Stoy { "_hz" }, 6218761Ssam #define X_PHZ 13 6315266Ssam { "_phz" }, 6415807Smckusick #define X_NCHSTATS 14 6515807Smckusick { "_nchstats" }, 6617262Smckusick #define X_INTRNAMES 15 6717262Smckusick { "_intrnames" }, 6817262Smckusick #define X_EINTRNAMES 16 6917262Smckusick { "_eintrnames" }, 7017262Smckusick #define X_INTRCNT 17 7117262Smckusick { "_intrcnt" }, 7217262Smckusick #define X_EINTRCNT 18 7317262Smckusick { "_eintrcnt" }, 7418761Ssam #define X_DK_NDRIVE 19 7518761Ssam { "_dk_ndrive" }, 7625512Ssam #define X_XSTATS 20 7725512Ssam { "_xstats" }, 7833610Smckusick #define X_KMEMSTAT 21 7933610Smckusick { "_kmemstats" }, 8033610Smckusick #define X_KMEMBUCKETS 22 8133610Smckusick { "_bucket" }, 8242952Sbostic #define X_END 22 8310826Ssam #ifdef vax 8442952Sbostic #define X_MBDINIT (X_END+1) 8510826Ssam { "_mbdinit" }, 8642952Sbostic #define X_UBDINIT (X_END+2) 8710826Ssam { "_ubdinit" }, 8810826Ssam #endif 8925708Ssam #ifdef tahoe 9042952Sbostic #define X_VBDINIT (X_END+1) 9125708Ssam { "_vbdinit" }, 9242952Sbostic #define X_CKEYSTATS (X_END+2) 9325960Ssam { "_ckeystats" }, 9442952Sbostic #define X_DKEYSTATS (X_END+3) 9525960Ssam { "_dkeystats" }, 9625708Ssam #endif 9742952Sbostic #ifdef hp300 9842952Sbostic #define X_HPDINIT (X_END+1) 9942952Sbostic { "_hp_dinit" }, 10042952Sbostic #endif 10110826Ssam { "" }, 1021155Sbill }; 1031155Sbill 104*45834Sbostic char *vmunix = _PATH_UNIX; 105*45834Sbostic char *kmem = NULL; 10618761Ssam char **dr_name; 10718761Ssam int *dr_select; 10818761Ssam int dk_ndrive; 10918761Ssam int ndrives = 0; 11018761Ssam #ifdef vax 11118761Ssam char *defdrives[] = { "hp0", "hp1", "hp2", 0 }; 11218761Ssam #else 11342952Sbostic #ifdef hp300 11442952Sbostic char *defdrives[] = { "rd0", "rd1", "rd2", 0 }; 11542952Sbostic #else 11618761Ssam char *defdrives[] = { 0 }; 11718761Ssam #endif 11842952Sbostic #endif 1191155Sbill double stat1(); 1201155Sbill int firstfree, maxfree; 1213162Stoy int hz; 12215266Ssam int phz; 12315266Ssam int HZ; 12418761Ssam 12518761Ssam struct { 1261155Sbill int busy; 1271448Sbill long time[CPUSTATES]; 12818761Ssam long *xfer; 1291155Sbill struct vmmeter Rate; 1301155Sbill struct vmtotal Total; 1311155Sbill struct vmmeter Sum; 1321155Sbill struct forkstat Forkstat; 1331155Sbill unsigned rectime; 1341155Sbill unsigned pgintime; 135*45834Sbostic } s, s1; 1361155Sbill #define rate s.Rate 1371155Sbill #define total s.Total 1381155Sbill #define sum s.Sum 1391155Sbill #define forkstat s.Forkstat 1401155Sbill 14110826Ssam struct vmmeter osum; 1421155Sbill int deficit; 1431155Sbill double etime; 14417262Smckusick time_t now, boottime; 14518768Ssam int lines = 1; 146*45834Sbostic void printhdr(); 147*45834Sbostic long lseek(); 1481155Sbill 14929664Ssam #define INTS(x) ((x) - (hz + phz)) 15029664Ssam 151*45834Sbostic #define FORKSTAT 0x01 152*45834Sbostic #define INTRSTAT 0x02 153*45834Sbostic #define MEMSTAT 0x04 154*45834Sbostic #define SUMSTAT 0x08 155*45834Sbostic #define TIMESTAT 0x10 156*45834Sbostic #define VMSTAT 0x20 157*45834Sbostic #define ZEROOUT 0x40 158*45834Sbostic 1591155Sbill main(argc, argv) 160*45834Sbostic register int argc; 161*45834Sbostic register char **argv; 1621155Sbill { 163*45834Sbostic register int c, i, todo = 0; 164*45834Sbostic extern int optind; 165*45834Sbostic extern char *optarg; 1661155Sbill 167*45834Sbostic while ((c = getopt(argc, argv, "fik:mstu:z")) != EOF) { 168*45834Sbostic switch (c) { 169*45834Sbostic case 'f': 170*45834Sbostic todo |= FORKSTAT; 171*45834Sbostic break; 172*45834Sbostic case 'i': 173*45834Sbostic todo |= INTRSTAT; 174*45834Sbostic break; 175*45834Sbostic case 'k': 176*45834Sbostic kmem = optarg; 177*45834Sbostic break; 178*45834Sbostic case 'm': 179*45834Sbostic todo |= MEMSTAT; 180*45834Sbostic break; 181*45834Sbostic case 's': 182*45834Sbostic todo |= SUMSTAT; 183*45834Sbostic break; 184*45834Sbostic case 't': 185*45834Sbostic todo |= TIMESTAT; 186*45834Sbostic break; 187*45834Sbostic case 'u': 188*45834Sbostic vmunix = optarg; 189*45834Sbostic break; 190*45834Sbostic case 'z': 191*45834Sbostic todo |= ZEROOUT; 192*45834Sbostic break; 193*45834Sbostic case '?': 194*45834Sbostic usage(); 195*45834Sbostic /* NOTREACHED */ 196*45834Sbostic default: 197*45834Sbostic (void) fprintf(stderr, 198*45834Sbostic "vmstat: internal error in options\n"); 199*45834Sbostic exit(1); 200*45834Sbostic /* NOTREACHED */ 201*45834Sbostic } 202*45834Sbostic } 203*45834Sbostic 204*45834Sbostic /* 205*45834Sbostic * Zeroing the statistics is fundamentally different 206*45834Sbostic * (and really belongs in a separate program). 207*45834Sbostic */ 208*45834Sbostic if (todo & ZEROOUT) { 209*45834Sbostic if (todo & ~ZEROOUT || kmem) 210*45834Sbostic usage(); 211*45834Sbostic nl[0].n_name = nl[X_SUM].n_name; 212*45834Sbostic nl[1].n_name = 0; 213*45834Sbostic if (nlist(vmunix, nl) || nl[0].n_type == 0) { 214*45834Sbostic (void) fprintf(stderr, 215*45834Sbostic "vmstat: cannot get symbol %s from %s\n", 216*45834Sbostic nl[0].n_name, vmunix); 217*45834Sbostic exit(1); 218*45834Sbostic } 219*45834Sbostic if ((i = open(kmem = _PATH_KMEM, 2)) < 0) { 220*45834Sbostic (void) fprintf(stderr, "vmstat: cannot write %s: %s\n", 221*45834Sbostic kmem, strerror(errno)); 222*45834Sbostic exit(1); 223*45834Sbostic } 224*45834Sbostic (void) lseek(i, (long)nl[0].n_value, L_SET); 225*45834Sbostic if (write(i, (char *)&s.Sum, sizeof s.Sum) != sizeof s.Sum) { 226*45834Sbostic (void) fprintf(stderr, "vmstat: write(%s): %s\n", 227*45834Sbostic kmem, strerror(errno)); 228*45834Sbostic exit(1); 229*45834Sbostic } 230*45834Sbostic exit(0); 231*45834Sbostic } 232*45834Sbostic 233*45834Sbostic if (todo == 0) 234*45834Sbostic todo = VMSTAT; 235*45834Sbostic 236*45834Sbostic if (kvm_openfiles(vmunix, kmem, (char *)NULL) < 0) { 237*45834Sbostic (void) fprintf(stderr, 238*45834Sbostic "vmstat: kvm_openfiles(%s, %s, NULL): %s\n", 239*45834Sbostic vmunix, kmem ? kmem : "NULL", kvm_geterr()); 2401155Sbill exit(1); 2411155Sbill } 242*45834Sbostic 243*45834Sbostic (void) kvm_nlist(nl); 244*45834Sbostic if (nl[0].n_type == 0) { 245*45834Sbostic (void) fprintf(stderr, "vmstat: %s: no namelist\n", 246*45834Sbostic vmunix); 2471155Sbill exit(1); 2481155Sbill } 2491155Sbill 250*45834Sbostic /* 251*45834Sbostic * Fork, memory, sum, and time statistics do not need everything. 252*45834Sbostic */ 253*45834Sbostic if (todo & FORKSTAT) 254*45834Sbostic doforkst(); 255*45834Sbostic if (todo & MEMSTAT) 256*45834Sbostic domem(); 257*45834Sbostic if (todo & SUMSTAT) 258*45834Sbostic dosum(); 259*45834Sbostic if (todo & TIMESTAT) 260*45834Sbostic dotimes(); 261*45834Sbostic if (todo & INTRSTAT) 262*45834Sbostic dointr(); 263*45834Sbostic if (todo & VMSTAT) { 264*45834Sbostic /* 265*45834Sbostic * Read drive names, decide which drives to report, etc. 266*45834Sbostic */ 267*45834Sbostic argc -= optind; 268*45834Sbostic argv += optind; 269*45834Sbostic i = getdrivedata(argc, argv); 270*45834Sbostic argc -= i; 271*45834Sbostic argv += i; 272*45834Sbostic dovmstat(argc > 0 ? atoi(argv[0]) : 0, 273*45834Sbostic argc > 1 ? atoi(argv[1]) : 0); 274*45834Sbostic } 275*45834Sbostic exit(0); 276*45834Sbostic } 27710826Ssam 278*45834Sbostic usage() 279*45834Sbostic { 2801155Sbill 281*45834Sbostic (void) fprintf(stderr, 282*45834Sbostic "usage: vmstat [-fimst]\n\tvmstat [drive-list] [interval [count]]\n\tvmstat -z\n"); 283*45834Sbostic exit(1); 284*45834Sbostic } 28533610Smckusick 286*45834Sbostic /* 287*45834Sbostic * kread reads something from the kernel, given its nlist index. 288*45834Sbostic */ 289*45834Sbostic void 290*45834Sbostic kread(nlx, addr, size) 291*45834Sbostic int nlx; 292*45834Sbostic char *addr; 293*45834Sbostic size_t size; 294*45834Sbostic { 295*45834Sbostic char *sym; 2961155Sbill 297*45834Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 298*45834Sbostic sym = nl[nlx].n_name; 299*45834Sbostic if (*sym == '_') 300*45834Sbostic sym++; 301*45834Sbostic (void) fprintf(stderr, 302*45834Sbostic "vmstat: symbol `%s' not defined in %s\n", sym, vmunix); 303*45834Sbostic exit(1); 3041155Sbill } 305*45834Sbostic if (kvm_read(nl[nlx].n_value, addr, size) != size) { 306*45834Sbostic sym = nl[nlx].n_name; 307*45834Sbostic if (*sym == '_') 308*45834Sbostic sym++; 309*45834Sbostic (void) fprintf(stderr, 310*45834Sbostic "vmstat: error reading `%s': %s\n", sym, kvm_geterr()); 311*45834Sbostic exit(1); 31218761Ssam } 313*45834Sbostic } 314*45834Sbostic 315*45834Sbostic getdrivedata(argc, argv) 316*45834Sbostic int argc; 317*45834Sbostic char **argv; 318*45834Sbostic { 319*45834Sbostic register int i; 320*45834Sbostic register char **cp; 321*45834Sbostic int ret; 322*45834Sbostic char buf[30]; 323*45834Sbostic 324*45834Sbostic kread(X_FIRSTFREE, (char *)&firstfree, sizeof firstfree); 325*45834Sbostic kread(X_MAXFREE, (char *)&maxfree, sizeof maxfree); 326*45834Sbostic kread(X_HZ, (char *)&hz, sizeof hz); 327*45834Sbostic if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 328*45834Sbostic kread(X_PHZ, (char *)&phz, sizeof phz); 32915266Ssam HZ = phz ? phz : hz; 330*45834Sbostic kread(X_DK_NDRIVE, (char *)&dk_ndrive, sizeof dk_ndrive); 33118761Ssam if (dk_ndrive <= 0) { 332*45834Sbostic (void) fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 33318761Ssam exit(1); 33418761Ssam } 335*45834Sbostic dr_select = (int *)calloc((size_t)dk_ndrive, sizeof (int)); 336*45834Sbostic dr_name = (char **)malloc((size_t)dk_ndrive * sizeof (char *)); 337*45834Sbostic for (i = 0; i < dk_ndrive; i++) 338*45834Sbostic dr_name[i] = NULL; 339*45834Sbostic s.xfer = (long *)calloc((size_t)dk_ndrive, sizeof (long)); 340*45834Sbostic s1.xfer = (long *)calloc((size_t)dk_ndrive, sizeof (long)); 3413162Stoy read_names(); 342*45834Sbostic for (i = 0; i < dk_ndrive; i++) { 343*45834Sbostic if (dr_name[i] == NULL) { 344*45834Sbostic (void) sprintf(buf, "??%d", i); 345*45834Sbostic dr_name[i] = strdup(buf); 346*45834Sbostic } 3471155Sbill } 348*45834Sbostic 34918761Ssam /* 35018761Ssam * Choose drives to be displayed. Priority 35118761Ssam * goes to (in order) drives supplied as arguments, 35218761Ssam * default drives. If everything isn't filled 35318761Ssam * in and there are drives not taken care of, 35418761Ssam * display the first few that fit. 35518761Ssam */ 356*45834Sbostic ret = 0; 35718761Ssam ndrives = 0; 35818761Ssam while (argc > 0 && !isdigit(argv[0][0])) { 35918761Ssam for (i = 0; i < dk_ndrive; i++) { 36018761Ssam if (strcmp(dr_name[i], argv[0])) 36118761Ssam continue; 36218761Ssam dr_select[i] = 1; 36318761Ssam ndrives++; 364*45834Sbostic break; 36518761Ssam } 366*45834Sbostic ret++; 36718761Ssam argc--, argv++; 36818761Ssam } 36918761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 37018761Ssam if (dr_select[i]) 37118761Ssam continue; 37218761Ssam for (cp = defdrives; *cp; cp++) 37318761Ssam if (strcmp(dr_name[i], *cp) == 0) { 37418761Ssam dr_select[i] = 1; 37518761Ssam ndrives++; 37618761Ssam break; 37718761Ssam } 37818761Ssam } 37918761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 38018761Ssam if (dr_select[i]) 38118761Ssam continue; 38218761Ssam dr_select[i] = 1; 38318761Ssam ndrives++; 38418761Ssam } 385*45834Sbostic return (ret); 386*45834Sbostic } 387*45834Sbostic 388*45834Sbostic long 389*45834Sbostic getuptime() 390*45834Sbostic { 391*45834Sbostic time_t time(); 392*45834Sbostic long uptime; 393*45834Sbostic 394*45834Sbostic if (boottime == 0) 395*45834Sbostic kread(X_BOOTTIME, (char *)&boottime, sizeof boottime); 396*45834Sbostic (void) time(&now); 397*45834Sbostic uptime = now - boottime; 398*45834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 399*45834Sbostic (void) fprintf(stderr, 400*45834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 401*45834Sbostic exit(1); 402*45834Sbostic } 403*45834Sbostic return (uptime); 404*45834Sbostic } 405*45834Sbostic 406*45834Sbostic dovmstat(sleeptime, iter) 407*45834Sbostic int sleeptime, iter; 408*45834Sbostic { 409*45834Sbostic register int i; 410*45834Sbostic long interval, t; 411*45834Sbostic 412*45834Sbostic interval = getuptime(); 413*45834Sbostic (void) signal(SIGCONT, printhdr); 4141155Sbill loop: 41518768Ssam if (--lines == 0) 41618768Ssam printhdr(); 417*45834Sbostic kread(X_CPTIME, (char *)s.time, sizeof s.time); 418*45834Sbostic kread(X_DKXFER, (char *)s.xfer, sizeof *s.xfer * dk_ndrive); 419*45834Sbostic if (interval != 1) 420*45834Sbostic kread(X_SUM, (char *)&rate, sizeof rate); 42118761Ssam else 422*45834Sbostic kread(X_RATE, (char *)&rate, sizeof rate); 423*45834Sbostic kread(X_TOTAL, (char *)&total, sizeof total); 42410826Ssam osum = sum; 425*45834Sbostic kread(X_SUM, (char *)&sum, sizeof sum); 426*45834Sbostic kread(X_DEFICIT, (char *)&deficit, sizeof deficit); 4271448Sbill etime = 0; 428*45834Sbostic for (i = 0; i < dk_ndrive; i++) { 4291448Sbill t = s.xfer[i]; 4301448Sbill s.xfer[i] -= s1.xfer[i]; 4311448Sbill s1.xfer[i] = t; 4321155Sbill } 433*45834Sbostic for (i = 0; i < CPUSTATES; i++) { 4341448Sbill t = s.time[i]; 4351448Sbill s.time[i] -= s1.time[i]; 4361448Sbill s1.time[i] = t; 4371448Sbill etime += s.time[i]; 4381155Sbill } 439*45834Sbostic if (etime == 0.) 4401155Sbill etime = 1.; 441*45834Sbostic (void) printf("%2d%2d%2d", 442*45834Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 443*45834Sbostic #define pgtok(a) ((a)*NBPG >> 10) 444*45834Sbostic (void) printf("%6ld%6ld", pgtok(total.t_avm), pgtok(total.t_free)); 445*45834Sbostic (void) printf("%4lu%3lu", 446*45834Sbostic (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec)) / interval, 447*45834Sbostic (rate.v_xsfrec+rate.v_xifrec) / interval); 448*45834Sbostic (void) printf("%4lu", pgtok(rate.v_pgpgin) / interval); 449*45834Sbostic (void) printf("%4lu%4lu%4d%4lu", pgtok(rate.v_pgpgout) / interval, 450*45834Sbostic pgtok(rate.v_dfree) / interval, 451*45834Sbostic pgtok(deficit), rate.v_scan / interval); 45218761Ssam etime /= (float)HZ; 45318761Ssam for (i = 0; i < dk_ndrive; i++) 45418761Ssam if (dr_select[i]) 45518761Ssam stats(i); 456*45834Sbostic (void) printf("%4lu%4lu%4lu", INTS(rate.v_intr / interval), 457*45834Sbostic rate.v_syscall / interval, rate.v_swtch / interval); 458*45834Sbostic for(i = 0; i < CPUSTATES; i++) { 4591155Sbill float f = stat1(i); 4601155Sbill if (i == 0) { /* US+NI */ 4611155Sbill i++; 4621155Sbill f += stat1(i); 4631155Sbill } 464*45834Sbostic (void) printf("%3.0f", f); 4651155Sbill } 466*45834Sbostic (void) printf("\n"); 467*45834Sbostic (void) fflush(stdout); 468*45834Sbostic interval = 1; 469*45834Sbostic if (iter && --iter == 0) 470*45834Sbostic return; 471*45834Sbostic if (sleeptime) { 472*45834Sbostic sleep((unsigned)sleeptime); 4731155Sbill goto loop; 4741155Sbill } 4751155Sbill } 4761155Sbill 477*45834Sbostic void 47817262Smckusick printhdr() 47917262Smckusick { 48018761Ssam register int i, j; 48118761Ssam 482*45834Sbostic (void) printf(" procs memory page "); 48318761Ssam i = (ndrives * 3 - 6) / 2; 48418761Ssam if (i < 0) 48518761Ssam i = 0; 48618761Ssam for (j = 0; j < i; j++) 487*45834Sbostic (void) putchar(' '); 488*45834Sbostic (void) printf("faults"); 48918761Ssam i = ndrives * 3 - 6 - i; 49018761Ssam for (j = 0; j < i; j++) 491*45834Sbostic (void) putchar(' '); 492*45834Sbostic (void) printf(" cpu\n"); 493*45834Sbostic (void) printf(" r b w avm fre re at pi po fr de sr "); 49418761Ssam for (i = 0; i < dk_ndrive; i++) 49518761Ssam if (dr_select[i]) 496*45834Sbostic (void) printf("%c%c ", dr_name[i][0], 497*45834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 498*45834Sbostic (void) printf(" in sy cs us sy id\n"); 49918768Ssam lines = 19; 50017262Smckusick } 50117262Smckusick 5021155Sbill dotimes() 5031155Sbill { 5041155Sbill 505*45834Sbostic kread(X_REC, (char *)&s.rectime, sizeof s.rectime); 506*45834Sbostic kread(X_PGIN, (char *)&s.pgintime, sizeof s.pgintime); 507*45834Sbostic kread(X_SUM, (char *)&sum, sizeof sum); 508*45834Sbostic (void) printf("%u reclaims, %u total time (usec)\n", 509*45834Sbostic sum.v_pgrec, s.rectime); 510*45834Sbostic (void) printf("average: %u usec / reclaim\n", s.rectime / sum.v_pgrec); 511*45834Sbostic (void) printf("\n"); 512*45834Sbostic (void) printf("%u page ins, %u total time (msec)\n", 513*45834Sbostic sum.v_pgin, s.pgintime / 10); 514*45834Sbostic (void) printf("average: %8.1f msec / page in\n", 515*45834Sbostic s.pgintime / (sum.v_pgin * 10.0)); 5161155Sbill } 5171155Sbill 518*45834Sbostic pct(top, bot) 519*45834Sbostic long top, bot; 520*45834Sbostic { 521*45834Sbostic 522*45834Sbostic if (bot == 0) 523*45834Sbostic return (0); 524*45834Sbostic return ((top * 100) / bot); 525*45834Sbostic } 526*45834Sbostic 527*45834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 528*45834Sbostic 52930069Ssam #if defined(tahoe) 530*45834Sbostic #include <machine/cpu.h> 53130069Ssam #endif 53230069Ssam 5331155Sbill dosum() 5341155Sbill { 53518761Ssam struct nchstats nchstats; 53625960Ssam struct xstats xstats; 53715807Smckusick long nchtotal; 53825960Ssam #if defined(tahoe) 53925960Ssam struct keystats keystats; 54025960Ssam #endif 5411155Sbill 542*45834Sbostic kread(X_SUM, (char *)&sum, sizeof sum); 543*45834Sbostic (void) printf("%9u swap ins\n", sum.v_swpin); 544*45834Sbostic (void) printf("%9u swap outs\n", sum.v_swpout); 545*45834Sbostic (void) printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 546*45834Sbostic (void) printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 547*45834Sbostic (void) printf("%9u total address trans. faults taken\n", sum.v_faults); 548*45834Sbostic (void) printf("%9u page ins\n", sum.v_pgin); 549*45834Sbostic (void) printf("%9u page outs\n", sum.v_pgout); 550*45834Sbostic (void) printf("%9u pages paged in\n", sum.v_pgpgin); 551*45834Sbostic (void) printf("%9u pages paged out\n", sum.v_pgpgout); 552*45834Sbostic (void) printf("%9u sequential process pages freed\n", sum.v_seqfree); 553*45834Sbostic (void) printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 554*45834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 555*45834Sbostic (void) printf("%9u reclaims from free list\n", sum.v_pgfrec); 556*45834Sbostic (void) printf("%9u intransit blocking page faults\n", sum.v_intrans); 557*45834Sbostic (void) printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 558*45834Sbostic (void) printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 559*45834Sbostic (void) printf("%9u executable fill pages created\n", 560*45834Sbostic sum.v_nexfod / CLSIZE); 561*45834Sbostic (void) printf("%9u executable fill page faults\n", 562*45834Sbostic sum.v_exfod / CLSIZE); 563*45834Sbostic (void) printf("%9u swap text pages found in free list\n", 564*45834Sbostic sum.v_xsfrec); 565*45834Sbostic (void) printf("%9u inode text pages found in free list\n", 566*45834Sbostic sum.v_xifrec); 567*45834Sbostic (void) printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 568*45834Sbostic (void) printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 569*45834Sbostic (void) printf("%9u pages examined by the clock daemon\n", sum.v_scan); 570*45834Sbostic (void) printf("%9u revolutions of the clock hand\n", sum.v_rev); 571*45834Sbostic (void) printf("%9u pages freed by the clock daemon\n", 572*45834Sbostic sum.v_dfree / CLSIZE); 573*45834Sbostic (void) printf("%9u cpu context switches\n", sum.v_swtch); 574*45834Sbostic (void) printf("%9u device interrupts\n", sum.v_intr); 575*45834Sbostic (void) printf("%9u software interrupts\n", sum.v_soft); 57618761Ssam #ifdef vax 577*45834Sbostic (void) printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 57818761Ssam #endif 579*45834Sbostic (void) printf("%9u traps\n", sum.v_trap); 580*45834Sbostic (void) printf("%9u system calls\n", sum.v_syscall); 581*45834Sbostic kread(X_NCHSTATS, (char *)&nchstats, sizeof nchstats); 58238773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 58338773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 58438773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 585*45834Sbostic (void) printf("%9ld total name lookups\n", nchtotal); 586*45834Sbostic (void) printf( 587*45834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 588*45834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 589*45834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 590*45834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 591*45834Sbostic (void) printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 592*45834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 593*45834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 594*45834Sbostic PCT(nchstats.ncs_long, nchtotal)); 595*45834Sbostic kread(X_XSTATS, (char *)&xstats, sizeof xstats); 596*45834Sbostic (void) printf("%9lu total calls to xalloc (cache hits %d%%)\n", 597*45834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 598*45834Sbostic (void) printf("%9s sticky %lu flushed %lu unused %lu\n", "", 59925512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 600*45834Sbostic (void) printf("%9lu total calls to xfree", xstats.free); 601*45834Sbostic (void) printf(" (sticky %lu cached %lu swapped %lu)\n", 60225512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 60325960Ssam #if defined(tahoe) 604*45834Sbostic kread(X_CKEYSTATS, (char *)&keystats, sizeof keystats); 605*45834Sbostic (void) printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 60625960Ssam keystats.ks_allocs, "code cache keys allocated", 607*45834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 608*45834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 609*45834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 610*45834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 611*45834Sbostic kread(X_DKEYSTATS, (char *)&keystats, sizeof keystats); 612*45834Sbostic (void) printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 61325960Ssam keystats.ks_allocs, "data cache keys allocated", 614*45834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 615*45834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 616*45834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 617*45834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 61825960Ssam #endif 6191155Sbill } 6201155Sbill 6211155Sbill doforkst() 6221155Sbill { 6231155Sbill 624*45834Sbostic kread(X_FORKSTAT, (char *)&forkstat, sizeof forkstat); 625*45834Sbostic (void) printf("%d forks, %d pages, average=%.2f\n", 6261155Sbill forkstat.cntfork, forkstat.sizfork, 6271155Sbill (float) forkstat.sizfork / forkstat.cntfork); 628*45834Sbostic (void) printf("%d vforks, %d pages, average=%.2f\n", 6291155Sbill forkstat.cntvfork, forkstat.sizvfork, 6301155Sbill (float)forkstat.sizvfork / forkstat.cntvfork); 6311155Sbill } 6321155Sbill 6331155Sbill stats(dn) 6341155Sbill { 6351155Sbill 63618761Ssam if (dn >= dk_ndrive) { 637*45834Sbostic (void) printf(" 0"); 6381155Sbill return; 6391155Sbill } 640*45834Sbostic (void) printf("%3.0f", s.xfer[dn]/etime); 6411155Sbill } 6421155Sbill 6431155Sbill double 6441155Sbill stat1(row) 6451155Sbill { 6461448Sbill double t; 6471448Sbill register i; 6481155Sbill 6491155Sbill t = 0; 6501155Sbill for(i=0; i<CPUSTATES; i++) 6511448Sbill t += s.time[i]; 6521448Sbill if(t == 0.) 6531448Sbill t = 1.; 6541448Sbill return(s.time[row]*100./t); 6551155Sbill } 6561155Sbill 657*45834Sbostic dointr() 6581155Sbill { 659*45834Sbostic register int nintr, inamlen; 660*45834Sbostic register long *intrcnt, inttotal, uptime = getuptime(); 661*45834Sbostic register char *intrname; 6621155Sbill 663*45834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 664*45834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 665*45834Sbostic intrcnt = (long *)malloc((size_t)nintr); 666*45834Sbostic intrname = malloc((size_t)inamlen); 66717262Smckusick if (intrcnt == NULL || intrname == NULL) { 668*45834Sbostic (void) fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 66917262Smckusick exit(9); 67017262Smckusick } 671*45834Sbostic kread(X_INTRCNT, (char *)intrcnt, (size_t)nintr); 672*45834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 673*45834Sbostic (void) printf("interrupt total rate\n"); 67417262Smckusick inttotal = 0; 675*45834Sbostic nintr /= sizeof(long); 676*45834Sbostic while (--nintr >= 0) { 67717262Smckusick if (*intrcnt) 678*45834Sbostic (void) printf("%-12s %8ld %8ld\n", intrname, 679*45834Sbostic *intrcnt, *intrcnt / uptime); 68017262Smckusick intrname += strlen(intrname) + 1; 68117262Smckusick inttotal += *intrcnt++; 68217262Smckusick } 683*45834Sbostic (void) printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 68417262Smckusick } 68517262Smckusick 68633610Smckusick /* 68745152Smckusick * These names are defined in <sys/malloc.h>. 68833610Smckusick */ 68945152Smckusick char *kmemnames[] = INITKMEMNAMES; 69033610Smckusick 69133610Smckusick domem() 69233610Smckusick { 693*45834Sbostic register struct kmembuckets *kp; 694*45834Sbostic register struct kmemstats *ks; 695*45834Sbostic register int i; 69633610Smckusick struct kmemstats kmemstats[M_LAST]; 69733610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 69833610Smckusick 699*45834Sbostic kread(X_KMEMBUCKETS, (char *)buckets, sizeof buckets); 700*45834Sbostic (void) printf("Memory statistics by bucket size\n"); 701*45834Sbostic (void) printf( 702*45834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 70333610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 70433610Smckusick if (kp->kb_calls == 0) 70533610Smckusick continue; 706*45834Sbostic (void) printf("%8d%9ld%7ld%11ld%8ld%11ld\n", 1 << i, 70733610Smckusick kp->kb_total - kp->kb_totalfree, 70833610Smckusick kp->kb_totalfree, kp->kb_calls, 70933610Smckusick kp->kb_highwat, kp->kb_couldfree); 71033610Smckusick 71133610Smckusick } 712*45834Sbostic kread(X_KMEMSTAT, (char *)kmemstats, sizeof kmemstats); 713*45834Sbostic (void) printf("Memory statistics by type\n"); 714*45834Sbostic (void) printf("\ 715*45834Sbostic Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 71633610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 71733610Smckusick if (ks->ks_calls == 0) 71833610Smckusick continue; 719*45834Sbostic (void) printf("%10s%7ld%8ldK%9ldK%6ldK%9ld%7u%10u\n", 72033610Smckusick kmemnames[i] ? kmemnames[i] : "undefined", 72133610Smckusick ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 72233610Smckusick (ks->ks_maxused + 1023) / 1024, 72333610Smckusick (ks->ks_limit + 1023) / 1024, ks->ks_calls, 72433610Smckusick ks->ks_limblocks, ks->ks_mapblocks); 72533610Smckusick } 72633610Smckusick } 72733610Smckusick 7283162Stoy /* 7293162Stoy * Read the drive names out of kmem. 7303162Stoy */ 73110826Ssam #ifdef vax 732*45834Sbostic #include <uba/ubavar.h> 733*45834Sbostic #include <mba/mbavar.h> 73418761Ssam 7353162Stoy read_names() 7363162Stoy { 737*45834Sbostic register char *p; 738*45834Sbostic unsigned long mp, up; 7393162Stoy struct mba_device mdev; 7403162Stoy struct mba_driver mdrv; 741*45834Sbostic struct uba_device udev; 7423162Stoy struct uba_driver udrv; 743*45834Sbostic char name[10]; 744*45834Sbostic static char buf[BUFSIZ]; 7453162Stoy 746*45834Sbostic mp = nl[X_MBDINIT].n_value; 747*45834Sbostic up = nl[X_UBDINIT].n_value; 748*45834Sbostic if (mp == 0 && up == 0) { 749*45834Sbostic (void) fprintf(stderr, 750*45834Sbostic "vmstat: disk init info not in namelist\n"); 7513162Stoy exit(1); 7523162Stoy } 753*45834Sbostic p = buf; 754*45834Sbostic if (mp) for (;; mp += sizeof mdev) { 755*45834Sbostic (void) kvm_read((u_long)mp, (char *)&mdev, sizeof mdev); 7563162Stoy if (mdev.mi_driver == 0) 7573162Stoy break; 7583162Stoy if (mdev.mi_dk < 0 || mdev.mi_alive == 0) 7593162Stoy continue; 760*45834Sbostic (void) kvm_read((u_long)mdev.mi_driver, 761*45834Sbostic (char *)&mdrv, sizeof mdrv); 762*45834Sbostic (void) kvm_read((u_long)mdrv.md_dname, name, sizeof name); 763*45834Sbostic dr_name[mdev.mi_dk] = p; 764*45834Sbostic p += sprintf(p, "%s%d", name, mdev.mi_unit); 7653162Stoy } 766*45834Sbostic if (up) for (;; up += sizeof udev) { 767*45834Sbostic (void) kvm_read(up, (char *)&udev, sizeof udev); 7683162Stoy if (udev.ui_driver == 0) 7693162Stoy break; 7703162Stoy if (udev.ui_dk < 0 || udev.ui_alive == 0) 7713162Stoy continue; 772*45834Sbostic (void) kvm_read((u_long)udev.ui_driver, 773*45834Sbostic (char *)&udrv, sizeof udrv); 774*45834Sbostic (void) kvm_read((u_long)udrv.ud_dname, name, sizeof name); 775*45834Sbostic dr_name[udev.ui_dk] = p; 776*45834Sbostic p += sprintf(p, "%s%d", name, udev.ui_unit); 7773162Stoy } 7783162Stoy } 77910826Ssam #endif 78025708Ssam 78125708Ssam #ifdef tahoe 782*45834Sbostic #include <vba/vbavar.h> 78325708Ssam 78425708Ssam /* 78525708Ssam * Read the drive names out of kmem. 78625708Ssam */ 78725708Ssam read_names() 78825708Ssam { 789*45834Sbostic register char *p; 79025708Ssam struct vba_device udev, *up; 79125708Ssam struct vba_driver udrv; 792*45834Sbostic char name[10]; 793*45834Sbostic static char buf[BUFSIZ]; 79425708Ssam 79525708Ssam up = (struct vba_device *) nl[X_VBDINIT].n_value; 79625708Ssam if (up == 0) { 797*45834Sbostic (void) fprintf(stderr, 798*45834Sbostic "vmstat: disk init info not in namelist\n"); 79925708Ssam exit(1); 80025708Ssam } 801*45834Sbostic p = buf; 802*45834Sbostic for (;; up += sizeof udev) { 803*45834Sbostic (void) kvm_read(up, (char *)&udev, sizeof udev); 80425708Ssam if (udev.ui_driver == 0) 80525708Ssam break; 80625708Ssam if (udev.ui_dk < 0 || udev.ui_alive == 0) 80725708Ssam continue; 808*45834Sbostic (void) kvm_read((u_long)udev.ui_driver, 809*45834Sbostic (char *)&udrv, sizeof udrv); 810*45834Sbostic (void) kvm_read((u_long)udrv.ud_dname, name, sizeof name); 811*45834Sbostic dr_name[udev.ui_dk] = p; 812*45834Sbostic p += sprintf(p, "%s%d", name, udev.ui_unit); 81325708Ssam } 81425708Ssam } 81525708Ssam #endif 81642952Sbostic 81742952Sbostic #ifdef hp300 81842952Sbostic #include <hpdev/device.h> 81942952Sbostic 82042952Sbostic read_names() 82142952Sbostic { 822*45834Sbostic register char *p; 823*45834Sbostic register u_long hp; 82442952Sbostic struct hp_device hdev; 82542952Sbostic struct driver hdrv; 826*45834Sbostic static char buf[BUFSIZ]; 82742952Sbostic 828*45834Sbostic hp = nl[X_HPDINIT].n_value; 82942952Sbostic if (hp == 0) { 830*45834Sbostic (void) fprintf(stderr, 831*45834Sbostic "vmstat: disk init info not in namelist\n"); 83242952Sbostic exit(1); 83342952Sbostic } 834*45834Sbostic p = buf; 835*45834Sbostic for (;; hp += sizeof hdev) { 836*45834Sbostic (void) kvm_read(hp, (char *)&hdev, sizeof hdev); 83742952Sbostic if (hdev.hp_driver == 0) 83842952Sbostic break; 839*45834Sbostic if (hdev.hp_dk < 0 || hdev.hp_alive == 0) 84042952Sbostic continue; 841*45834Sbostic (void) kvm_read((u_long)hdev.hp_driver, 842*45834Sbostic (char *)&hdrv, sizeof hdrv); 843*45834Sbostic (void) kvm_read((u_long)hdrv.d_name, name, sizeof name); 844*45834Sbostic dr_name[hdev.hp_dk] = p; 845*45834Sbostic p += sprintf(p, "%s%d", name, hdev.hp_unit); 84642952Sbostic } 84742952Sbostic } 84842952Sbostic #endif 849