121585Sdist /* 2*48570Sbostic * Copyright (c) 1980, 1986, 1991 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[] = 10*48570Sbostic "@(#) Copyright (c) 1980, 1986, 1991 The Regents of the University of California.\n\ 1121585Sdist All rights reserved.\n"; 1236580Sbostic #endif /* not lint */ 1310826Ssam 1421585Sdist #ifndef lint 15*48570Sbostic static char sccsid[] = "@(#)vmstat.c 5.25 (Berkeley) 04/23/91"; 1636580Sbostic #endif /* not lint */ 1721585Sdist 181155Sbill #include <sys/param.h> 191155Sbill #include <sys/vm.h> 2046892Sbostic #include <sys/user.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> 26*48570Sbostic #include <signal.h> 27*48570Sbostic #include <fcntl.h> 28*48570Sbostic #include <time.h> 29*48570Sbostic #include <nlist.h> 30*48570Sbostic #include <kvm.h> 3145834Sbostic #include <errno.h> 32*48570Sbostic #include <unistd.h> 3345834Sbostic #include <stdio.h> 34*48570Sbostic #include <ctype.h> 3545834Sbostic #include <stdlib.h> 3645834Sbostic #include <string.h> 3737912Sbostic #include <paths.h> 381155Sbill 391155Sbill struct nlist nl[] = { 401448Sbill #define X_CPTIME 0 411448Sbill { "_cp_time" }, 421448Sbill #define X_RATE 1 431155Sbill { "_rate" }, 441448Sbill #define X_TOTAL 2 451155Sbill { "_total" }, 461448Sbill #define X_DEFICIT 3 471155Sbill { "_deficit" }, 481448Sbill #define X_FORKSTAT 4 491155Sbill { "_forkstat" }, 501448Sbill #define X_SUM 5 511155Sbill { "_sum" }, 52*48570Sbostic #define X_BOOTTIME 6 539249Ssam { "_boottime" }, 54*48570Sbostic #define X_DKXFER 7 551448Sbill { "_dk_xfer" }, 56*48570Sbostic #define X_REC 8 571155Sbill { "_rectime" }, 58*48570Sbostic #define X_PGIN 9 591155Sbill { "_pgintime" }, 60*48570Sbostic #define X_HZ 10 613162Stoy { "_hz" }, 62*48570Sbostic #define X_PHZ 11 6315266Ssam { "_phz" }, 64*48570Sbostic #define X_NCHSTATS 12 6515807Smckusick { "_nchstats" }, 66*48570Sbostic #define X_INTRNAMES 13 6717262Smckusick { "_intrnames" }, 68*48570Sbostic #define X_EINTRNAMES 14 6917262Smckusick { "_eintrnames" }, 70*48570Sbostic #define X_INTRCNT 15 7117262Smckusick { "_intrcnt" }, 72*48570Sbostic #define X_EINTRCNT 16 7317262Smckusick { "_eintrcnt" }, 74*48570Sbostic #define X_DK_NDRIVE 17 7518761Ssam { "_dk_ndrive" }, 76*48570Sbostic #define X_XSTATS 18 7725512Ssam { "_xstats" }, 78*48570Sbostic #define X_KMEMSTAT 19 7933610Smckusick { "_kmemstats" }, 80*48570Sbostic #define X_KMEMBUCKETS 20 8133610Smckusick { "_bucket" }, 82*48570Sbostic #define X_END 20 83*48570Sbostic #ifdef hp300 84*48570Sbostic #define X_HPDINIT (X_END+1) 85*48570Sbostic { "_hp_dinit" }, 8610826Ssam #endif 8725708Ssam #ifdef tahoe 8842952Sbostic #define X_VBDINIT (X_END+1) 8925708Ssam { "_vbdinit" }, 9042952Sbostic #define X_CKEYSTATS (X_END+2) 9125960Ssam { "_ckeystats" }, 9242952Sbostic #define X_DKEYSTATS (X_END+3) 9325960Ssam { "_dkeystats" }, 9425708Ssam #endif 95*48570Sbostic #ifdef vax 96*48570Sbostic #define X_MBDINIT (X_END+1) 97*48570Sbostic { "_mbdinit" }, 98*48570Sbostic #define X_UBDINIT (X_END+2) 99*48570Sbostic { "_ubdinit" }, 10042952Sbostic #endif 10110826Ssam { "" }, 1021155Sbill }; 1031155Sbill 104*48570Sbostic struct _disk { 105*48570Sbostic long time[CPUSTATES]; 106*48570Sbostic long *xfer; 107*48570Sbostic } cur, last; 10818761Ssam 109*48570Sbostic struct vmmeter sum; 110*48570Sbostic double etime, stat1(); 111*48570Sbostic char *vmunix = _PATH_UNIX; 112*48570Sbostic char **dr_name; 113*48570Sbostic int *dr_select, dk_ndrive, ndrives; 1141155Sbill 11545834Sbostic #define FORKSTAT 0x01 11645834Sbostic #define INTRSTAT 0x02 11745834Sbostic #define MEMSTAT 0x04 11845834Sbostic #define SUMSTAT 0x08 11945834Sbostic #define TIMESTAT 0x10 12045834Sbostic #define VMSTAT 0x20 12145834Sbostic #define ZEROOUT 0x40 12245834Sbostic 123*48570Sbostic void kread(); 124*48570Sbostic 125*48570Sbostic #include "names.c" /* disk names -- machine dependent */ 126*48570Sbostic 127*48570Sbostic void doforkst(), dointr(), domem(), dosum(), dotimes(), dovmstat(); 128*48570Sbostic void stats(), usage(), zero(); 129*48570Sbostic 1301155Sbill main(argc, argv) 13145834Sbostic register int argc; 13245834Sbostic register char **argv; 1331155Sbill { 13445834Sbostic extern int optind; 13545834Sbostic extern char *optarg; 136*48570Sbostic register int c, todo; 137*48570Sbostic u_int interval; 138*48570Sbostic int reps; 139*48570Sbostic char *kmem; 1401155Sbill 141*48570Sbostic kmem = NULL; 142*48570Sbostic interval = reps = todo = 0; 143*48570Sbostic while ((c = getopt(argc, argv, "c:fiM:mN:stw:z")) != EOF) { 14445834Sbostic switch (c) { 145*48570Sbostic case 'c': 146*48570Sbostic reps = atoi(optarg); 147*48570Sbostic break; 14845834Sbostic case 'f': 14945834Sbostic todo |= FORKSTAT; 15045834Sbostic break; 15145834Sbostic case 'i': 15245834Sbostic todo |= INTRSTAT; 15345834Sbostic break; 154*48570Sbostic case 'M': 15545834Sbostic kmem = optarg; 15645834Sbostic break; 15745834Sbostic case 'm': 15845834Sbostic todo |= MEMSTAT; 15945834Sbostic break; 160*48570Sbostic case 'N': 161*48570Sbostic vmunix = optarg; 162*48570Sbostic break; 16345834Sbostic case 's': 16445834Sbostic todo |= SUMSTAT; 16545834Sbostic break; 16645834Sbostic case 't': 16745834Sbostic todo |= TIMESTAT; 16845834Sbostic break; 169*48570Sbostic case 'w': 170*48570Sbostic interval = atoi(optarg); 17145834Sbostic break; 17245834Sbostic case 'z': 17345834Sbostic todo |= ZEROOUT; 17445834Sbostic break; 17545834Sbostic case '?': 176*48570Sbostic default: 17745834Sbostic usage(); 17845834Sbostic } 17945834Sbostic } 180*48570Sbostic argc -= optind; 181*48570Sbostic argv += optind; 18245834Sbostic 18345834Sbostic if (todo & ZEROOUT) { 18445834Sbostic if (todo & ~ZEROOUT || kmem) 18545834Sbostic usage(); 186*48570Sbostic zero(); 18745834Sbostic exit(0); 18845834Sbostic } 18945834Sbostic 19045834Sbostic if (todo == 0) 19145834Sbostic todo = VMSTAT; 19245834Sbostic 193*48570Sbostic if (kvm_openfiles(vmunix, kmem, NULL) < 0) { 194*48570Sbostic (void)fprintf(stderr, 195*48570Sbostic "vmstat: kvm_openfiles: %s\n", kvm_geterr()); 1961155Sbill exit(1); 1971155Sbill } 19845834Sbostic 199*48570Sbostic (void)kvm_nlist(nl); 20045834Sbostic if (nl[0].n_type == 0) { 201*48570Sbostic (void)fprintf(stderr, 202*48570Sbostic "vmstat: %s: no namelist\n", vmunix); 2031155Sbill exit(1); 2041155Sbill } 2051155Sbill 206*48570Sbostic if (todo & VMSTAT) { 207*48570Sbostic char **getdrivedata(); 208*48570Sbostic 209*48570Sbostic argv = getdrivedata(argv); 210*48570Sbostic } 211*48570Sbostic 212*48570Sbostic #define BACKWARD_COMPATIBILITY 213*48570Sbostic #ifdef BACKWARD_COMPATIBILITY 214*48570Sbostic if (*argv) { 215*48570Sbostic interval = atoi(*argv); 216*48570Sbostic if (*++argv) 217*48570Sbostic reps = atoi(*argv); 218*48570Sbostic } 219*48570Sbostic #endif 220*48570Sbostic 22145834Sbostic if (todo & FORKSTAT) 22245834Sbostic doforkst(); 22345834Sbostic if (todo & MEMSTAT) 22445834Sbostic domem(); 22545834Sbostic if (todo & SUMSTAT) 22645834Sbostic dosum(); 22745834Sbostic if (todo & TIMESTAT) 22845834Sbostic dotimes(); 22945834Sbostic if (todo & INTRSTAT) 23045834Sbostic dointr(); 231*48570Sbostic if (todo & VMSTAT) 232*48570Sbostic dovmstat(interval, reps); 23345834Sbostic exit(0); 23445834Sbostic } 23510826Ssam 236*48570Sbostic char ** 237*48570Sbostic getdrivedata(argv) 23845834Sbostic char **argv; 23945834Sbostic { 24045834Sbostic register int i; 24145834Sbostic register char **cp; 24245834Sbostic char buf[30]; 24345834Sbostic 244*48570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 24518761Ssam if (dk_ndrive <= 0) { 246*48570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 24718761Ssam exit(1); 24818761Ssam } 249*48570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 250*48570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 25145834Sbostic for (i = 0; i < dk_ndrive; i++) 25245834Sbostic dr_name[i] = NULL; 253*48570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 254*48570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 2553162Stoy read_names(); 256*48570Sbostic for (i = 0; i < dk_ndrive; i++) 25745834Sbostic if (dr_name[i] == NULL) { 258*48570Sbostic (void)sprintf(buf, "??%d", i); 25945834Sbostic dr_name[i] = strdup(buf); 26045834Sbostic } 26145834Sbostic 26218761Ssam /* 263*48570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives 264*48570Sbostic * supplied as arguments, default drives. If everything isn't filled 265*48570Sbostic * in and there are drives not taken care of, display the first few 266*48570Sbostic * that fit. 26718761Ssam */ 268*48570Sbostic #define BACKWARD_COMPATIBILITY 269*48570Sbostic for (ndrives = 0; *argv; ++argv) { 270*48570Sbostic #ifdef BACKWARD_COMPATIBILITY 271*48570Sbostic if (isdigit(**argv)) 272*48570Sbostic break; 273*48570Sbostic #endif 27418761Ssam for (i = 0; i < dk_ndrive; i++) { 275*48570Sbostic if (strcmp(dr_name[i], *argv)) 27618761Ssam continue; 27718761Ssam dr_select[i] = 1; 278*48570Sbostic ++ndrives; 27945834Sbostic break; 28018761Ssam } 28118761Ssam } 28218761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 28318761Ssam if (dr_select[i]) 28418761Ssam continue; 28518761Ssam for (cp = defdrives; *cp; cp++) 28618761Ssam if (strcmp(dr_name[i], *cp) == 0) { 28718761Ssam dr_select[i] = 1; 288*48570Sbostic ++ndrives; 28918761Ssam break; 29018761Ssam } 29118761Ssam } 29218761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 29318761Ssam if (dr_select[i]) 29418761Ssam continue; 29518761Ssam dr_select[i] = 1; 296*48570Sbostic ++ndrives; 29718761Ssam } 298*48570Sbostic return(argv); 29945834Sbostic } 30045834Sbostic 30145834Sbostic long 30245834Sbostic getuptime() 30345834Sbostic { 304*48570Sbostic static time_t now, boottime; 305*48570Sbostic time_t uptime; 30645834Sbostic 30745834Sbostic if (boottime == 0) 308*48570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime)); 309*48570Sbostic (void)time(&now); 31045834Sbostic uptime = now - boottime; 31145834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 312*48570Sbostic (void)fprintf(stderr, 31345834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 31445834Sbostic exit(1); 31545834Sbostic } 316*48570Sbostic return(uptime); 31745834Sbostic } 31845834Sbostic 319*48570Sbostic void 320*48570Sbostic dovmstat(interval, reps) 321*48570Sbostic u_int interval; 322*48570Sbostic int reps; 32345834Sbostic { 324*48570Sbostic struct vmmeter rate; 325*48570Sbostic struct vmtotal total; 32645834Sbostic register int i; 327*48570Sbostic time_t uptime; 328*48570Sbostic long tmp; 329*48570Sbostic int deficit, hdrcnt, HZ, hz, phz; 330*48570Sbostic void printhdr(); 33145834Sbostic 332*48570Sbostic uptime = getuptime(); 333*48570Sbostic (void)signal(SIGCONT, printhdr); 334*48570Sbostic 335*48570Sbostic kread(X_HZ, &hz, sizeof(hz)); 336*48570Sbostic if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 337*48570Sbostic kread(X_PHZ, &phz, sizeof(phz)); 338*48570Sbostic HZ = phz ? phz : hz; 339*48570Sbostic 340*48570Sbostic for (hdrcnt = 1;;) { 341*48570Sbostic if (!--hdrcnt) { 342*48570Sbostic printhdr(); 343*48570Sbostic hdrcnt = 20; 344*48570Sbostic } 345*48570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time)); 346*48570Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 347*48570Sbostic if (uptime != 1) 348*48570Sbostic kread(X_SUM, &rate, sizeof(rate)); 349*48570Sbostic else 350*48570Sbostic kread(X_RATE, &rate, sizeof(rate)); 351*48570Sbostic kread(X_TOTAL, &total, sizeof(total)); 352*48570Sbostic kread(X_SUM, &sum, sizeof(sum)); 353*48570Sbostic kread(X_DEFICIT, &deficit, sizeof(deficit)); 354*48570Sbostic etime = 0; 355*48570Sbostic for (i = 0; i < dk_ndrive; i++) { 356*48570Sbostic tmp = cur.xfer[i]; 357*48570Sbostic cur.xfer[i] -= last.xfer[i]; 358*48570Sbostic last.xfer[i] = tmp; 359*48570Sbostic } 360*48570Sbostic for (i = 0; i < CPUSTATES; i++) { 361*48570Sbostic tmp = cur.time[i]; 362*48570Sbostic cur.time[i] -= last.time[i]; 363*48570Sbostic last.time[i] = tmp; 364*48570Sbostic etime += cur.time[i]; 365*48570Sbostic } 366*48570Sbostic if (etime == 0.) 367*48570Sbostic etime = 1.; 368*48570Sbostic (void)printf("%2d%2d%2d", 369*48570Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 37045834Sbostic #define pgtok(a) ((a)*NBPG >> 10) 371*48570Sbostic (void)printf("%6ld%6ld", 372*48570Sbostic pgtok(total.t_avm), pgtok(total.t_free)); 373*48570Sbostic (void)printf("%4lu%3lu", 374*48570Sbostic (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec)) / uptime, 375*48570Sbostic (rate.v_xsfrec+rate.v_xifrec) / uptime); 376*48570Sbostic (void)printf("%4lu", pgtok(rate.v_pgpgin) / uptime); 377*48570Sbostic (void)printf("%4lu%4lu%4d%4lu", pgtok(rate.v_pgpgout) / uptime, 378*48570Sbostic pgtok(rate.v_dfree) / uptime, 379*48570Sbostic pgtok(deficit), rate.v_scan / uptime); 380*48570Sbostic etime /= (float)HZ; 381*48570Sbostic for (i = 0; i < dk_ndrive; i++) 382*48570Sbostic if (dr_select[i]) 383*48570Sbostic stats(i); 384*48570Sbostic #define INTS(x) ((x) - (hz + phz)) 385*48570Sbostic (void)printf("%4lu%4lu%4lu", INTS(rate.v_intr / uptime), 386*48570Sbostic rate.v_syscall / uptime, rate.v_swtch / uptime); 387*48570Sbostic for (i = 0; i < CPUSTATES; i++) { 388*48570Sbostic double f; 389*48570Sbostic 390*48570Sbostic f = stat1(i); 391*48570Sbostic if (i == 0) { /* US+NI */ 392*48570Sbostic i++; 393*48570Sbostic f += stat1(i); 394*48570Sbostic } 395*48570Sbostic (void)printf("%3.0f", f); 3961155Sbill } 397*48570Sbostic (void)printf("\n"); 398*48570Sbostic (void)fflush(stdout); 399*48570Sbostic uptime = 1; 400*48570Sbostic if (--reps <= 0) 401*48570Sbostic break; 402*48570Sbostic if (interval) 403*48570Sbostic sleep(interval); 4041155Sbill } 4051155Sbill } 4061155Sbill 40745834Sbostic void 40817262Smckusick printhdr() 40917262Smckusick { 410*48570Sbostic register int i; 41118761Ssam 412*48570Sbostic (void)printf(" procs memory page%*s", 22, ""); 413*48570Sbostic if (ndrives > 1) 414*48570Sbostic (void)printf("disks %*s faults cpu\n", 415*48570Sbostic ndrives * 3 - 6, ""); 416*48570Sbostic else 417*48570Sbostic (void)printf("%*s faults cpu\n", ndrives * 3, ""); 418*48570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr "); 41918761Ssam for (i = 0; i < dk_ndrive; i++) 42018761Ssam if (dr_select[i]) 421*48570Sbostic (void)printf("%c%c ", dr_name[i][0], 42245834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 423*48570Sbostic (void)printf(" in sy cs us sy id\n"); 42417262Smckusick } 42517262Smckusick 426*48570Sbostic void 4271155Sbill dotimes() 4281155Sbill { 429*48570Sbostic u_int pgintime, rectime; 4301155Sbill 431*48570Sbostic kread(X_REC, &rectime, sizeof(rectime)); 432*48570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime)); 433*48570Sbostic kread(X_SUM, &sum, sizeof(sum)); 434*48570Sbostic (void)printf("%u reclaims, %u total time (usec)\n", 435*48570Sbostic sum.v_pgrec, rectime); 436*48570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 437*48570Sbostic (void)printf("\n"); 438*48570Sbostic (void)printf("%u page ins, %u total time (msec)\n", 439*48570Sbostic sum.v_pgin, pgintime / 10); 440*48570Sbostic (void)printf("average: %8.1f msec / page in\n", 441*48570Sbostic pgintime / (sum.v_pgin * 10.0)); 4421155Sbill } 4431155Sbill 44445834Sbostic pct(top, bot) 44545834Sbostic long top, bot; 44645834Sbostic { 44745834Sbostic if (bot == 0) 448*48570Sbostic return(0); 449*48570Sbostic return((top * 100) / bot); 45045834Sbostic } 45145834Sbostic 45245834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 45345834Sbostic 45430069Ssam #if defined(tahoe) 45545834Sbostic #include <machine/cpu.h> 45630069Ssam #endif 45730069Ssam 458*48570Sbostic void 4591155Sbill dosum() 4601155Sbill { 46118761Ssam struct nchstats nchstats; 46225960Ssam struct xstats xstats; 46315807Smckusick long nchtotal; 46425960Ssam #if defined(tahoe) 46525960Ssam struct keystats keystats; 46625960Ssam #endif 4671155Sbill 468*48570Sbostic kread(X_SUM, &sum, sizeof(sum)); 469*48570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin); 470*48570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout); 471*48570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 472*48570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 473*48570Sbostic (void)printf("%9u total address trans. faults taken\n", sum.v_faults); 474*48570Sbostic (void)printf("%9u page ins\n", sum.v_pgin); 475*48570Sbostic (void)printf("%9u page outs\n", sum.v_pgout); 476*48570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin); 477*48570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout); 478*48570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 479*48570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 48045834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 481*48570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 482*48570Sbostic (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 483*48570Sbostic (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 484*48570Sbostic (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 485*48570Sbostic (void)printf("%9u executable fill pages created\n", 48645834Sbostic sum.v_nexfod / CLSIZE); 487*48570Sbostic (void)printf("%9u executable fill page faults\n", 48845834Sbostic sum.v_exfod / CLSIZE); 489*48570Sbostic (void)printf("%9u swap text pages found in free list\n", 49045834Sbostic sum.v_xsfrec); 491*48570Sbostic (void)printf("%9u inode text pages found in free list\n", 49245834Sbostic sum.v_xifrec); 493*48570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 494*48570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 495*48570Sbostic (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 496*48570Sbostic (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 497*48570Sbostic (void)printf("%9u pages freed by the clock daemon\n", 49845834Sbostic sum.v_dfree / CLSIZE); 499*48570Sbostic (void)printf("%9u cpu context switches\n", sum.v_swtch); 500*48570Sbostic (void)printf("%9u device interrupts\n", sum.v_intr); 501*48570Sbostic (void)printf("%9u software interrupts\n", sum.v_soft); 50218761Ssam #ifdef vax 503*48570Sbostic (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 50418761Ssam #endif 505*48570Sbostic (void)printf("%9u traps\n", sum.v_trap); 506*48570Sbostic (void)printf("%9u system calls\n", sum.v_syscall); 507*48570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 50838773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 50938773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 51038773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 511*48570Sbostic (void)printf("%9ld total name lookups\n", nchtotal); 512*48570Sbostic (void)printf( 51345834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 51445834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 51545834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 51645834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 517*48570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 51845834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 51945834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 52045834Sbostic PCT(nchstats.ncs_long, nchtotal)); 521*48570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats)); 522*48570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 52345834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 524*48570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 52525512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 526*48570Sbostic (void)printf("%9lu total calls to xfree", xstats.free); 527*48570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 52825512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 52925960Ssam #if defined(tahoe) 530*48570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 531*48570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 53225960Ssam keystats.ks_allocs, "code cache keys allocated", 53345834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 53445834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 53545834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 53645834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 537*48570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 538*48570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 53925960Ssam keystats.ks_allocs, "data cache keys allocated", 54045834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 54145834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 54245834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 54345834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 54425960Ssam #endif 5451155Sbill } 5461155Sbill 547*48570Sbostic void 5481155Sbill doforkst() 5491155Sbill { 550*48570Sbostic struct forkstat fks; 5511155Sbill 552*48570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 553*48570Sbostic (void)printf("%d forks, %d pages, average %.2f\n", 554*48570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 555*48570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n", 556*48570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 5571155Sbill } 5581155Sbill 559*48570Sbostic void 5601155Sbill stats(dn) 561*48570Sbostic int dn; 5621155Sbill { 563*48570Sbostic if (dn >= dk_ndrive) 564*48570Sbostic (void)printf(" 0"); 565*48570Sbostic else 566*48570Sbostic (void)printf("%3.0f", cur.xfer[dn] / etime); 5671155Sbill } 5681155Sbill 5691155Sbill double 5701155Sbill stat1(row) 571*48570Sbostic int row; 5721155Sbill { 573*48570Sbostic register int i; 5741448Sbill double t; 5751155Sbill 5761155Sbill t = 0; 577*48570Sbostic for (i = 0; i < CPUSTATES; i++) 578*48570Sbostic t += cur.time[i]; 579*48570Sbostic if (t == 0.) 5801448Sbill t = 1.; 581*48570Sbostic return(cur.time[row]*100./t); 5821155Sbill } 5831155Sbill 584*48570Sbostic void 58545834Sbostic dointr() 5861155Sbill { 587*48570Sbostic register long *intrcnt, inttotal, uptime; 58845834Sbostic register int nintr, inamlen; 58945834Sbostic register char *intrname; 5901155Sbill 591*48570Sbostic uptime = getuptime(); 59245834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 59345834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 594*48570Sbostic intrcnt = malloc((size_t)nintr); 59545834Sbostic intrname = malloc((size_t)inamlen); 59617262Smckusick if (intrcnt == NULL || intrname == NULL) { 597*48570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 598*48570Sbostic exit(1); 59917262Smckusick } 600*48570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr); 60145834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 602*48570Sbostic (void)printf("interrupt total rate\n"); 60317262Smckusick inttotal = 0; 60445834Sbostic nintr /= sizeof(long); 60545834Sbostic while (--nintr >= 0) { 60617262Smckusick if (*intrcnt) 607*48570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname, 60845834Sbostic *intrcnt, *intrcnt / uptime); 60917262Smckusick intrname += strlen(intrname) + 1; 61017262Smckusick inttotal += *intrcnt++; 61117262Smckusick } 612*48570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 61317262Smckusick } 61417262Smckusick 61533610Smckusick /* 61645152Smckusick * These names are defined in <sys/malloc.h>. 61733610Smckusick */ 61845152Smckusick char *kmemnames[] = INITKMEMNAMES; 61933610Smckusick 620*48570Sbostic void 62133610Smckusick domem() 62233610Smckusick { 62345834Sbostic register struct kmembuckets *kp; 62445834Sbostic register struct kmemstats *ks; 62545834Sbostic register int i; 62633610Smckusick struct kmemstats kmemstats[M_LAST]; 62733610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 62833610Smckusick 629*48570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 630*48570Sbostic (void)printf("Memory statistics by bucket size\n"); 631*48570Sbostic (void)printf( 63245834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 63333610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 63433610Smckusick if (kp->kb_calls == 0) 63533610Smckusick continue; 636*48570Sbostic (void)printf("%8d%9ld%7ld%11ld%8ld%11ld\n", 1 << i, 63733610Smckusick kp->kb_total - kp->kb_totalfree, 63833610Smckusick kp->kb_totalfree, kp->kb_calls, 63933610Smckusick kp->kb_highwat, kp->kb_couldfree); 64033610Smckusick 64133610Smckusick } 642*48570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 643*48570Sbostic (void)printf("\nMemory statistics by type\n"); 644*48570Sbostic (void)printf( 645*48570Sbostic " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 64633610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 64733610Smckusick if (ks->ks_calls == 0) 64833610Smckusick continue; 649*48570Sbostic (void)printf("%10s%7ld%8ldK%9ldK%6ldK%9ld%7u%10u\n", 650*48570Sbostic kmemnames[i] ? kmemnames[i] : "undefined", 651*48570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 652*48570Sbostic (ks->ks_maxused + 1023) / 1024, 653*48570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls, 654*48570Sbostic ks->ks_limblocks, ks->ks_mapblocks); 65533610Smckusick } 65633610Smckusick } 65733610Smckusick 658*48570Sbostic void 659*48570Sbostic zero() 6603162Stoy { 661*48570Sbostic struct nlist znl[] = { 662*48570Sbostic #undef X_SUM 663*48570Sbostic #define X_SUM 0 664*48570Sbostic { "_sum" }, 665*48570Sbostic { "" }, 666*48570Sbostic }; 667*48570Sbostic int fd; 668*48570Sbostic char *kmem; 6693162Stoy 670*48570Sbostic if (geteuid()) { 671*48570Sbostic (void)fprintf(stderr, "vmstat: %s\n", strerror(EPERM)); 6723162Stoy exit(1); 6733162Stoy } 674*48570Sbostic /* 675*48570Sbostic * Zeroing the statistics is fundamentally different 676*48570Sbostic * (and really belongs in a separate program). 677*48570Sbostic */ 678*48570Sbostic if (nlist(vmunix, znl) || nl[0].n_type == 0) { 679*48570Sbostic (void)fprintf(stderr, "vmstat: %s: symbol %s not found\n", 680*48570Sbostic vmunix, nl[0].n_name); 681*48570Sbostic exit(1); 6823162Stoy } 683*48570Sbostic 684*48570Sbostic kmem = _PATH_KMEM; 685*48570Sbostic if ((fd = open(kmem, O_RDWR)) < 0) { 686*48570Sbostic (void)fprintf(stderr, 687*48570Sbostic "vmstat: %s: %s\n", kmem, strerror(errno)); 688*48570Sbostic exit(1); 6893162Stoy } 690*48570Sbostic if (lseek(fd, (long)nl[0].n_value, L_SET) == -1 || 691*48570Sbostic write(fd, &sum, sizeof(sum)) != sizeof(sum)) { 692*48570Sbostic (void)fprintf(stderr, 693*48570Sbostic "vmstat: %s: %s\n", kmem, strerror(errno)); 694*48570Sbostic exit(1); 695*48570Sbostic } 6963162Stoy } 69725708Ssam 69825708Ssam /* 699*48570Sbostic * kread reads something from the kernel, given its nlist index. 70025708Ssam */ 701*48570Sbostic void 702*48570Sbostic kread(nlx, addr, size) 703*48570Sbostic int nlx; 704*48570Sbostic void *addr; 705*48570Sbostic size_t size; 70625708Ssam { 707*48570Sbostic char *sym; 70825708Ssam 709*48570Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 710*48570Sbostic sym = nl[nlx].n_name; 711*48570Sbostic if (*sym == '_') 712*48570Sbostic ++sym; 713*48570Sbostic (void)fprintf(stderr, 714*48570Sbostic "vmstat: %s: symbol %s not defined\n", vmunix, sym); 71525708Ssam exit(1); 71625708Ssam } 717*48570Sbostic if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { 718*48570Sbostic sym = nl[nlx].n_name; 719*48570Sbostic if (*sym == '_') 720*48570Sbostic ++sym; 721*48570Sbostic (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); 722*48570Sbostic exit(1); 72325708Ssam } 72425708Ssam } 72542952Sbostic 726*48570Sbostic void 727*48570Sbostic usage() 72842952Sbostic { 729*48570Sbostic (void)fprintf(stderr, 730*48570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \ 731*48570Sbostic [-N system] [-w wait] [disks]\n vmstat -z\n"); 732*48570Sbostic exit(1); 73342952Sbostic } 734