10Sstevel@tonic-gate /* 2*5461Stc35445 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate /* 70Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 80Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 90Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 100Sstevel@tonic-gate */ 110Sstevel@tonic-gate 120Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 130Sstevel@tonic-gate 140Sstevel@tonic-gate /* from UCB 5.4 5/17/86 */ 150Sstevel@tonic-gate /* from SunOS 4.1, SID 1.31 */ 160Sstevel@tonic-gate 170Sstevel@tonic-gate #include <stdio.h> 180Sstevel@tonic-gate #include <stdlib.h> 190Sstevel@tonic-gate #include <stdarg.h> 200Sstevel@tonic-gate #include <ctype.h> 210Sstevel@tonic-gate #include <unistd.h> 220Sstevel@tonic-gate #include <memory.h> 230Sstevel@tonic-gate #include <string.h> 240Sstevel@tonic-gate #include <fcntl.h> 250Sstevel@tonic-gate #include <errno.h> 260Sstevel@tonic-gate #include <signal.h> 270Sstevel@tonic-gate #include <values.h> 280Sstevel@tonic-gate #include <poll.h> 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include "statcommon.h" 310Sstevel@tonic-gate 32*5461Stc35445 char *cmdname = "vmstat"; 33*5461Stc35445 int caught_cont = 0; 340Sstevel@tonic-gate 350Sstevel@tonic-gate static int hz; 360Sstevel@tonic-gate static int pagesize; 370Sstevel@tonic-gate static double etime; 380Sstevel@tonic-gate static int lines = 1; 390Sstevel@tonic-gate static int swflag = 0, cflag = 0, pflag = 0; 400Sstevel@tonic-gate static int suppress_state; 410Sstevel@tonic-gate static long iter = 0; 42*5461Stc35445 static hrtime_t period_n = 0; 430Sstevel@tonic-gate static struct snapshot *ss; 440Sstevel@tonic-gate 450Sstevel@tonic-gate struct iodev_filter df; 460Sstevel@tonic-gate 470Sstevel@tonic-gate #define pgtok(a) ((a) * (pagesize >> 10)) 480Sstevel@tonic-gate #define denom(x) ((x) ? (x) : 1) 490Sstevel@tonic-gate #define REPRINT 19 500Sstevel@tonic-gate 510Sstevel@tonic-gate static void dovmstats(struct snapshot *old, struct snapshot *new); 520Sstevel@tonic-gate static void printhdr(int); 530Sstevel@tonic-gate static void dosum(struct sys_snapshot *ss); 540Sstevel@tonic-gate static void dointr(struct snapshot *ss); 55*5461Stc35445 static void docachestats(kstat_ctl_t *kc, hrtime_t interval, int forever); 560Sstevel@tonic-gate static void usage(void); 570Sstevel@tonic-gate 580Sstevel@tonic-gate int 590Sstevel@tonic-gate main(int argc, char **argv) 600Sstevel@tonic-gate { 610Sstevel@tonic-gate struct snapshot *old = NULL; 620Sstevel@tonic-gate enum snapshot_types types = SNAP_SYSTEM; 630Sstevel@tonic-gate int summary = 0; 640Sstevel@tonic-gate int intr = 0; 650Sstevel@tonic-gate kstat_ctl_t *kc; 66*5461Stc35445 int forever = 0; 67*5461Stc35445 hrtime_t start_n; 680Sstevel@tonic-gate 690Sstevel@tonic-gate pagesize = sysconf(_SC_PAGESIZE); 700Sstevel@tonic-gate hz = sysconf(_SC_CLK_TCK); 710Sstevel@tonic-gate 720Sstevel@tonic-gate argc--, argv++; 730Sstevel@tonic-gate while (argc > 0 && argv[0][0] == '-') { 740Sstevel@tonic-gate char *cp = *argv++; 750Sstevel@tonic-gate argc--; 760Sstevel@tonic-gate while (*++cp) { 770Sstevel@tonic-gate switch (*cp) { 780Sstevel@tonic-gate 790Sstevel@tonic-gate case 'S': 800Sstevel@tonic-gate swflag = !swflag; 810Sstevel@tonic-gate break; 820Sstevel@tonic-gate case 's': 830Sstevel@tonic-gate summary = 1; 840Sstevel@tonic-gate break; 850Sstevel@tonic-gate case 'i': 860Sstevel@tonic-gate intr = 1; 870Sstevel@tonic-gate break; 880Sstevel@tonic-gate case 'c': 890Sstevel@tonic-gate cflag++; 900Sstevel@tonic-gate break; 910Sstevel@tonic-gate case 'q': 920Sstevel@tonic-gate suppress_state = 1; 930Sstevel@tonic-gate break; 940Sstevel@tonic-gate case 'p': 950Sstevel@tonic-gate pflag++; /* detailed paging info */ 960Sstevel@tonic-gate break; 970Sstevel@tonic-gate default: 980Sstevel@tonic-gate usage(); 990Sstevel@tonic-gate } 1000Sstevel@tonic-gate } 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate /* consistency with iostat */ 1040Sstevel@tonic-gate types |= SNAP_CPUS; 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate if (intr) 1070Sstevel@tonic-gate types |= SNAP_INTERRUPTS; 1080Sstevel@tonic-gate if (cflag) 1090Sstevel@tonic-gate types |= SNAP_FLUSHES; 1100Sstevel@tonic-gate if (!intr) 1110Sstevel@tonic-gate types |= SNAP_IODEVS; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate /* max to fit in less than 80 characters */ 1140Sstevel@tonic-gate df.if_max_iodevs = 4; 1150Sstevel@tonic-gate df.if_allowed_types = IODEV_DISK; 1160Sstevel@tonic-gate df.if_nr_names = 0; 1170Sstevel@tonic-gate df.if_names = safe_alloc(df.if_max_iodevs * sizeof (char *)); 1180Sstevel@tonic-gate (void) memset(df.if_names, 0, df.if_max_iodevs * sizeof (char *)); 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate while (argc > 0 && !isdigit(argv[0][0]) && 1210Sstevel@tonic-gate df.if_nr_names < df.if_max_iodevs) { 1220Sstevel@tonic-gate df.if_names[df.if_nr_names] = *argv; 1230Sstevel@tonic-gate df.if_nr_names++; 1240Sstevel@tonic-gate argc--, argv++; 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate kc = open_kstat(); 1280Sstevel@tonic-gate 129*5461Stc35445 start_n = gethrtime(); 130*5461Stc35445 1310Sstevel@tonic-gate ss = acquire_snapshot(kc, types, &df); 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* time, in seconds, since boot */ 1340Sstevel@tonic-gate etime = ss->s_sys.ss_ticks / hz; 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate if (intr) { 1370Sstevel@tonic-gate dointr(ss); 1380Sstevel@tonic-gate free_snapshot(ss); 1390Sstevel@tonic-gate exit(0); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate if (summary) { 1420Sstevel@tonic-gate dosum(&ss->s_sys); 1430Sstevel@tonic-gate free_snapshot(ss); 1440Sstevel@tonic-gate exit(0); 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate if (argc > 0) { 1480Sstevel@tonic-gate long interval; 1490Sstevel@tonic-gate char *endptr; 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate errno = 0; 1520Sstevel@tonic-gate interval = strtol(argv[0], &endptr, 10); 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate if (errno > 0 || *endptr != '\0' || interval <= 0 || 1550Sstevel@tonic-gate interval > MAXINT) 1560Sstevel@tonic-gate usage(); 157*5461Stc35445 period_n = (hrtime_t)interval * NANOSEC; 158*5461Stc35445 if (period_n <= 0) 1590Sstevel@tonic-gate usage(); 1600Sstevel@tonic-gate iter = MAXLONG; 1610Sstevel@tonic-gate if (argc > 1) { 1620Sstevel@tonic-gate iter = strtol(argv[1], NULL, 10); 1630Sstevel@tonic-gate if (errno > 0 || *endptr != '\0' || iter <= 0) 1640Sstevel@tonic-gate usage(); 165*5461Stc35445 } else 166*5461Stc35445 forever = 1; 1670Sstevel@tonic-gate if (argc > 2) 1680Sstevel@tonic-gate usage(); 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate if (cflag) { 1720Sstevel@tonic-gate free_snapshot(ss); 173*5461Stc35445 docachestats(kc, period_n, forever); 1740Sstevel@tonic-gate exit(0); 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate 1770Sstevel@tonic-gate (void) sigset(SIGCONT, printhdr); 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate printhdr(0); 1800Sstevel@tonic-gate dovmstats(old, ss); 181*5461Stc35445 while (forever || --iter > 0) { 182*5461Stc35445 /* (void) poll(NULL, 0, poll_interval); */ 183*5461Stc35445 184*5461Stc35445 /* Have a kip */ 185*5461Stc35445 sleep_until(&start_n, period_n, forever, &caught_cont); 186*5461Stc35445 1870Sstevel@tonic-gate free_snapshot(old); 1880Sstevel@tonic-gate old = ss; 1890Sstevel@tonic-gate ss = acquire_snapshot(kc, types, &df); 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate if (!suppress_state) 1920Sstevel@tonic-gate snapshot_report_changes(old, ss); 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate /* if config changed, show stats from boot */ 1950Sstevel@tonic-gate if (snapshot_has_changed(old, ss)) { 1960Sstevel@tonic-gate free_snapshot(old); 1970Sstevel@tonic-gate old = NULL; 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate dovmstats(old, ss); 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate free_snapshot(old); 2040Sstevel@tonic-gate free_snapshot(ss); 2050Sstevel@tonic-gate free(df.if_names); 2060Sstevel@tonic-gate (void) kstat_close(kc); 2070Sstevel@tonic-gate return (0); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate #define DELTA(v) (new->v - (old ? old->v : 0)) 2110Sstevel@tonic-gate #define ADJ(n) ((adj <= 0) ? n : (adj >= n) ? 1 : n - adj) 2120Sstevel@tonic-gate #define adjprintf(fmt, n, val) adj -= (n + 1) - printf(fmt, ADJ(n), val) 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate static int adj; /* number of excess columns */ 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate /*ARGSUSED*/ 2170Sstevel@tonic-gate static void 2180Sstevel@tonic-gate show_disk(void *v1, void *v2, void *d) 2190Sstevel@tonic-gate { 2200Sstevel@tonic-gate struct iodev_snapshot *old = (struct iodev_snapshot *)v1; 2210Sstevel@tonic-gate struct iodev_snapshot *new = (struct iodev_snapshot *)v2; 2220Sstevel@tonic-gate hrtime_t oldtime = new->is_crtime; 2230Sstevel@tonic-gate double hr_etime; 2240Sstevel@tonic-gate double reads, writes; 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate if (new == NULL) 2270Sstevel@tonic-gate return; 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate if (old) 2300Sstevel@tonic-gate oldtime = old->is_stats.wlastupdate; 2310Sstevel@tonic-gate hr_etime = new->is_stats.wlastupdate - oldtime; 2320Sstevel@tonic-gate if (hr_etime == 0.0) 2330Sstevel@tonic-gate hr_etime = NANOSEC; 2340Sstevel@tonic-gate reads = new->is_stats.reads - (old ? old->is_stats.reads : 0); 2350Sstevel@tonic-gate writes = new->is_stats.writes - (old ? old->is_stats.writes : 0); 2360Sstevel@tonic-gate adjprintf(" %*.0f", 2, (reads + writes) / hr_etime * NANOSEC); 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate static void 2400Sstevel@tonic-gate dovmstats(struct snapshot *old, struct snapshot *new) 2410Sstevel@tonic-gate { 2420Sstevel@tonic-gate kstat_t *oldsys = NULL; 2430Sstevel@tonic-gate kstat_t *newsys = &new->s_sys.ss_agg_sys; 2440Sstevel@tonic-gate kstat_t *oldvm = NULL; 2450Sstevel@tonic-gate kstat_t *newvm = &new->s_sys.ss_agg_vm; 2460Sstevel@tonic-gate double percent_factor; 2470Sstevel@tonic-gate ulong_t updates; 2480Sstevel@tonic-gate int count; 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate adj = 0; 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (old) { 2530Sstevel@tonic-gate oldsys = &old->s_sys.ss_agg_sys; 2540Sstevel@tonic-gate oldvm = &old->s_sys.ss_agg_vm; 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate etime = cpu_ticks_delta(oldsys, newsys); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate percent_factor = 100.0 / denom(etime); 2600Sstevel@tonic-gate /* 2610Sstevel@tonic-gate * If any time has passed, convert etime to seconds per CPU 2620Sstevel@tonic-gate */ 2630Sstevel@tonic-gate etime = etime >= 1.0 ? (etime / nr_active_cpus(new)) / hz : 1.0; 2640Sstevel@tonic-gate updates = denom(DELTA(s_sys.ss_sysinfo.updates)); 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate if (--lines == 0) 2670Sstevel@tonic-gate printhdr(0); 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate adj = 0; 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate if (pflag) { 2720Sstevel@tonic-gate adjprintf(" %*u", 6, 2730Sstevel@tonic-gate pgtok((int)(DELTA(s_sys.ss_vminfo.swap_avail) / updates))); 2740Sstevel@tonic-gate adjprintf(" %*u", 5, 2750Sstevel@tonic-gate pgtok((int)(DELTA(s_sys.ss_vminfo.freemem) / updates))); 2760Sstevel@tonic-gate adjprintf(" %*.0f", 3, kstat_delta(oldvm, newvm, "pgrec") 2770Sstevel@tonic-gate / etime); 2780Sstevel@tonic-gate adjprintf(" %*.0f", 3, (kstat_delta(oldvm, newvm, "hat_fault") + 2790Sstevel@tonic-gate kstat_delta(oldvm, newvm, "as_fault")) / etime); 2800Sstevel@tonic-gate adjprintf(" %*.0f", 3, pgtok(kstat_delta(oldvm, newvm, "dfree")) 2810Sstevel@tonic-gate / etime); 2820Sstevel@tonic-gate adjprintf(" %*ld", 3, pgtok(new->s_sys.ss_deficit)); 2830Sstevel@tonic-gate adjprintf(" %*.0f", 3, kstat_delta(oldvm, newvm, "scan") 2840Sstevel@tonic-gate / etime); 2850Sstevel@tonic-gate adjprintf(" %*.0f", 4, 2860Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "execpgin")) / etime); 2870Sstevel@tonic-gate adjprintf(" %*.0f", 4, 2880Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "execpgout")) / etime); 2890Sstevel@tonic-gate adjprintf(" %*.0f", 4, 2900Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "execfree")) / etime); 2910Sstevel@tonic-gate adjprintf(" %*.0f", 4, 2920Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "anonpgin")) / etime); 2930Sstevel@tonic-gate adjprintf(" %*.0f", 4, 2940Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "anonpgout")) / etime); 2950Sstevel@tonic-gate adjprintf(" %*.0f", 4, 2960Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "anonfree")) / etime); 2970Sstevel@tonic-gate adjprintf(" %*.0f", 4, 2980Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "fspgin")) / etime); 2990Sstevel@tonic-gate adjprintf(" %*.0f", 4, 3000Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "fspgout")) / etime); 3010Sstevel@tonic-gate adjprintf(" %*.0f\n", 4, 3020Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "fsfree")) / etime); 3030Sstevel@tonic-gate (void) fflush(stdout); 3040Sstevel@tonic-gate return; 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.runque) / updates); 3080Sstevel@tonic-gate adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.waiting) / updates); 3090Sstevel@tonic-gate adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.swpque) / updates); 3100Sstevel@tonic-gate adjprintf(" %*u", 6, pgtok((int)(DELTA(s_sys.ss_vminfo.swap_avail) 3110Sstevel@tonic-gate / updates))); 3120Sstevel@tonic-gate adjprintf(" %*u", 5, pgtok((int)(DELTA(s_sys.ss_vminfo.freemem) 3130Sstevel@tonic-gate / updates))); 3140Sstevel@tonic-gate adjprintf(" %*.0f", 3, swflag? 3150Sstevel@tonic-gate kstat_delta(oldvm, newvm, "swapin") / etime : 3160Sstevel@tonic-gate kstat_delta(oldvm, newvm, "pgrec") / etime); 3170Sstevel@tonic-gate adjprintf(" %*.0f", 3, swflag? 3180Sstevel@tonic-gate kstat_delta(oldvm, newvm, "swapout") / etime : 3190Sstevel@tonic-gate (kstat_delta(oldvm, newvm, "hat_fault") 3200Sstevel@tonic-gate + kstat_delta(oldvm, newvm, "as_fault")) 3210Sstevel@tonic-gate / etime); 3220Sstevel@tonic-gate adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "pgpgin")) 3230Sstevel@tonic-gate / etime); 3240Sstevel@tonic-gate adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "pgpgout")) 3250Sstevel@tonic-gate / etime); 3260Sstevel@tonic-gate adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "dfree")) 3270Sstevel@tonic-gate / etime); 3280Sstevel@tonic-gate adjprintf(" %*ld", 2, pgtok(new->s_sys.ss_deficit)); 3290Sstevel@tonic-gate adjprintf(" %*.0f", 2, kstat_delta(oldvm, newvm, "scan") / etime); 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate (void) snapshot_walk(SNAP_IODEVS, old, new, show_disk, NULL); 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate count = df.if_max_iodevs - new->s_nr_iodevs; 3340Sstevel@tonic-gate while (count-- > 0) 3350Sstevel@tonic-gate adjprintf(" %*d", 2, 0); 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "intr") / etime); 3380Sstevel@tonic-gate adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "syscall") / etime); 3390Sstevel@tonic-gate adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "pswitch") / etime); 3400Sstevel@tonic-gate adjprintf(" %*.0f", 2, 3410Sstevel@tonic-gate kstat_delta(oldsys, newsys, "cpu_ticks_user") * percent_factor); 3420Sstevel@tonic-gate adjprintf(" %*.0f", 2, kstat_delta(oldsys, newsys, "cpu_ticks_kernel") 3430Sstevel@tonic-gate * percent_factor); 3440Sstevel@tonic-gate adjprintf(" %*.0f\n", 2, (kstat_delta(oldsys, newsys, "cpu_ticks_idle") 3450Sstevel@tonic-gate + kstat_delta(oldsys, newsys, "cpu_ticks_wait")) 3460Sstevel@tonic-gate * percent_factor); 3470Sstevel@tonic-gate (void) fflush(stdout); 3480Sstevel@tonic-gate } 3490Sstevel@tonic-gate 3500Sstevel@tonic-gate /*ARGSUSED*/ 3510Sstevel@tonic-gate static void 3520Sstevel@tonic-gate print_disk(void *v, void *v2, void *d) 3530Sstevel@tonic-gate { 3540Sstevel@tonic-gate struct iodev_snapshot *iodev = (struct iodev_snapshot *)v2; 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate if (iodev == NULL) 3570Sstevel@tonic-gate return; 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate (void) printf("%c%c ", iodev->is_name[0], iodev->is_name[2]); 3600Sstevel@tonic-gate } 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate /* ARGSUSED */ 3630Sstevel@tonic-gate static void 3640Sstevel@tonic-gate printhdr(int sig) 3650Sstevel@tonic-gate { 3660Sstevel@tonic-gate int i = df.if_max_iodevs - ss->s_nr_iodevs; 3670Sstevel@tonic-gate 368*5461Stc35445 if (sig == SIGCONT) 369*5461Stc35445 caught_cont = 1; 370*5461Stc35445 3710Sstevel@tonic-gate if (pflag) { 3720Sstevel@tonic-gate (void) printf(" memory page "); 3730Sstevel@tonic-gate (void) printf("executable anonymous filesystem \n"); 3740Sstevel@tonic-gate (void) printf(" swap free re mf fr de sr "); 3750Sstevel@tonic-gate (void) printf("epi epo epf api apo apf fpi fpo fpf\n"); 3760Sstevel@tonic-gate lines = REPRINT; 3770Sstevel@tonic-gate return; 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate (void) printf(" kthr memory page "); 3810Sstevel@tonic-gate (void) printf("disk faults cpu\n"); 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate if (swflag) 3840Sstevel@tonic-gate (void) printf(" r b w swap free si so pi po fr de sr "); 3850Sstevel@tonic-gate else 3860Sstevel@tonic-gate (void) printf(" r b w swap free re mf pi po fr de sr "); 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate (void) snapshot_walk(SNAP_IODEVS, NULL, ss, print_disk, NULL); 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate while (i-- > 0) 3910Sstevel@tonic-gate (void) printf("-- "); 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate (void) printf(" in sy cs us sy id\n"); 3940Sstevel@tonic-gate lines = REPRINT; 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate static void 3980Sstevel@tonic-gate sum_out(char const *pretty, kstat_t *ks, char *name) 3990Sstevel@tonic-gate { 4000Sstevel@tonic-gate kstat_named_t *ksn = kstat_data_lookup(ks, name); 4010Sstevel@tonic-gate if (ksn == NULL) { 4020Sstevel@tonic-gate fail(0, "kstat_data_lookup('%s', '%s') failed", 4030Sstevel@tonic-gate ks->ks_name, name); 4040Sstevel@tonic-gate } 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate (void) printf("%9llu %s\n", ksn->value.ui64, pretty); 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate static void 4100Sstevel@tonic-gate dosum(struct sys_snapshot *ss) 4110Sstevel@tonic-gate { 4120Sstevel@tonic-gate uint64_t total_faults; 4130Sstevel@tonic-gate kstat_named_t *ksn; 4140Sstevel@tonic-gate long double nchtotal; 4150Sstevel@tonic-gate uint64_t nchhits; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate sum_out("swap ins", &ss->ss_agg_vm, "swapin"); 4180Sstevel@tonic-gate sum_out("swap outs", &ss->ss_agg_vm, "swapout"); 4190Sstevel@tonic-gate sum_out("pages swapped in", &ss->ss_agg_vm, "pgswapin"); 4200Sstevel@tonic-gate sum_out("pages swapped out", &ss->ss_agg_vm, "pgswapout"); 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate ksn = kstat_data_lookup(&ss->ss_agg_vm, "hat_fault"); 4230Sstevel@tonic-gate if (ksn == NULL) { 4240Sstevel@tonic-gate fail(0, "kstat_data_lookup('%s', 'hat_fault') failed", 4250Sstevel@tonic-gate ss->ss_agg_vm.ks_name); 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate total_faults = ksn->value.ui64; 4280Sstevel@tonic-gate ksn = kstat_data_lookup(&ss->ss_agg_vm, "as_fault"); 4290Sstevel@tonic-gate if (ksn == NULL) { 4300Sstevel@tonic-gate fail(0, "kstat_data_lookup('%s', 'as_fault') failed", 4310Sstevel@tonic-gate ss->ss_agg_vm.ks_name); 4320Sstevel@tonic-gate } 4330Sstevel@tonic-gate total_faults += ksn->value.ui64; 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate (void) printf("%9llu total address trans. faults taken\n", 4360Sstevel@tonic-gate total_faults); 4370Sstevel@tonic-gate 4380Sstevel@tonic-gate sum_out("page ins", &ss->ss_agg_vm, "pgin"); 4390Sstevel@tonic-gate sum_out("page outs", &ss->ss_agg_vm, "pgout"); 4400Sstevel@tonic-gate sum_out("pages paged in", &ss->ss_agg_vm, "pgpgin"); 4410Sstevel@tonic-gate sum_out("pages paged out", &ss->ss_agg_vm, "pgpgout"); 4420Sstevel@tonic-gate sum_out("total reclaims", &ss->ss_agg_vm, "pgrec"); 4430Sstevel@tonic-gate sum_out("reclaims from free list", &ss->ss_agg_vm, "pgfrec"); 4440Sstevel@tonic-gate sum_out("micro (hat) faults", &ss->ss_agg_vm, "hat_fault"); 4450Sstevel@tonic-gate sum_out("minor (as) faults", &ss->ss_agg_vm, "as_fault"); 4460Sstevel@tonic-gate sum_out("major faults", &ss->ss_agg_vm, "maj_fault"); 4470Sstevel@tonic-gate sum_out("copy-on-write faults", &ss->ss_agg_vm, "cow_fault"); 4480Sstevel@tonic-gate sum_out("zero fill page faults", &ss->ss_agg_vm, "zfod"); 4490Sstevel@tonic-gate sum_out("pages examined by the clock daemon", &ss->ss_agg_vm, "scan"); 4500Sstevel@tonic-gate sum_out("revolutions of the clock hand", &ss->ss_agg_vm, "rev"); 4510Sstevel@tonic-gate sum_out("pages freed by the clock daemon", &ss->ss_agg_vm, "dfree"); 4520Sstevel@tonic-gate sum_out("forks", &ss->ss_agg_sys, "sysfork"); 4530Sstevel@tonic-gate sum_out("vforks", &ss->ss_agg_sys, "sysvfork"); 4540Sstevel@tonic-gate sum_out("execs", &ss->ss_agg_sys, "sysexec"); 4550Sstevel@tonic-gate sum_out("cpu context switches", &ss->ss_agg_sys, "pswitch"); 4560Sstevel@tonic-gate sum_out("device interrupts", &ss->ss_agg_sys, "intr"); 4570Sstevel@tonic-gate sum_out("traps", &ss->ss_agg_sys, "trap"); 4580Sstevel@tonic-gate sum_out("system calls", &ss->ss_agg_sys, "syscall"); 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate nchtotal = (long double) ss->ss_nc.ncs_hits.value.ui64 + 4610Sstevel@tonic-gate (long double) ss->ss_nc.ncs_misses.value.ui64; 4620Sstevel@tonic-gate nchhits = ss->ss_nc.ncs_hits.value.ui64; 4630Sstevel@tonic-gate (void) printf("%9.0Lf total name lookups (cache hits %.0Lf%%)\n", 4640Sstevel@tonic-gate nchtotal, nchhits / denom(nchtotal) * 100); 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate sum_out("user cpu", &ss->ss_agg_sys, "cpu_ticks_user"); 4670Sstevel@tonic-gate sum_out("system cpu", &ss->ss_agg_sys, "cpu_ticks_kernel"); 4680Sstevel@tonic-gate sum_out("idle cpu", &ss->ss_agg_sys, "cpu_ticks_idle"); 4690Sstevel@tonic-gate sum_out("wait cpu", &ss->ss_agg_sys, "cpu_ticks_wait"); 4700Sstevel@tonic-gate } 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate static void 4730Sstevel@tonic-gate dointr(struct snapshot *ss) 4740Sstevel@tonic-gate { 4750Sstevel@tonic-gate size_t i; 4760Sstevel@tonic-gate ulong_t total = 0; 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate (void) printf("interrupt total rate\n"); 4790Sstevel@tonic-gate (void) printf("--------------------------------\n"); 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate for (i = 0; i < ss->s_nr_intrs; i++) { 4820Sstevel@tonic-gate (void) printf("%-12.8s %10lu %8.0f\n", 4830Sstevel@tonic-gate ss->s_intrs[i].is_name, ss->s_intrs[i].is_total, 4840Sstevel@tonic-gate ss->s_intrs[i].is_total / etime); 4850Sstevel@tonic-gate total += ss->s_intrs[i].is_total; 4860Sstevel@tonic-gate } 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate (void) printf("--------------------------------\n"); 4890Sstevel@tonic-gate (void) printf("Total %10lu %8.0f\n", total, total / etime); 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate static void 493*5461Stc35445 docachestats(kstat_ctl_t *kc, hrtime_t interval, int forever) 4940Sstevel@tonic-gate { 4950Sstevel@tonic-gate struct snapshot *old; 4960Sstevel@tonic-gate struct snapshot *new; 4970Sstevel@tonic-gate int i; 498*5461Stc35445 hrtime_t start; 4990Sstevel@tonic-gate 500*5461Stc35445 start = gethrtime(); 5010Sstevel@tonic-gate old = acquire_snapshot(kc, SNAP_FLUSHES, NULL); 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate if (iter == 0) { 5040Sstevel@tonic-gate (void) printf("flush statistics: (totals)\n"); 5050Sstevel@tonic-gate (void) printf("%8s%8s%8s%8s%8s%8s\n", 5060Sstevel@tonic-gate "usr", "ctx", "rgn", "seg", "pag", "par"); 5070Sstevel@tonic-gate (void) printf(" %7d %7d %7d %7d %7d %7d\n", 5080Sstevel@tonic-gate old->s_flushes.f_usr, old->s_flushes.f_ctx, 5090Sstevel@tonic-gate old->s_flushes.f_region, old->s_flushes.f_segment, 5100Sstevel@tonic-gate old->s_flushes.f_page, old->s_flushes.f_partial); 5110Sstevel@tonic-gate return; 5120Sstevel@tonic-gate } 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate (void) printf("flush statistics: (interval based)\n"); 5150Sstevel@tonic-gate for (i = 0; i < iter; i++) { 5160Sstevel@tonic-gate if (i % REPRINT == 0) 5170Sstevel@tonic-gate (void) printf("%8s%8s%8s%8s%8s%8s\n", 5180Sstevel@tonic-gate "usr", "ctx", "rgn", "seg", "pag", "par"); 5190Sstevel@tonic-gate 520*5461Stc35445 /* Have a kip */ 521*5461Stc35445 sleep_until(&start, interval, forever, &caught_cont); 522*5461Stc35445 5230Sstevel@tonic-gate new = acquire_snapshot(kc, SNAP_FLUSHES, NULL); 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate (void) printf(" %7d %7d %7d %7d %7d %7d\n", 5260Sstevel@tonic-gate new->s_flushes.f_usr - old->s_flushes.f_usr, 5270Sstevel@tonic-gate new->s_flushes.f_ctx - old->s_flushes.f_ctx, 5280Sstevel@tonic-gate new->s_flushes.f_region - old->s_flushes.f_region, 5290Sstevel@tonic-gate new->s_flushes.f_segment - old->s_flushes.f_segment, 5300Sstevel@tonic-gate new->s_flushes.f_page - old->s_flushes.f_page, 5310Sstevel@tonic-gate new->s_flushes.f_partial- old->s_flushes.f_partial); 5320Sstevel@tonic-gate (void) fflush(stdout); 5330Sstevel@tonic-gate free_snapshot(old); 5340Sstevel@tonic-gate old = new; 5350Sstevel@tonic-gate } 5360Sstevel@tonic-gate } 5370Sstevel@tonic-gate 5380Sstevel@tonic-gate static void 5390Sstevel@tonic-gate usage(void) 5400Sstevel@tonic-gate { 5410Sstevel@tonic-gate (void) fprintf(stderr, 5420Sstevel@tonic-gate "Usage: vmstat [-cipqsS] [disk ...] [interval [count]]\n"); 5430Sstevel@tonic-gate exit(1); 5440Sstevel@tonic-gate } 545