121585Sdist /* 248570Sbostic * 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[] = 1048570Sbostic "@(#) 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*49924Sbostic static char sccsid[] = "@(#)vmstat.c 5.27 (Berkeley) 05/29/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> 2648570Sbostic #include <signal.h> 2748570Sbostic #include <fcntl.h> 2848570Sbostic #include <time.h> 2948570Sbostic #include <nlist.h> 3048570Sbostic #include <kvm.h> 3145834Sbostic #include <errno.h> 3248570Sbostic #include <unistd.h> 3345834Sbostic #include <stdio.h> 3448570Sbostic #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" }, 5248570Sbostic #define X_BOOTTIME 6 539249Ssam { "_boottime" }, 5448570Sbostic #define X_DKXFER 7 551448Sbill { "_dk_xfer" }, 5648570Sbostic #define X_REC 8 571155Sbill { "_rectime" }, 5848570Sbostic #define X_PGIN 9 591155Sbill { "_pgintime" }, 6048570Sbostic #define X_HZ 10 613162Stoy { "_hz" }, 6248570Sbostic #define X_PHZ 11 6315266Ssam { "_phz" }, 6448570Sbostic #define X_NCHSTATS 12 6515807Smckusick { "_nchstats" }, 6648570Sbostic #define X_INTRNAMES 13 6717262Smckusick { "_intrnames" }, 6848570Sbostic #define X_EINTRNAMES 14 6917262Smckusick { "_eintrnames" }, 7048570Sbostic #define X_INTRCNT 15 7117262Smckusick { "_intrcnt" }, 7248570Sbostic #define X_EINTRCNT 16 7317262Smckusick { "_eintrcnt" }, 7448570Sbostic #define X_DK_NDRIVE 17 7518761Ssam { "_dk_ndrive" }, 7648570Sbostic #define X_XSTATS 18 7725512Ssam { "_xstats" }, 7848570Sbostic #define X_KMEMSTAT 19 7933610Smckusick { "_kmemstats" }, 8048570Sbostic #define X_KMEMBUCKETS 20 8133610Smckusick { "_bucket" }, 8248570Sbostic #define X_END 20 8348570Sbostic #ifdef hp300 8448570Sbostic #define X_HPDINIT (X_END+1) 8548570Sbostic { "_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 9548570Sbostic #ifdef vax 9648570Sbostic #define X_MBDINIT (X_END+1) 9748570Sbostic { "_mbdinit" }, 9848570Sbostic #define X_UBDINIT (X_END+2) 9948570Sbostic { "_ubdinit" }, 10042952Sbostic #endif 10110826Ssam { "" }, 1021155Sbill }; 1031155Sbill 10448570Sbostic struct _disk { 10548570Sbostic long time[CPUSTATES]; 10648570Sbostic long *xfer; 10748570Sbostic } cur, last; 10818761Ssam 10948570Sbostic struct vmmeter sum; 11048570Sbostic char *vmunix = _PATH_UNIX; 11148570Sbostic char **dr_name; 11248570Sbostic int *dr_select, dk_ndrive, ndrives; 1131155Sbill 11445834Sbostic #define FORKSTAT 0x01 11545834Sbostic #define INTRSTAT 0x02 11645834Sbostic #define MEMSTAT 0x04 11745834Sbostic #define SUMSTAT 0x08 11845834Sbostic #define TIMESTAT 0x10 11945834Sbostic #define VMSTAT 0x20 12045834Sbostic #define ZEROOUT 0x40 12145834Sbostic 12248570Sbostic #include "names.c" /* disk names -- machine dependent */ 12348570Sbostic 12448613Sbostic void cpustats(), dkstats(), doforkst(), dointr(), domem(), dosum(); 12548613Sbostic void dotimes(), dovmstat(), kread(), usage(), zero(); 12648570Sbostic 1271155Sbill main(argc, argv) 12845834Sbostic register int argc; 12945834Sbostic register char **argv; 1301155Sbill { 13145834Sbostic extern int optind; 13245834Sbostic extern char *optarg; 13348570Sbostic register int c, todo; 13448570Sbostic u_int interval; 13548570Sbostic int reps; 13648570Sbostic char *kmem; 1371155Sbill 13848570Sbostic kmem = NULL; 13948570Sbostic interval = reps = todo = 0; 14048570Sbostic while ((c = getopt(argc, argv, "c:fiM:mN:stw:z")) != EOF) { 14145834Sbostic switch (c) { 14248570Sbostic case 'c': 14348570Sbostic reps = atoi(optarg); 14448570Sbostic break; 14545834Sbostic case 'f': 14645834Sbostic todo |= FORKSTAT; 14745834Sbostic break; 14845834Sbostic case 'i': 14945834Sbostic todo |= INTRSTAT; 15045834Sbostic break; 15148570Sbostic case 'M': 15245834Sbostic kmem = optarg; 15345834Sbostic break; 15445834Sbostic case 'm': 15545834Sbostic todo |= MEMSTAT; 15645834Sbostic break; 15748570Sbostic case 'N': 15848570Sbostic vmunix = optarg; 15948570Sbostic break; 16045834Sbostic case 's': 16145834Sbostic todo |= SUMSTAT; 16245834Sbostic break; 16345834Sbostic case 't': 16445834Sbostic todo |= TIMESTAT; 16545834Sbostic break; 16648570Sbostic case 'w': 16748570Sbostic interval = atoi(optarg); 16845834Sbostic break; 16945834Sbostic case 'z': 17045834Sbostic todo |= ZEROOUT; 17145834Sbostic break; 17245834Sbostic case '?': 17348570Sbostic default: 17445834Sbostic usage(); 17545834Sbostic } 17645834Sbostic } 17748570Sbostic argc -= optind; 17848570Sbostic argv += optind; 17945834Sbostic 18045834Sbostic if (todo & ZEROOUT) { 18145834Sbostic if (todo & ~ZEROOUT || kmem) 18245834Sbostic usage(); 18348570Sbostic zero(); 18445834Sbostic exit(0); 18545834Sbostic } 18645834Sbostic 18745834Sbostic if (todo == 0) 18845834Sbostic todo = VMSTAT; 18945834Sbostic 19048570Sbostic if (kvm_openfiles(vmunix, kmem, NULL) < 0) { 19148570Sbostic (void)fprintf(stderr, 19248570Sbostic "vmstat: kvm_openfiles: %s\n", kvm_geterr()); 1931155Sbill exit(1); 1941155Sbill } 19545834Sbostic 19648570Sbostic (void)kvm_nlist(nl); 19745834Sbostic if (nl[0].n_type == 0) { 19848570Sbostic (void)fprintf(stderr, 19948570Sbostic "vmstat: %s: no namelist\n", vmunix); 2001155Sbill exit(1); 2011155Sbill } 2021155Sbill 20348570Sbostic if (todo & VMSTAT) { 20448570Sbostic char **getdrivedata(); 20548570Sbostic 20648570Sbostic argv = getdrivedata(argv); 20748570Sbostic } 20848570Sbostic 20948570Sbostic #define BACKWARD_COMPATIBILITY 21048570Sbostic #ifdef BACKWARD_COMPATIBILITY 21148570Sbostic if (*argv) { 21248570Sbostic interval = atoi(*argv); 21348570Sbostic if (*++argv) 21448570Sbostic reps = atoi(*argv); 21548570Sbostic } 21648570Sbostic #endif 21748570Sbostic 21848613Sbostic if (interval) { 21948613Sbostic if (!reps) 22048613Sbostic reps = -1; 22148613Sbostic } else 22248613Sbostic if (reps) 22348613Sbostic interval = 1; 22448613Sbostic 22545834Sbostic if (todo & FORKSTAT) 22645834Sbostic doforkst(); 22745834Sbostic if (todo & MEMSTAT) 22845834Sbostic domem(); 22945834Sbostic if (todo & SUMSTAT) 23045834Sbostic dosum(); 23145834Sbostic if (todo & TIMESTAT) 23245834Sbostic dotimes(); 23345834Sbostic if (todo & INTRSTAT) 23445834Sbostic dointr(); 23548570Sbostic if (todo & VMSTAT) 23648570Sbostic dovmstat(interval, reps); 23745834Sbostic exit(0); 23845834Sbostic } 23910826Ssam 24048570Sbostic char ** 24148570Sbostic getdrivedata(argv) 24245834Sbostic char **argv; 24345834Sbostic { 24445834Sbostic register int i; 24545834Sbostic register char **cp; 24645834Sbostic char buf[30]; 24745834Sbostic 24848570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive)); 24918761Ssam if (dk_ndrive <= 0) { 25048570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive); 25118761Ssam exit(1); 25218761Ssam } 25348570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int)); 25448570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *)); 25545834Sbostic for (i = 0; i < dk_ndrive; i++) 25645834Sbostic dr_name[i] = NULL; 25748570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 25848570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long)); 2593162Stoy read_names(); 26048570Sbostic for (i = 0; i < dk_ndrive; i++) 26145834Sbostic if (dr_name[i] == NULL) { 26248570Sbostic (void)sprintf(buf, "??%d", i); 26345834Sbostic dr_name[i] = strdup(buf); 26445834Sbostic } 26545834Sbostic 26618761Ssam /* 26748570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives 26848570Sbostic * supplied as arguments, default drives. If everything isn't filled 26948570Sbostic * in and there are drives not taken care of, display the first few 27048570Sbostic * that fit. 27118761Ssam */ 27248570Sbostic #define BACKWARD_COMPATIBILITY 27348570Sbostic for (ndrives = 0; *argv; ++argv) { 27448570Sbostic #ifdef BACKWARD_COMPATIBILITY 27548570Sbostic if (isdigit(**argv)) 27648570Sbostic break; 27748570Sbostic #endif 27818761Ssam for (i = 0; i < dk_ndrive; i++) { 27948570Sbostic if (strcmp(dr_name[i], *argv)) 28018761Ssam continue; 28118761Ssam dr_select[i] = 1; 28248570Sbostic ++ndrives; 28345834Sbostic break; 28418761Ssam } 28518761Ssam } 28618761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 28718761Ssam if (dr_select[i]) 28818761Ssam continue; 28918761Ssam for (cp = defdrives; *cp; cp++) 29018761Ssam if (strcmp(dr_name[i], *cp) == 0) { 29118761Ssam dr_select[i] = 1; 29248570Sbostic ++ndrives; 29318761Ssam break; 29418761Ssam } 29518761Ssam } 29618761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) { 29718761Ssam if (dr_select[i]) 29818761Ssam continue; 29918761Ssam dr_select[i] = 1; 30048570Sbostic ++ndrives; 30118761Ssam } 30248570Sbostic return(argv); 30345834Sbostic } 30445834Sbostic 30545834Sbostic long 30645834Sbostic getuptime() 30745834Sbostic { 30848570Sbostic static time_t now, boottime; 30948570Sbostic time_t uptime; 31045834Sbostic 31145834Sbostic if (boottime == 0) 31248570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime)); 31348570Sbostic (void)time(&now); 31445834Sbostic uptime = now - boottime; 31545834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) { 31648570Sbostic (void)fprintf(stderr, 31745834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n"); 31845834Sbostic exit(1); 31945834Sbostic } 32048570Sbostic return(uptime); 32145834Sbostic } 32245834Sbostic 32348613Sbostic int hz; 32448613Sbostic 32548570Sbostic void 32648570Sbostic dovmstat(interval, reps) 32748570Sbostic u_int interval; 32848570Sbostic int reps; 32945834Sbostic { 33048570Sbostic struct vmmeter rate; 33148570Sbostic struct vmtotal total; 33248570Sbostic time_t uptime; 33348613Sbostic int deficit, hdrcnt; 33448570Sbostic void printhdr(); 33545834Sbostic 33648570Sbostic uptime = getuptime(); 33748570Sbostic (void)signal(SIGCONT, printhdr); 33848570Sbostic 33948570Sbostic if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0) 34048613Sbostic kread(X_PHZ, &hz, sizeof(hz)); 34148613Sbostic if (!hz) 34248613Sbostic kread(X_HZ, &hz, sizeof(hz)); 34348570Sbostic 34448570Sbostic for (hdrcnt = 1;;) { 34548570Sbostic if (!--hdrcnt) { 34648570Sbostic printhdr(); 34748570Sbostic hdrcnt = 20; 34848570Sbostic } 34948570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time)); 35048570Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive)); 35148570Sbostic if (uptime != 1) 35248570Sbostic kread(X_SUM, &rate, sizeof(rate)); 35348570Sbostic else 35448570Sbostic kread(X_RATE, &rate, sizeof(rate)); 35548570Sbostic kread(X_TOTAL, &total, sizeof(total)); 35648570Sbostic kread(X_SUM, &sum, sizeof(sum)); 35748570Sbostic kread(X_DEFICIT, &deficit, sizeof(deficit)); 35848570Sbostic (void)printf("%2d%2d%2d", 35948570Sbostic total.t_rq, total.t_dw + total.t_pw, total.t_sw); 36045834Sbostic #define pgtok(a) ((a)*NBPG >> 10) 36148570Sbostic (void)printf("%6ld%6ld", 36248570Sbostic pgtok(total.t_avm), pgtok(total.t_free)); 36348570Sbostic (void)printf("%4lu%3lu", 36448570Sbostic (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec)) / uptime, 36548570Sbostic (rate.v_xsfrec+rate.v_xifrec) / uptime); 36648570Sbostic (void)printf("%4lu", pgtok(rate.v_pgpgin) / uptime); 36748570Sbostic (void)printf("%4lu%4lu%4d%4lu", pgtok(rate.v_pgpgout) / uptime, 36848570Sbostic pgtok(rate.v_dfree) / uptime, 36948570Sbostic pgtok(deficit), rate.v_scan / uptime); 37048613Sbostic dkstats(); 37148613Sbostic (void)printf("%4lu%4lu%4lu", rate.v_intr / uptime, 37248570Sbostic rate.v_syscall / uptime, rate.v_swtch / uptime); 37348613Sbostic cpustats(); 37448570Sbostic (void)printf("\n"); 37548570Sbostic (void)fflush(stdout); 37648570Sbostic uptime = 1; 37748613Sbostic if (reps >= 0 && --reps <= 0) 37848570Sbostic break; 37948613Sbostic (void)sleep(interval); 3801155Sbill } 3811155Sbill } 3821155Sbill 38345834Sbostic void 38417262Smckusick printhdr() 38517262Smckusick { 38648570Sbostic register int i; 38718761Ssam 38848570Sbostic (void)printf(" procs memory page%*s", 22, ""); 38948570Sbostic if (ndrives > 1) 39048570Sbostic (void)printf("disks %*s faults cpu\n", 39148570Sbostic ndrives * 3 - 6, ""); 39248570Sbostic else 39348570Sbostic (void)printf("%*s faults cpu\n", ndrives * 3, ""); 39448570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr "); 39518761Ssam for (i = 0; i < dk_ndrive; i++) 39618761Ssam if (dr_select[i]) 39748570Sbostic (void)printf("%c%c ", dr_name[i][0], 39845834Sbostic dr_name[i][strlen(dr_name[i]) - 1]); 39948570Sbostic (void)printf(" in sy cs us sy id\n"); 40017262Smckusick } 40117262Smckusick 40248570Sbostic void 4031155Sbill dotimes() 4041155Sbill { 40548570Sbostic u_int pgintime, rectime; 4061155Sbill 40748570Sbostic kread(X_REC, &rectime, sizeof(rectime)); 40848570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime)); 40948570Sbostic kread(X_SUM, &sum, sizeof(sum)); 41048570Sbostic (void)printf("%u reclaims, %u total time (usec)\n", 41148570Sbostic sum.v_pgrec, rectime); 41248570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec); 41348570Sbostic (void)printf("\n"); 41448570Sbostic (void)printf("%u page ins, %u total time (msec)\n", 41548570Sbostic sum.v_pgin, pgintime / 10); 41648570Sbostic (void)printf("average: %8.1f msec / page in\n", 41748570Sbostic pgintime / (sum.v_pgin * 10.0)); 4181155Sbill } 4191155Sbill 42045834Sbostic pct(top, bot) 42145834Sbostic long top, bot; 42245834Sbostic { 42345834Sbostic if (bot == 0) 42448570Sbostic return(0); 42548570Sbostic return((top * 100) / bot); 42645834Sbostic } 42745834Sbostic 42845834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot)) 42945834Sbostic 43030069Ssam #if defined(tahoe) 43145834Sbostic #include <machine/cpu.h> 43230069Ssam #endif 43330069Ssam 43448570Sbostic void 4351155Sbill dosum() 4361155Sbill { 43718761Ssam struct nchstats nchstats; 43825960Ssam struct xstats xstats; 43915807Smckusick long nchtotal; 44025960Ssam #if defined(tahoe) 44125960Ssam struct keystats keystats; 44225960Ssam #endif 4431155Sbill 44448570Sbostic kread(X_SUM, &sum, sizeof(sum)); 44548570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin); 44648570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout); 44748570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE); 44848570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE); 44948570Sbostic (void)printf("%9u total address trans. faults taken\n", sum.v_faults); 45048570Sbostic (void)printf("%9u page ins\n", sum.v_pgin); 45148570Sbostic (void)printf("%9u page outs\n", sum.v_pgout); 45248570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin); 45348570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout); 45448570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree); 45548570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec, 45645834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec)); 45748570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec); 45848570Sbostic (void)printf("%9u intransit blocking page faults\n", sum.v_intrans); 45948570Sbostic (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE); 46048570Sbostic (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE); 46148570Sbostic (void)printf("%9u executable fill pages created\n", 46245834Sbostic sum.v_nexfod / CLSIZE); 46348570Sbostic (void)printf("%9u executable fill page faults\n", 46445834Sbostic sum.v_exfod / CLSIZE); 46548570Sbostic (void)printf("%9u swap text pages found in free list\n", 46645834Sbostic sum.v_xsfrec); 46748570Sbostic (void)printf("%9u inode text pages found in free list\n", 46845834Sbostic sum.v_xifrec); 46948570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE); 47048570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE); 47148570Sbostic (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan); 47248570Sbostic (void)printf("%9u revolutions of the clock hand\n", sum.v_rev); 47348570Sbostic (void)printf("%9u pages freed by the clock daemon\n", 47445834Sbostic sum.v_dfree / CLSIZE); 47548570Sbostic (void)printf("%9u cpu context switches\n", sum.v_swtch); 47648570Sbostic (void)printf("%9u device interrupts\n", sum.v_intr); 47748570Sbostic (void)printf("%9u software interrupts\n", sum.v_soft); 47818761Ssam #ifdef vax 47948570Sbostic (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma); 48018761Ssam #endif 48148570Sbostic (void)printf("%9u traps\n", sum.v_trap); 48248570Sbostic (void)printf("%9u system calls\n", sum.v_syscall); 48348570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats)); 48438773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits + 48538773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits + 48638773Smckusick nchstats.ncs_miss + nchstats.ncs_long; 48748570Sbostic (void)printf("%9ld total name lookups\n", nchtotal); 48848570Sbostic (void)printf( 48945834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n", 49045834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal), 49145834Sbostic PCT(nchstats.ncs_neghits, nchtotal), 49245834Sbostic PCT(nchstats.ncs_pass2, nchtotal)); 49348570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "", 49445834Sbostic PCT(nchstats.ncs_badhits, nchtotal), 49545834Sbostic PCT(nchstats.ncs_falsehits, nchtotal), 49645834Sbostic PCT(nchstats.ncs_long, nchtotal)); 49748570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats)); 49848570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n", 49945834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc)); 50048570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "", 50125512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused); 50248570Sbostic (void)printf("%9lu total calls to xfree", xstats.free); 50348570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n", 50425512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap); 50525960Ssam #if defined(tahoe) 50648570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats)); 50748570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 50825960Ssam keystats.ks_allocs, "code cache keys allocated", 50945834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 51045834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 51145834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 51245834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 51348570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats)); 51448570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n", 51525960Ssam keystats.ks_allocs, "data cache keys allocated", 51645834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs), 51745834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs), 51845834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs), 51945834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs)); 52025960Ssam #endif 5211155Sbill } 5221155Sbill 52348570Sbostic void 5241155Sbill doforkst() 5251155Sbill { 52648570Sbostic struct forkstat fks; 5271155Sbill 52848570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat)); 52948570Sbostic (void)printf("%d forks, %d pages, average %.2f\n", 53048570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork); 53148570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n", 53248570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork); 5331155Sbill } 5341155Sbill 53548570Sbostic void 53648613Sbostic dkstats() 5371155Sbill { 53848613Sbostic register int dn, state; 53948613Sbostic double etime; 54048613Sbostic long tmp; 54148613Sbostic 54248613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 54348613Sbostic tmp = cur.xfer[dn]; 54448613Sbostic cur.xfer[dn] -= last.xfer[dn]; 54548613Sbostic last.xfer[dn] = tmp; 54648613Sbostic } 54748613Sbostic etime = 0; 54848613Sbostic for (state = 0; state < CPUSTATES; ++state) { 54948613Sbostic tmp = cur.time[state]; 55048613Sbostic cur.time[state] -= last.time[state]; 55148613Sbostic last.time[state] = tmp; 55248613Sbostic etime += cur.time[state]; 55348613Sbostic } 55448613Sbostic if (etime == 0) 55548613Sbostic etime = 1; 55648613Sbostic etime /= hz; 55748613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) { 55848613Sbostic if (!dr_select[dn]) 55948613Sbostic continue; 56048570Sbostic (void)printf("%3.0f", cur.xfer[dn] / etime); 56148613Sbostic } 5621155Sbill } 5631155Sbill 56448613Sbostic void 56548613Sbostic cpustats() 5661155Sbill { 56748613Sbostic register int state; 56848613Sbostic double pct, total; 5691155Sbill 57048613Sbostic total = 0; 57148613Sbostic for (state = 0; state < CPUSTATES; ++state) 57248613Sbostic total += cur.time[state]; 57348613Sbostic if (total) 57448613Sbostic pct = 100 / total; 57548613Sbostic else 57648613Sbostic pct = 0; 57748613Sbostic (void)printf("%3.0f", /* user + nice */ 57848613Sbostic (cur.time[0] + cur.time[1]) * pct); 57948613Sbostic (void)printf("%3.0f", cur.time[2] * pct); /* system */ 58048613Sbostic (void)printf("%3.0f", cur.time[3] * pct); /* idle */ 5811155Sbill } 5821155Sbill 58348570Sbostic void 58445834Sbostic dointr() 5851155Sbill { 58648570Sbostic register long *intrcnt, inttotal, uptime; 58745834Sbostic register int nintr, inamlen; 58845834Sbostic register char *intrname; 5891155Sbill 59048570Sbostic uptime = getuptime(); 59145834Sbostic nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value; 59245834Sbostic inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value; 59348570Sbostic intrcnt = malloc((size_t)nintr); 59445834Sbostic intrname = malloc((size_t)inamlen); 59517262Smckusick if (intrcnt == NULL || intrname == NULL) { 59648570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno)); 59748570Sbostic exit(1); 59817262Smckusick } 59948570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr); 60045834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen); 60148570Sbostic (void)printf("interrupt total rate\n"); 60217262Smckusick inttotal = 0; 60345834Sbostic nintr /= sizeof(long); 60445834Sbostic while (--nintr >= 0) { 60517262Smckusick if (*intrcnt) 60648570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname, 60745834Sbostic *intrcnt, *intrcnt / uptime); 60817262Smckusick intrname += strlen(intrname) + 1; 60917262Smckusick inttotal += *intrcnt++; 61017262Smckusick } 61148570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime); 61217262Smckusick } 61317262Smckusick 61433610Smckusick /* 61545152Smckusick * These names are defined in <sys/malloc.h>. 61633610Smckusick */ 61745152Smckusick char *kmemnames[] = INITKMEMNAMES; 61833610Smckusick 61948570Sbostic void 62033610Smckusick domem() 62133610Smckusick { 62245834Sbostic register struct kmembuckets *kp; 62345834Sbostic register struct kmemstats *ks; 62445834Sbostic register int i; 62533610Smckusick struct kmemstats kmemstats[M_LAST]; 62633610Smckusick struct kmembuckets buckets[MINBUCKET + 16]; 62733610Smckusick 62848570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets)); 62948570Sbostic (void)printf("Memory statistics by bucket size\n"); 63048570Sbostic (void)printf( 63145834Sbostic " Size In Use Free Requests HighWater Couldfree\n"); 63233610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) { 63333610Smckusick if (kp->kb_calls == 0) 63433610Smckusick continue; 63548570Sbostic (void)printf("%8d%9ld%7ld%11ld%8ld%11ld\n", 1 << i, 63633610Smckusick kp->kb_total - kp->kb_totalfree, 63733610Smckusick kp->kb_totalfree, kp->kb_calls, 63833610Smckusick kp->kb_highwat, kp->kb_couldfree); 63933610Smckusick 64033610Smckusick } 64148570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats)); 64248570Sbostic (void)printf("\nMemory statistics by type\n"); 64348570Sbostic (void)printf( 64448570Sbostic " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n"); 64533610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) { 64633610Smckusick if (ks->ks_calls == 0) 64733610Smckusick continue; 64848570Sbostic (void)printf("%10s%7ld%8ldK%9ldK%6ldK%9ld%7u%10u\n", 64948570Sbostic kmemnames[i] ? kmemnames[i] : "undefined", 65048570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024, 65148570Sbostic (ks->ks_maxused + 1023) / 1024, 65248570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls, 65348570Sbostic ks->ks_limblocks, ks->ks_mapblocks); 65433610Smckusick } 65533610Smckusick } 65633610Smckusick 65748570Sbostic void 65848570Sbostic zero() 6593162Stoy { 660*49924Sbostic static struct nlist znl[] = { 66148570Sbostic #undef X_SUM 66248570Sbostic #define X_SUM 0 66348570Sbostic { "_sum" }, 66448570Sbostic { "" }, 66548570Sbostic }; 66648570Sbostic int fd; 66748570Sbostic char *kmem; 6683162Stoy 66948570Sbostic if (geteuid()) { 67048570Sbostic (void)fprintf(stderr, "vmstat: %s\n", strerror(EPERM)); 6713162Stoy exit(1); 6723162Stoy } 67348570Sbostic /* 67448570Sbostic * Zeroing the statistics is fundamentally different 67548570Sbostic * (and really belongs in a separate program). 67648570Sbostic */ 67748570Sbostic if (nlist(vmunix, znl) || nl[0].n_type == 0) { 67848570Sbostic (void)fprintf(stderr, "vmstat: %s: symbol %s not found\n", 67948570Sbostic vmunix, nl[0].n_name); 68048570Sbostic exit(1); 6813162Stoy } 68248570Sbostic 68348570Sbostic kmem = _PATH_KMEM; 68448570Sbostic if ((fd = open(kmem, O_RDWR)) < 0) { 68548570Sbostic (void)fprintf(stderr, 68648570Sbostic "vmstat: %s: %s\n", kmem, strerror(errno)); 68748570Sbostic exit(1); 6883162Stoy } 68948570Sbostic if (lseek(fd, (long)nl[0].n_value, L_SET) == -1 || 69048570Sbostic write(fd, &sum, sizeof(sum)) != sizeof(sum)) { 69148570Sbostic (void)fprintf(stderr, 69248570Sbostic "vmstat: %s: %s\n", kmem, strerror(errno)); 69348570Sbostic exit(1); 69448570Sbostic } 6953162Stoy } 69625708Ssam 69725708Ssam /* 69848570Sbostic * kread reads something from the kernel, given its nlist index. 69925708Ssam */ 70048570Sbostic void 70148570Sbostic kread(nlx, addr, size) 70248570Sbostic int nlx; 70348570Sbostic void *addr; 70448570Sbostic size_t size; 70525708Ssam { 70648570Sbostic char *sym; 70725708Ssam 70848570Sbostic if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) { 70948570Sbostic sym = nl[nlx].n_name; 71048570Sbostic if (*sym == '_') 71148570Sbostic ++sym; 71248570Sbostic (void)fprintf(stderr, 71348570Sbostic "vmstat: %s: symbol %s not defined\n", vmunix, sym); 71425708Ssam exit(1); 71525708Ssam } 71648570Sbostic if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) { 71748570Sbostic sym = nl[nlx].n_name; 71848570Sbostic if (*sym == '_') 71948570Sbostic ++sym; 72048570Sbostic (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr()); 72148570Sbostic exit(1); 72225708Ssam } 72325708Ssam } 72442952Sbostic 72548570Sbostic void 72648570Sbostic usage() 72742952Sbostic { 72848570Sbostic (void)fprintf(stderr, 72948570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \ 73048570Sbostic [-N system] [-w wait] [disks]\n vmstat -z\n"); 73148570Sbostic exit(1); 73242952Sbostic } 733