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