1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate /* 7*0Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 8*0Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 9*0Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 10*0Sstevel@tonic-gate */ 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 13*0Sstevel@tonic-gate 14*0Sstevel@tonic-gate /* from UCB 5.4 5/17/86 */ 15*0Sstevel@tonic-gate /* from SunOS 4.1, SID 1.31 */ 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate #include <stdio.h> 18*0Sstevel@tonic-gate #include <stdlib.h> 19*0Sstevel@tonic-gate #include <stdarg.h> 20*0Sstevel@tonic-gate #include <ctype.h> 21*0Sstevel@tonic-gate #include <unistd.h> 22*0Sstevel@tonic-gate #include <memory.h> 23*0Sstevel@tonic-gate #include <string.h> 24*0Sstevel@tonic-gate #include <fcntl.h> 25*0Sstevel@tonic-gate #include <errno.h> 26*0Sstevel@tonic-gate #include <signal.h> 27*0Sstevel@tonic-gate #include <values.h> 28*0Sstevel@tonic-gate #include <poll.h> 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate #include "statcommon.h" 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate char cmdname[] = "vmstat"; 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate static int hz; 35*0Sstevel@tonic-gate static int pagesize; 36*0Sstevel@tonic-gate static double etime; 37*0Sstevel@tonic-gate static int lines = 1; 38*0Sstevel@tonic-gate static int swflag = 0, cflag = 0, pflag = 0; 39*0Sstevel@tonic-gate static int suppress_state; 40*0Sstevel@tonic-gate static long iter = 0; 41*0Sstevel@tonic-gate static int poll_interval = 0; 42*0Sstevel@tonic-gate static struct snapshot *ss; 43*0Sstevel@tonic-gate 44*0Sstevel@tonic-gate struct iodev_filter df; 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #define pgtok(a) ((a) * (pagesize >> 10)) 47*0Sstevel@tonic-gate #define denom(x) ((x) ? (x) : 1) 48*0Sstevel@tonic-gate #define REPRINT 19 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate static void dovmstats(struct snapshot *old, struct snapshot *new); 51*0Sstevel@tonic-gate static void printhdr(int); 52*0Sstevel@tonic-gate static void dosum(struct sys_snapshot *ss); 53*0Sstevel@tonic-gate static void dointr(struct snapshot *ss); 54*0Sstevel@tonic-gate static void docachestats(kstat_ctl_t *kc); 55*0Sstevel@tonic-gate static void usage(void); 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate int 58*0Sstevel@tonic-gate main(int argc, char **argv) 59*0Sstevel@tonic-gate { 60*0Sstevel@tonic-gate struct snapshot *old = NULL; 61*0Sstevel@tonic-gate enum snapshot_types types = SNAP_SYSTEM; 62*0Sstevel@tonic-gate int summary = 0; 63*0Sstevel@tonic-gate int intr = 0; 64*0Sstevel@tonic-gate kstat_ctl_t *kc; 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate pagesize = sysconf(_SC_PAGESIZE); 67*0Sstevel@tonic-gate hz = sysconf(_SC_CLK_TCK); 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate argc--, argv++; 70*0Sstevel@tonic-gate while (argc > 0 && argv[0][0] == '-') { 71*0Sstevel@tonic-gate char *cp = *argv++; 72*0Sstevel@tonic-gate argc--; 73*0Sstevel@tonic-gate while (*++cp) { 74*0Sstevel@tonic-gate switch (*cp) { 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate case 'S': 77*0Sstevel@tonic-gate swflag = !swflag; 78*0Sstevel@tonic-gate break; 79*0Sstevel@tonic-gate case 's': 80*0Sstevel@tonic-gate summary = 1; 81*0Sstevel@tonic-gate break; 82*0Sstevel@tonic-gate case 'i': 83*0Sstevel@tonic-gate intr = 1; 84*0Sstevel@tonic-gate break; 85*0Sstevel@tonic-gate case 'c': 86*0Sstevel@tonic-gate cflag++; 87*0Sstevel@tonic-gate break; 88*0Sstevel@tonic-gate case 'q': 89*0Sstevel@tonic-gate suppress_state = 1; 90*0Sstevel@tonic-gate break; 91*0Sstevel@tonic-gate case 'p': 92*0Sstevel@tonic-gate pflag++; /* detailed paging info */ 93*0Sstevel@tonic-gate break; 94*0Sstevel@tonic-gate default: 95*0Sstevel@tonic-gate usage(); 96*0Sstevel@tonic-gate } 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate /* consistency with iostat */ 101*0Sstevel@tonic-gate types |= SNAP_CPUS; 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate if (intr) 104*0Sstevel@tonic-gate types |= SNAP_INTERRUPTS; 105*0Sstevel@tonic-gate if (cflag) 106*0Sstevel@tonic-gate types |= SNAP_FLUSHES; 107*0Sstevel@tonic-gate if (!intr) 108*0Sstevel@tonic-gate types |= SNAP_IODEVS; 109*0Sstevel@tonic-gate 110*0Sstevel@tonic-gate /* max to fit in less than 80 characters */ 111*0Sstevel@tonic-gate df.if_max_iodevs = 4; 112*0Sstevel@tonic-gate df.if_allowed_types = IODEV_DISK; 113*0Sstevel@tonic-gate df.if_nr_names = 0; 114*0Sstevel@tonic-gate df.if_names = safe_alloc(df.if_max_iodevs * sizeof (char *)); 115*0Sstevel@tonic-gate (void) memset(df.if_names, 0, df.if_max_iodevs * sizeof (char *)); 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate while (argc > 0 && !isdigit(argv[0][0]) && 118*0Sstevel@tonic-gate df.if_nr_names < df.if_max_iodevs) { 119*0Sstevel@tonic-gate df.if_names[df.if_nr_names] = *argv; 120*0Sstevel@tonic-gate df.if_nr_names++; 121*0Sstevel@tonic-gate argc--, argv++; 122*0Sstevel@tonic-gate } 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate kc = open_kstat(); 125*0Sstevel@tonic-gate 126*0Sstevel@tonic-gate ss = acquire_snapshot(kc, types, &df); 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate /* time, in seconds, since boot */ 129*0Sstevel@tonic-gate etime = ss->s_sys.ss_ticks / hz; 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate if (intr) { 132*0Sstevel@tonic-gate dointr(ss); 133*0Sstevel@tonic-gate free_snapshot(ss); 134*0Sstevel@tonic-gate exit(0); 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate if (summary) { 137*0Sstevel@tonic-gate dosum(&ss->s_sys); 138*0Sstevel@tonic-gate free_snapshot(ss); 139*0Sstevel@tonic-gate exit(0); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate if (argc > 0) { 143*0Sstevel@tonic-gate long interval; 144*0Sstevel@tonic-gate char *endptr; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate errno = 0; 147*0Sstevel@tonic-gate interval = strtol(argv[0], &endptr, 10); 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate if (errno > 0 || *endptr != '\0' || interval <= 0 || 150*0Sstevel@tonic-gate interval > MAXINT) 151*0Sstevel@tonic-gate usage(); 152*0Sstevel@tonic-gate poll_interval = 1000 * interval; 153*0Sstevel@tonic-gate if (poll_interval <= 0) 154*0Sstevel@tonic-gate usage(); 155*0Sstevel@tonic-gate iter = MAXLONG; 156*0Sstevel@tonic-gate if (argc > 1) { 157*0Sstevel@tonic-gate iter = strtol(argv[1], NULL, 10); 158*0Sstevel@tonic-gate if (errno > 0 || *endptr != '\0' || iter <= 0) 159*0Sstevel@tonic-gate usage(); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate if (argc > 2) 162*0Sstevel@tonic-gate usage(); 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate if (cflag) { 166*0Sstevel@tonic-gate free_snapshot(ss); 167*0Sstevel@tonic-gate docachestats(kc); 168*0Sstevel@tonic-gate exit(0); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate (void) sigset(SIGCONT, printhdr); 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate printhdr(0); 174*0Sstevel@tonic-gate dovmstats(old, ss); 175*0Sstevel@tonic-gate while (--iter > 0) { 176*0Sstevel@tonic-gate (void) poll(NULL, 0, poll_interval); 177*0Sstevel@tonic-gate free_snapshot(old); 178*0Sstevel@tonic-gate old = ss; 179*0Sstevel@tonic-gate ss = acquire_snapshot(kc, types, &df); 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate if (!suppress_state) 182*0Sstevel@tonic-gate snapshot_report_changes(old, ss); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* if config changed, show stats from boot */ 185*0Sstevel@tonic-gate if (snapshot_has_changed(old, ss)) { 186*0Sstevel@tonic-gate free_snapshot(old); 187*0Sstevel@tonic-gate old = NULL; 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate dovmstats(old, ss); 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate free_snapshot(old); 194*0Sstevel@tonic-gate free_snapshot(ss); 195*0Sstevel@tonic-gate free(df.if_names); 196*0Sstevel@tonic-gate (void) kstat_close(kc); 197*0Sstevel@tonic-gate return (0); 198*0Sstevel@tonic-gate } 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate #define DELTA(v) (new->v - (old ? old->v : 0)) 201*0Sstevel@tonic-gate #define ADJ(n) ((adj <= 0) ? n : (adj >= n) ? 1 : n - adj) 202*0Sstevel@tonic-gate #define adjprintf(fmt, n, val) adj -= (n + 1) - printf(fmt, ADJ(n), val) 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate static int adj; /* number of excess columns */ 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate /*ARGSUSED*/ 207*0Sstevel@tonic-gate static void 208*0Sstevel@tonic-gate show_disk(void *v1, void *v2, void *d) 209*0Sstevel@tonic-gate { 210*0Sstevel@tonic-gate struct iodev_snapshot *old = (struct iodev_snapshot *)v1; 211*0Sstevel@tonic-gate struct iodev_snapshot *new = (struct iodev_snapshot *)v2; 212*0Sstevel@tonic-gate hrtime_t oldtime = new->is_crtime; 213*0Sstevel@tonic-gate double hr_etime; 214*0Sstevel@tonic-gate double reads, writes; 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if (new == NULL) 217*0Sstevel@tonic-gate return; 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate if (old) 220*0Sstevel@tonic-gate oldtime = old->is_stats.wlastupdate; 221*0Sstevel@tonic-gate hr_etime = new->is_stats.wlastupdate - oldtime; 222*0Sstevel@tonic-gate if (hr_etime == 0.0) 223*0Sstevel@tonic-gate hr_etime = NANOSEC; 224*0Sstevel@tonic-gate reads = new->is_stats.reads - (old ? old->is_stats.reads : 0); 225*0Sstevel@tonic-gate writes = new->is_stats.writes - (old ? old->is_stats.writes : 0); 226*0Sstevel@tonic-gate adjprintf(" %*.0f", 2, (reads + writes) / hr_etime * NANOSEC); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate static void 230*0Sstevel@tonic-gate dovmstats(struct snapshot *old, struct snapshot *new) 231*0Sstevel@tonic-gate { 232*0Sstevel@tonic-gate kstat_t *oldsys = NULL; 233*0Sstevel@tonic-gate kstat_t *newsys = &new->s_sys.ss_agg_sys; 234*0Sstevel@tonic-gate kstat_t *oldvm = NULL; 235*0Sstevel@tonic-gate kstat_t *newvm = &new->s_sys.ss_agg_vm; 236*0Sstevel@tonic-gate double percent_factor; 237*0Sstevel@tonic-gate ulong_t updates; 238*0Sstevel@tonic-gate int count; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate adj = 0; 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate if (old) { 243*0Sstevel@tonic-gate oldsys = &old->s_sys.ss_agg_sys; 244*0Sstevel@tonic-gate oldvm = &old->s_sys.ss_agg_vm; 245*0Sstevel@tonic-gate } 246*0Sstevel@tonic-gate 247*0Sstevel@tonic-gate etime = cpu_ticks_delta(oldsys, newsys); 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate percent_factor = 100.0 / denom(etime); 250*0Sstevel@tonic-gate /* 251*0Sstevel@tonic-gate * If any time has passed, convert etime to seconds per CPU 252*0Sstevel@tonic-gate */ 253*0Sstevel@tonic-gate etime = etime >= 1.0 ? (etime / nr_active_cpus(new)) / hz : 1.0; 254*0Sstevel@tonic-gate updates = denom(DELTA(s_sys.ss_sysinfo.updates)); 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate if (--lines == 0) 257*0Sstevel@tonic-gate printhdr(0); 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate adj = 0; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate if (pflag) { 262*0Sstevel@tonic-gate adjprintf(" %*u", 6, 263*0Sstevel@tonic-gate pgtok((int)(DELTA(s_sys.ss_vminfo.swap_avail) / updates))); 264*0Sstevel@tonic-gate adjprintf(" %*u", 5, 265*0Sstevel@tonic-gate pgtok((int)(DELTA(s_sys.ss_vminfo.freemem) / updates))); 266*0Sstevel@tonic-gate adjprintf(" %*.0f", 3, kstat_delta(oldvm, newvm, "pgrec") 267*0Sstevel@tonic-gate / etime); 268*0Sstevel@tonic-gate adjprintf(" %*.0f", 3, (kstat_delta(oldvm, newvm, "hat_fault") + 269*0Sstevel@tonic-gate kstat_delta(oldvm, newvm, "as_fault")) / etime); 270*0Sstevel@tonic-gate adjprintf(" %*.0f", 3, pgtok(kstat_delta(oldvm, newvm, "dfree")) 271*0Sstevel@tonic-gate / etime); 272*0Sstevel@tonic-gate adjprintf(" %*ld", 3, pgtok(new->s_sys.ss_deficit)); 273*0Sstevel@tonic-gate adjprintf(" %*.0f", 3, kstat_delta(oldvm, newvm, "scan") 274*0Sstevel@tonic-gate / etime); 275*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, 276*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "execpgin")) / etime); 277*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, 278*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "execpgout")) / etime); 279*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, 280*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "execfree")) / etime); 281*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, 282*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "anonpgin")) / etime); 283*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, 284*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "anonpgout")) / etime); 285*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, 286*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "anonfree")) / etime); 287*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, 288*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "fspgin")) / etime); 289*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, 290*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "fspgout")) / etime); 291*0Sstevel@tonic-gate adjprintf(" %*.0f\n", 4, 292*0Sstevel@tonic-gate pgtok(kstat_delta(oldvm, newvm, "fsfree")) / etime); 293*0Sstevel@tonic-gate (void) fflush(stdout); 294*0Sstevel@tonic-gate return; 295*0Sstevel@tonic-gate } 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.runque) / updates); 298*0Sstevel@tonic-gate adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.waiting) / updates); 299*0Sstevel@tonic-gate adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.swpque) / updates); 300*0Sstevel@tonic-gate adjprintf(" %*u", 6, pgtok((int)(DELTA(s_sys.ss_vminfo.swap_avail) 301*0Sstevel@tonic-gate / updates))); 302*0Sstevel@tonic-gate adjprintf(" %*u", 5, pgtok((int)(DELTA(s_sys.ss_vminfo.freemem) 303*0Sstevel@tonic-gate / updates))); 304*0Sstevel@tonic-gate adjprintf(" %*.0f", 3, swflag? 305*0Sstevel@tonic-gate kstat_delta(oldvm, newvm, "swapin") / etime : 306*0Sstevel@tonic-gate kstat_delta(oldvm, newvm, "pgrec") / etime); 307*0Sstevel@tonic-gate adjprintf(" %*.0f", 3, swflag? 308*0Sstevel@tonic-gate kstat_delta(oldvm, newvm, "swapout") / etime : 309*0Sstevel@tonic-gate (kstat_delta(oldvm, newvm, "hat_fault") 310*0Sstevel@tonic-gate + kstat_delta(oldvm, newvm, "as_fault")) 311*0Sstevel@tonic-gate / etime); 312*0Sstevel@tonic-gate adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "pgpgin")) 313*0Sstevel@tonic-gate / etime); 314*0Sstevel@tonic-gate adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "pgpgout")) 315*0Sstevel@tonic-gate / etime); 316*0Sstevel@tonic-gate adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "dfree")) 317*0Sstevel@tonic-gate / etime); 318*0Sstevel@tonic-gate adjprintf(" %*ld", 2, pgtok(new->s_sys.ss_deficit)); 319*0Sstevel@tonic-gate adjprintf(" %*.0f", 2, kstat_delta(oldvm, newvm, "scan") / etime); 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate (void) snapshot_walk(SNAP_IODEVS, old, new, show_disk, NULL); 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate count = df.if_max_iodevs - new->s_nr_iodevs; 324*0Sstevel@tonic-gate while (count-- > 0) 325*0Sstevel@tonic-gate adjprintf(" %*d", 2, 0); 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "intr") / etime); 328*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "syscall") / etime); 329*0Sstevel@tonic-gate adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "pswitch") / etime); 330*0Sstevel@tonic-gate adjprintf(" %*.0f", 2, 331*0Sstevel@tonic-gate kstat_delta(oldsys, newsys, "cpu_ticks_user") * percent_factor); 332*0Sstevel@tonic-gate adjprintf(" %*.0f", 2, kstat_delta(oldsys, newsys, "cpu_ticks_kernel") 333*0Sstevel@tonic-gate * percent_factor); 334*0Sstevel@tonic-gate adjprintf(" %*.0f\n", 2, (kstat_delta(oldsys, newsys, "cpu_ticks_idle") 335*0Sstevel@tonic-gate + kstat_delta(oldsys, newsys, "cpu_ticks_wait")) 336*0Sstevel@tonic-gate * percent_factor); 337*0Sstevel@tonic-gate (void) fflush(stdout); 338*0Sstevel@tonic-gate } 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate /*ARGSUSED*/ 341*0Sstevel@tonic-gate static void 342*0Sstevel@tonic-gate print_disk(void *v, void *v2, void *d) 343*0Sstevel@tonic-gate { 344*0Sstevel@tonic-gate struct iodev_snapshot *iodev = (struct iodev_snapshot *)v2; 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate if (iodev == NULL) 347*0Sstevel@tonic-gate return; 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate (void) printf("%c%c ", iodev->is_name[0], iodev->is_name[2]); 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate /* ARGSUSED */ 353*0Sstevel@tonic-gate static void 354*0Sstevel@tonic-gate printhdr(int sig) 355*0Sstevel@tonic-gate { 356*0Sstevel@tonic-gate int i = df.if_max_iodevs - ss->s_nr_iodevs; 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate if (pflag) { 359*0Sstevel@tonic-gate (void) printf(" memory page "); 360*0Sstevel@tonic-gate (void) printf("executable anonymous filesystem \n"); 361*0Sstevel@tonic-gate (void) printf(" swap free re mf fr de sr "); 362*0Sstevel@tonic-gate (void) printf("epi epo epf api apo apf fpi fpo fpf\n"); 363*0Sstevel@tonic-gate lines = REPRINT; 364*0Sstevel@tonic-gate return; 365*0Sstevel@tonic-gate } 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate (void) printf(" kthr memory page "); 368*0Sstevel@tonic-gate (void) printf("disk faults cpu\n"); 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate if (swflag) 371*0Sstevel@tonic-gate (void) printf(" r b w swap free si so pi po fr de sr "); 372*0Sstevel@tonic-gate else 373*0Sstevel@tonic-gate (void) printf(" r b w swap free re mf pi po fr de sr "); 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate (void) snapshot_walk(SNAP_IODEVS, NULL, ss, print_disk, NULL); 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate while (i-- > 0) 378*0Sstevel@tonic-gate (void) printf("-- "); 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate (void) printf(" in sy cs us sy id\n"); 381*0Sstevel@tonic-gate lines = REPRINT; 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate static void 385*0Sstevel@tonic-gate sum_out(char const *pretty, kstat_t *ks, char *name) 386*0Sstevel@tonic-gate { 387*0Sstevel@tonic-gate kstat_named_t *ksn = kstat_data_lookup(ks, name); 388*0Sstevel@tonic-gate if (ksn == NULL) { 389*0Sstevel@tonic-gate fail(0, "kstat_data_lookup('%s', '%s') failed", 390*0Sstevel@tonic-gate ks->ks_name, name); 391*0Sstevel@tonic-gate } 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate (void) printf("%9llu %s\n", ksn->value.ui64, pretty); 394*0Sstevel@tonic-gate } 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate static void 397*0Sstevel@tonic-gate dosum(struct sys_snapshot *ss) 398*0Sstevel@tonic-gate { 399*0Sstevel@tonic-gate uint64_t total_faults; 400*0Sstevel@tonic-gate kstat_named_t *ksn; 401*0Sstevel@tonic-gate long double nchtotal; 402*0Sstevel@tonic-gate uint64_t nchhits; 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate sum_out("swap ins", &ss->ss_agg_vm, "swapin"); 405*0Sstevel@tonic-gate sum_out("swap outs", &ss->ss_agg_vm, "swapout"); 406*0Sstevel@tonic-gate sum_out("pages swapped in", &ss->ss_agg_vm, "pgswapin"); 407*0Sstevel@tonic-gate sum_out("pages swapped out", &ss->ss_agg_vm, "pgswapout"); 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate ksn = kstat_data_lookup(&ss->ss_agg_vm, "hat_fault"); 410*0Sstevel@tonic-gate if (ksn == NULL) { 411*0Sstevel@tonic-gate fail(0, "kstat_data_lookup('%s', 'hat_fault') failed", 412*0Sstevel@tonic-gate ss->ss_agg_vm.ks_name); 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate total_faults = ksn->value.ui64; 415*0Sstevel@tonic-gate ksn = kstat_data_lookup(&ss->ss_agg_vm, "as_fault"); 416*0Sstevel@tonic-gate if (ksn == NULL) { 417*0Sstevel@tonic-gate fail(0, "kstat_data_lookup('%s', 'as_fault') failed", 418*0Sstevel@tonic-gate ss->ss_agg_vm.ks_name); 419*0Sstevel@tonic-gate } 420*0Sstevel@tonic-gate total_faults += ksn->value.ui64; 421*0Sstevel@tonic-gate 422*0Sstevel@tonic-gate (void) printf("%9llu total address trans. faults taken\n", 423*0Sstevel@tonic-gate total_faults); 424*0Sstevel@tonic-gate 425*0Sstevel@tonic-gate sum_out("page ins", &ss->ss_agg_vm, "pgin"); 426*0Sstevel@tonic-gate sum_out("page outs", &ss->ss_agg_vm, "pgout"); 427*0Sstevel@tonic-gate sum_out("pages paged in", &ss->ss_agg_vm, "pgpgin"); 428*0Sstevel@tonic-gate sum_out("pages paged out", &ss->ss_agg_vm, "pgpgout"); 429*0Sstevel@tonic-gate sum_out("total reclaims", &ss->ss_agg_vm, "pgrec"); 430*0Sstevel@tonic-gate sum_out("reclaims from free list", &ss->ss_agg_vm, "pgfrec"); 431*0Sstevel@tonic-gate sum_out("micro (hat) faults", &ss->ss_agg_vm, "hat_fault"); 432*0Sstevel@tonic-gate sum_out("minor (as) faults", &ss->ss_agg_vm, "as_fault"); 433*0Sstevel@tonic-gate sum_out("major faults", &ss->ss_agg_vm, "maj_fault"); 434*0Sstevel@tonic-gate sum_out("copy-on-write faults", &ss->ss_agg_vm, "cow_fault"); 435*0Sstevel@tonic-gate sum_out("zero fill page faults", &ss->ss_agg_vm, "zfod"); 436*0Sstevel@tonic-gate sum_out("pages examined by the clock daemon", &ss->ss_agg_vm, "scan"); 437*0Sstevel@tonic-gate sum_out("revolutions of the clock hand", &ss->ss_agg_vm, "rev"); 438*0Sstevel@tonic-gate sum_out("pages freed by the clock daemon", &ss->ss_agg_vm, "dfree"); 439*0Sstevel@tonic-gate sum_out("forks", &ss->ss_agg_sys, "sysfork"); 440*0Sstevel@tonic-gate sum_out("vforks", &ss->ss_agg_sys, "sysvfork"); 441*0Sstevel@tonic-gate sum_out("execs", &ss->ss_agg_sys, "sysexec"); 442*0Sstevel@tonic-gate sum_out("cpu context switches", &ss->ss_agg_sys, "pswitch"); 443*0Sstevel@tonic-gate sum_out("device interrupts", &ss->ss_agg_sys, "intr"); 444*0Sstevel@tonic-gate sum_out("traps", &ss->ss_agg_sys, "trap"); 445*0Sstevel@tonic-gate sum_out("system calls", &ss->ss_agg_sys, "syscall"); 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate nchtotal = (long double) ss->ss_nc.ncs_hits.value.ui64 + 448*0Sstevel@tonic-gate (long double) ss->ss_nc.ncs_misses.value.ui64; 449*0Sstevel@tonic-gate nchhits = ss->ss_nc.ncs_hits.value.ui64; 450*0Sstevel@tonic-gate (void) printf("%9.0Lf total name lookups (cache hits %.0Lf%%)\n", 451*0Sstevel@tonic-gate nchtotal, nchhits / denom(nchtotal) * 100); 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate sum_out("user cpu", &ss->ss_agg_sys, "cpu_ticks_user"); 454*0Sstevel@tonic-gate sum_out("system cpu", &ss->ss_agg_sys, "cpu_ticks_kernel"); 455*0Sstevel@tonic-gate sum_out("idle cpu", &ss->ss_agg_sys, "cpu_ticks_idle"); 456*0Sstevel@tonic-gate sum_out("wait cpu", &ss->ss_agg_sys, "cpu_ticks_wait"); 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate static void 460*0Sstevel@tonic-gate dointr(struct snapshot *ss) 461*0Sstevel@tonic-gate { 462*0Sstevel@tonic-gate size_t i; 463*0Sstevel@tonic-gate ulong_t total = 0; 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate (void) printf("interrupt total rate\n"); 466*0Sstevel@tonic-gate (void) printf("--------------------------------\n"); 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate for (i = 0; i < ss->s_nr_intrs; i++) { 469*0Sstevel@tonic-gate (void) printf("%-12.8s %10lu %8.0f\n", 470*0Sstevel@tonic-gate ss->s_intrs[i].is_name, ss->s_intrs[i].is_total, 471*0Sstevel@tonic-gate ss->s_intrs[i].is_total / etime); 472*0Sstevel@tonic-gate total += ss->s_intrs[i].is_total; 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate (void) printf("--------------------------------\n"); 476*0Sstevel@tonic-gate (void) printf("Total %10lu %8.0f\n", total, total / etime); 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate static void 480*0Sstevel@tonic-gate docachestats(kstat_ctl_t *kc) 481*0Sstevel@tonic-gate { 482*0Sstevel@tonic-gate struct snapshot *old; 483*0Sstevel@tonic-gate struct snapshot *new; 484*0Sstevel@tonic-gate int i; 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate old = acquire_snapshot(kc, SNAP_FLUSHES, NULL); 487*0Sstevel@tonic-gate 488*0Sstevel@tonic-gate if (iter == 0) { 489*0Sstevel@tonic-gate (void) printf("flush statistics: (totals)\n"); 490*0Sstevel@tonic-gate (void) printf("%8s%8s%8s%8s%8s%8s\n", 491*0Sstevel@tonic-gate "usr", "ctx", "rgn", "seg", "pag", "par"); 492*0Sstevel@tonic-gate (void) printf(" %7d %7d %7d %7d %7d %7d\n", 493*0Sstevel@tonic-gate old->s_flushes.f_usr, old->s_flushes.f_ctx, 494*0Sstevel@tonic-gate old->s_flushes.f_region, old->s_flushes.f_segment, 495*0Sstevel@tonic-gate old->s_flushes.f_page, old->s_flushes.f_partial); 496*0Sstevel@tonic-gate return; 497*0Sstevel@tonic-gate } 498*0Sstevel@tonic-gate 499*0Sstevel@tonic-gate (void) printf("flush statistics: (interval based)\n"); 500*0Sstevel@tonic-gate for (i = 0; i < iter; i++) { 501*0Sstevel@tonic-gate if (i % REPRINT == 0) 502*0Sstevel@tonic-gate (void) printf("%8s%8s%8s%8s%8s%8s\n", 503*0Sstevel@tonic-gate "usr", "ctx", "rgn", "seg", "pag", "par"); 504*0Sstevel@tonic-gate 505*0Sstevel@tonic-gate (void) poll(NULL, 0, poll_interval); 506*0Sstevel@tonic-gate new = acquire_snapshot(kc, SNAP_FLUSHES, NULL); 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate (void) printf(" %7d %7d %7d %7d %7d %7d\n", 509*0Sstevel@tonic-gate new->s_flushes.f_usr - old->s_flushes.f_usr, 510*0Sstevel@tonic-gate new->s_flushes.f_ctx - old->s_flushes.f_ctx, 511*0Sstevel@tonic-gate new->s_flushes.f_region - old->s_flushes.f_region, 512*0Sstevel@tonic-gate new->s_flushes.f_segment - old->s_flushes.f_segment, 513*0Sstevel@tonic-gate new->s_flushes.f_page - old->s_flushes.f_page, 514*0Sstevel@tonic-gate new->s_flushes.f_partial- old->s_flushes.f_partial); 515*0Sstevel@tonic-gate (void) fflush(stdout); 516*0Sstevel@tonic-gate free_snapshot(old); 517*0Sstevel@tonic-gate old = new; 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate static void 522*0Sstevel@tonic-gate usage(void) 523*0Sstevel@tonic-gate { 524*0Sstevel@tonic-gate (void) fprintf(stderr, 525*0Sstevel@tonic-gate "Usage: vmstat [-cipqsS] [disk ...] [interval [count]]\n"); 526*0Sstevel@tonic-gate exit(1); 527*0Sstevel@tonic-gate } 528