xref: /titanic_52/usr/src/cmd/stat/vmstat/vmstat.c (revision c65c9cdc54c4ba51aeb34ab36b73286653013c8a)
17c478bd9Sstevel@tonic-gate /*
2*c65c9cdcSDonghai Qiao  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
87c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
97c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate 
127c478bd9Sstevel@tonic-gate /* from UCB 5.4 5/17/86 */
137c478bd9Sstevel@tonic-gate /* from SunOS 4.1, SID 1.31 */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #include <stdio.h>
167c478bd9Sstevel@tonic-gate #include <stdlib.h>
177c478bd9Sstevel@tonic-gate #include <stdarg.h>
187c478bd9Sstevel@tonic-gate #include <ctype.h>
197c478bd9Sstevel@tonic-gate #include <unistd.h>
207c478bd9Sstevel@tonic-gate #include <memory.h>
217c478bd9Sstevel@tonic-gate #include <string.h>
227c478bd9Sstevel@tonic-gate #include <fcntl.h>
237c478bd9Sstevel@tonic-gate #include <errno.h>
247c478bd9Sstevel@tonic-gate #include <signal.h>
257c478bd9Sstevel@tonic-gate #include <values.h>
267c478bd9Sstevel@tonic-gate #include <poll.h>
274944376cSJohn Levon #include <locale.h>
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include "statcommon.h"
307c478bd9Sstevel@tonic-gate 
3100c76d6fStc35445 char *cmdname = "vmstat";
3200c76d6fStc35445 int caught_cont = 0;
337c478bd9Sstevel@tonic-gate 
3426fd7700SKrishnendu Sadhukhan - Sun Microsystems static uint_t timestamp_fmt = NODATE;
354944376cSJohn Levon 
367c478bd9Sstevel@tonic-gate static	int	hz;
377c478bd9Sstevel@tonic-gate static	int	pagesize;
387c478bd9Sstevel@tonic-gate static	double	etime;
397c478bd9Sstevel@tonic-gate static	int	lines = 1;
407c478bd9Sstevel@tonic-gate static	int	swflag = 0, cflag = 0, pflag = 0;
417c478bd9Sstevel@tonic-gate static	int	suppress_state;
427c478bd9Sstevel@tonic-gate static	long	iter = 0;
4300c76d6fStc35445 static	hrtime_t period_n = 0;
447c478bd9Sstevel@tonic-gate static  struct	snapshot *ss;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate struct iodev_filter df;
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #define	pgtok(a) ((a) * (pagesize >> 10))
497c478bd9Sstevel@tonic-gate #define	denom(x) ((x) ? (x) : 1)
507c478bd9Sstevel@tonic-gate #define	REPRINT	19
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate static	void	dovmstats(struct snapshot *old, struct snapshot *new);
537c478bd9Sstevel@tonic-gate static	void	printhdr(int);
547c478bd9Sstevel@tonic-gate static	void	dosum(struct sys_snapshot *ss);
557c478bd9Sstevel@tonic-gate static	void	dointr(struct snapshot *ss);
5600c76d6fStc35445 static	void	docachestats(kstat_ctl_t *kc, hrtime_t interval, int forever);
577c478bd9Sstevel@tonic-gate static	void	usage(void);
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate int
607c478bd9Sstevel@tonic-gate main(int argc, char **argv)
617c478bd9Sstevel@tonic-gate {
627c478bd9Sstevel@tonic-gate 	struct snapshot *old = NULL;
637c478bd9Sstevel@tonic-gate 	enum snapshot_types types = SNAP_SYSTEM;
647c478bd9Sstevel@tonic-gate 	int summary = 0;
657c478bd9Sstevel@tonic-gate 	int intr = 0;
667c478bd9Sstevel@tonic-gate 	kstat_ctl_t *kc;
6700c76d6fStc35445 	int forever = 0;
6800c76d6fStc35445 	hrtime_t start_n;
694944376cSJohn Levon 	int c;
704944376cSJohn Levon 
714944376cSJohn Levon 	(void) setlocale(LC_ALL, "");
724944376cSJohn Levon #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
734944376cSJohn Levon #define	TEXT_DOMAIN "SYS_TEST"		/* Use this only if it weren't */
744944376cSJohn Levon #endif
754944376cSJohn Levon 	(void) textdomain(TEXT_DOMAIN);
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	pagesize = sysconf(_SC_PAGESIZE);
787c478bd9Sstevel@tonic-gate 	hz = sysconf(_SC_CLK_TCK);
797c478bd9Sstevel@tonic-gate 
804944376cSJohn Levon 	while ((c = getopt(argc, argv, "cipqsST:")) != EOF)
814944376cSJohn Levon 		switch (c) {
827c478bd9Sstevel@tonic-gate 		case 'S':
837c478bd9Sstevel@tonic-gate 			swflag = !swflag;
847c478bd9Sstevel@tonic-gate 			break;
857c478bd9Sstevel@tonic-gate 		case 's':
867c478bd9Sstevel@tonic-gate 			summary = 1;
877c478bd9Sstevel@tonic-gate 			break;
887c478bd9Sstevel@tonic-gate 		case 'i':
897c478bd9Sstevel@tonic-gate 			intr = 1;
907c478bd9Sstevel@tonic-gate 			break;
917c478bd9Sstevel@tonic-gate 		case 'c':
927c478bd9Sstevel@tonic-gate 			cflag++;
937c478bd9Sstevel@tonic-gate 			break;
947c478bd9Sstevel@tonic-gate 		case 'q':
957c478bd9Sstevel@tonic-gate 			suppress_state = 1;
967c478bd9Sstevel@tonic-gate 			break;
977c478bd9Sstevel@tonic-gate 		case 'p':
987c478bd9Sstevel@tonic-gate 			pflag++;	/* detailed paging info */
997c478bd9Sstevel@tonic-gate 			break;
1004944376cSJohn Levon 		case 'T':
1014944376cSJohn Levon 			if (optarg) {
1024944376cSJohn Levon 				if (*optarg == 'u')
1034944376cSJohn Levon 					timestamp_fmt = UDATE;
1044944376cSJohn Levon 				else if (*optarg == 'd')
1054944376cSJohn Levon 					timestamp_fmt = DDATE;
1064944376cSJohn Levon 				else
1074944376cSJohn Levon 					usage();
1084944376cSJohn Levon 			} else {
1094944376cSJohn Levon 				usage();
1104944376cSJohn Levon 			}
1114944376cSJohn Levon 			break;
1127c478bd9Sstevel@tonic-gate 		default:
1137c478bd9Sstevel@tonic-gate 			usage();
1147c478bd9Sstevel@tonic-gate 		}
1154944376cSJohn Levon 
1164944376cSJohn Levon 	argc -= optind;
1174944376cSJohn Levon 	argv += optind;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	/* consistency with iostat */
1207c478bd9Sstevel@tonic-gate 	types |= SNAP_CPUS;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	if (intr)
1237c478bd9Sstevel@tonic-gate 		types |= SNAP_INTERRUPTS;
1247c478bd9Sstevel@tonic-gate 	if (cflag)
1257c478bd9Sstevel@tonic-gate 		types |= SNAP_FLUSHES;
1267c478bd9Sstevel@tonic-gate 	if (!intr)
1277c478bd9Sstevel@tonic-gate 		types |= SNAP_IODEVS;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	/* max to fit in less than 80 characters */
1307c478bd9Sstevel@tonic-gate 	df.if_max_iodevs = 4;
1317c478bd9Sstevel@tonic-gate 	df.if_allowed_types = IODEV_DISK;
1327c478bd9Sstevel@tonic-gate 	df.if_nr_names = 0;
1337c478bd9Sstevel@tonic-gate 	df.if_names = safe_alloc(df.if_max_iodevs * sizeof (char *));
1347c478bd9Sstevel@tonic-gate 	(void) memset(df.if_names, 0, df.if_max_iodevs * sizeof (char *));
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	while (argc > 0 && !isdigit(argv[0][0]) &&
1377c478bd9Sstevel@tonic-gate 	    df.if_nr_names < df.if_max_iodevs) {
1387c478bd9Sstevel@tonic-gate 		df.if_names[df.if_nr_names] = *argv;
1397c478bd9Sstevel@tonic-gate 		df.if_nr_names++;
1407c478bd9Sstevel@tonic-gate 		argc--, argv++;
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	kc = open_kstat();
1447c478bd9Sstevel@tonic-gate 
14500c76d6fStc35445 	start_n = gethrtime();
14600c76d6fStc35445 
1477c478bd9Sstevel@tonic-gate 	ss = acquire_snapshot(kc, types, &df);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/* time, in seconds, since boot */
1507c478bd9Sstevel@tonic-gate 	etime = ss->s_sys.ss_ticks / hz;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	if (intr) {
1537c478bd9Sstevel@tonic-gate 		dointr(ss);
1547c478bd9Sstevel@tonic-gate 		free_snapshot(ss);
1557c478bd9Sstevel@tonic-gate 		exit(0);
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 	if (summary) {
1587c478bd9Sstevel@tonic-gate 		dosum(&ss->s_sys);
1597c478bd9Sstevel@tonic-gate 		free_snapshot(ss);
1607c478bd9Sstevel@tonic-gate 		exit(0);
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 	if (argc > 0) {
1647c478bd9Sstevel@tonic-gate 		long interval;
1657c478bd9Sstevel@tonic-gate 		char *endptr;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 		errno = 0;
1687c478bd9Sstevel@tonic-gate 		interval = strtol(argv[0], &endptr, 10);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 		if (errno > 0 || *endptr != '\0' || interval <= 0 ||
1717c478bd9Sstevel@tonic-gate 		    interval > MAXINT)
1727c478bd9Sstevel@tonic-gate 			usage();
17300c76d6fStc35445 		period_n = (hrtime_t)interval * NANOSEC;
17400c76d6fStc35445 		if (period_n <= 0)
1757c478bd9Sstevel@tonic-gate 			usage();
1767c478bd9Sstevel@tonic-gate 		iter = MAXLONG;
1777c478bd9Sstevel@tonic-gate 		if (argc > 1) {
1787c478bd9Sstevel@tonic-gate 			iter = strtol(argv[1], NULL, 10);
1797c478bd9Sstevel@tonic-gate 			if (errno > 0 || *endptr != '\0' || iter <= 0)
1807c478bd9Sstevel@tonic-gate 				usage();
18100c76d6fStc35445 		} else
18200c76d6fStc35445 			forever = 1;
1837c478bd9Sstevel@tonic-gate 		if (argc > 2)
1847c478bd9Sstevel@tonic-gate 			usage();
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	if (cflag) {
1887c478bd9Sstevel@tonic-gate 		free_snapshot(ss);
18900c76d6fStc35445 		docachestats(kc, period_n, forever);
1907c478bd9Sstevel@tonic-gate 		exit(0);
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	(void) sigset(SIGCONT, printhdr);
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	dovmstats(old, ss);
19600c76d6fStc35445 	while (forever || --iter > 0) {
19700c76d6fStc35445 		/* (void) poll(NULL, 0, poll_interval); */
19800c76d6fStc35445 
19900c76d6fStc35445 		/* Have a kip */
20000c76d6fStc35445 		sleep_until(&start_n, period_n, forever, &caught_cont);
20100c76d6fStc35445 
2027c478bd9Sstevel@tonic-gate 		free_snapshot(old);
2037c478bd9Sstevel@tonic-gate 		old = ss;
2047c478bd9Sstevel@tonic-gate 		ss = acquire_snapshot(kc, types, &df);
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 		if (!suppress_state)
2077c478bd9Sstevel@tonic-gate 			snapshot_report_changes(old, ss);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 		/* if config changed, show stats from boot */
2107c478bd9Sstevel@tonic-gate 		if (snapshot_has_changed(old, ss)) {
2117c478bd9Sstevel@tonic-gate 			free_snapshot(old);
2127c478bd9Sstevel@tonic-gate 			old = NULL;
2137c478bd9Sstevel@tonic-gate 		}
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 		dovmstats(old, ss);
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	free_snapshot(old);
2197c478bd9Sstevel@tonic-gate 	free_snapshot(ss);
2207c478bd9Sstevel@tonic-gate 	free(df.if_names);
2217c478bd9Sstevel@tonic-gate 	(void) kstat_close(kc);
2227c478bd9Sstevel@tonic-gate 	return (0);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate #define	DELTA(v) (new->v - (old ? old->v : 0))
2267c478bd9Sstevel@tonic-gate #define	ADJ(n)	((adj <= 0) ? n : (adj >= n) ? 1 : n - adj)
2277c478bd9Sstevel@tonic-gate #define	adjprintf(fmt, n, val)	adj -= (n + 1) - printf(fmt, ADJ(n), val)
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate static int adj;	/* number of excess columns */
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2327c478bd9Sstevel@tonic-gate static void
2337c478bd9Sstevel@tonic-gate show_disk(void *v1, void *v2, void *d)
2347c478bd9Sstevel@tonic-gate {
2357c478bd9Sstevel@tonic-gate 	struct iodev_snapshot *old = (struct iodev_snapshot *)v1;
2367c478bd9Sstevel@tonic-gate 	struct iodev_snapshot *new = (struct iodev_snapshot *)v2;
2377c478bd9Sstevel@tonic-gate 	hrtime_t oldtime = new->is_crtime;
2387c478bd9Sstevel@tonic-gate 	double hr_etime;
2397c478bd9Sstevel@tonic-gate 	double reads, writes;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	if (new == NULL)
2427c478bd9Sstevel@tonic-gate 		return;
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	if (old)
2457c478bd9Sstevel@tonic-gate 		oldtime = old->is_stats.wlastupdate;
2467c478bd9Sstevel@tonic-gate 	hr_etime = new->is_stats.wlastupdate - oldtime;
2477c478bd9Sstevel@tonic-gate 	if (hr_etime == 0.0)
2487c478bd9Sstevel@tonic-gate 		hr_etime = NANOSEC;
2497c478bd9Sstevel@tonic-gate 	reads = new->is_stats.reads - (old ? old->is_stats.reads : 0);
2507c478bd9Sstevel@tonic-gate 	writes = new->is_stats.writes - (old ? old->is_stats.writes : 0);
2517c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 2, (reads + writes) / hr_etime * NANOSEC);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate static void
2557c478bd9Sstevel@tonic-gate dovmstats(struct snapshot *old, struct snapshot *new)
2567c478bd9Sstevel@tonic-gate {
2577c478bd9Sstevel@tonic-gate 	kstat_t *oldsys = NULL;
2587c478bd9Sstevel@tonic-gate 	kstat_t *newsys = &new->s_sys.ss_agg_sys;
2597c478bd9Sstevel@tonic-gate 	kstat_t *oldvm = NULL;
2607c478bd9Sstevel@tonic-gate 	kstat_t *newvm = &new->s_sys.ss_agg_vm;
2617c478bd9Sstevel@tonic-gate 	double percent_factor;
262*c65c9cdcSDonghai Qiao 	ulong_t sys_updates, vm_updates;
2637c478bd9Sstevel@tonic-gate 	int count;
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	adj = 0;
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	if (old) {
2687c478bd9Sstevel@tonic-gate 		oldsys = &old->s_sys.ss_agg_sys;
2697c478bd9Sstevel@tonic-gate 		oldvm = &old->s_sys.ss_agg_vm;
2707c478bd9Sstevel@tonic-gate 	}
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 	etime = cpu_ticks_delta(oldsys, newsys);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	percent_factor = 100.0 / denom(etime);
2757c478bd9Sstevel@tonic-gate 	/*
2767c478bd9Sstevel@tonic-gate 	 * If any time has passed, convert etime to seconds per CPU
2777c478bd9Sstevel@tonic-gate 	 */
2787c478bd9Sstevel@tonic-gate 	etime = etime >= 1.0 ? (etime / nr_active_cpus(new)) / hz : 1.0;
279*c65c9cdcSDonghai Qiao 	sys_updates = denom(DELTA(s_sys.ss_sysinfo.updates));
280*c65c9cdcSDonghai Qiao 	vm_updates = denom(DELTA(s_sys.ss_vminfo.updates));
2817c478bd9Sstevel@tonic-gate 
2824944376cSJohn Levon 	if (timestamp_fmt != NODATE) {
28326fd7700SKrishnendu Sadhukhan - Sun Microsystems 		print_timestamp(timestamp_fmt);
2844944376cSJohn Levon 		lines--;
2854944376cSJohn Levon 	}
2864944376cSJohn Levon 
2874944376cSJohn Levon 	if (--lines <= 0)
2887c478bd9Sstevel@tonic-gate 		printhdr(0);
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	adj = 0;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	if (pflag) {
2937c478bd9Sstevel@tonic-gate 		adjprintf(" %*u", 6,
294*c65c9cdcSDonghai Qiao 		    pgtok((int)(DELTA(s_sys.ss_vminfo.swap_avail)
295*c65c9cdcSDonghai Qiao 		    / vm_updates)));
2967c478bd9Sstevel@tonic-gate 		adjprintf(" %*u", 5,
297*c65c9cdcSDonghai Qiao 		    pgtok((int)(DELTA(s_sys.ss_vminfo.freemem) / vm_updates)));
2987c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 3, kstat_delta(oldvm, newvm, "pgrec")
2997c478bd9Sstevel@tonic-gate 		    / etime);
3007c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 3, (kstat_delta(oldvm, newvm, "hat_fault") +
3017c478bd9Sstevel@tonic-gate 		    kstat_delta(oldvm, newvm, "as_fault")) / etime);
3027c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 3, pgtok(kstat_delta(oldvm, newvm, "dfree"))
3037c478bd9Sstevel@tonic-gate 		    / etime);
3047c478bd9Sstevel@tonic-gate 		adjprintf(" %*ld", 3, pgtok(new->s_sys.ss_deficit));
3057c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 3, kstat_delta(oldvm, newvm, "scan")
3067c478bd9Sstevel@tonic-gate 		    / etime);
3077c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 4,
3087c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "execpgin")) / etime);
3097c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 4,
3107c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "execpgout")) / etime);
3117c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 4,
3127c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "execfree")) / etime);
3137c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 4,
3147c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "anonpgin")) / etime);
3157c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 4,
3167c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "anonpgout")) / etime);
3177c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 4,
3187c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "anonfree")) / etime);
3197c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 4,
3207c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "fspgin")) / etime);
3217c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f", 4,
3227c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "fspgout")) / etime);
3237c478bd9Sstevel@tonic-gate 		adjprintf(" %*.0f\n", 4,
3247c478bd9Sstevel@tonic-gate 		    pgtok(kstat_delta(oldvm, newvm, "fsfree")) / etime);
3257c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
3267c478bd9Sstevel@tonic-gate 		return;
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
329*c65c9cdcSDonghai Qiao 	adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.runque) / sys_updates);
330*c65c9cdcSDonghai Qiao 	adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.waiting) / sys_updates);
331*c65c9cdcSDonghai Qiao 	adjprintf(" %*lu", 1, DELTA(s_sys.ss_sysinfo.swpque) / sys_updates);
3327c478bd9Sstevel@tonic-gate 	adjprintf(" %*u", 6, pgtok((int)(DELTA(s_sys.ss_vminfo.swap_avail)
333*c65c9cdcSDonghai Qiao 	    / vm_updates)));
3347c478bd9Sstevel@tonic-gate 	adjprintf(" %*u", 5, pgtok((int)(DELTA(s_sys.ss_vminfo.freemem)
335*c65c9cdcSDonghai Qiao 	    / vm_updates)));
3367c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 3, swflag?
3377c478bd9Sstevel@tonic-gate 	    kstat_delta(oldvm, newvm, "swapin") / etime :
3387c478bd9Sstevel@tonic-gate 	    kstat_delta(oldvm, newvm, "pgrec") / etime);
3397c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 3, swflag?
3407c478bd9Sstevel@tonic-gate 	    kstat_delta(oldvm, newvm, "swapout") / etime :
3417c478bd9Sstevel@tonic-gate 	    (kstat_delta(oldvm, newvm, "hat_fault")
3427c478bd9Sstevel@tonic-gate 	    + kstat_delta(oldvm, newvm, "as_fault"))
3437c478bd9Sstevel@tonic-gate 	    / etime);
3447c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "pgpgin"))
3457c478bd9Sstevel@tonic-gate 	    / etime);
3467c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "pgpgout"))
3477c478bd9Sstevel@tonic-gate 	    / etime);
3487c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 2, pgtok(kstat_delta(oldvm, newvm, "dfree"))
3497c478bd9Sstevel@tonic-gate 	    / etime);
3507c478bd9Sstevel@tonic-gate 	adjprintf(" %*ld", 2, pgtok(new->s_sys.ss_deficit));
3517c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 2, kstat_delta(oldvm, newvm, "scan") / etime);
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 	(void) snapshot_walk(SNAP_IODEVS, old, new, show_disk, NULL);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	count = df.if_max_iodevs - new->s_nr_iodevs;
3567c478bd9Sstevel@tonic-gate 	while (count-- > 0)
3577c478bd9Sstevel@tonic-gate 		adjprintf(" %*d", 2, 0);
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "intr") / etime);
3607c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "syscall") / etime);
3617c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 4, kstat_delta(oldsys, newsys, "pswitch") / etime);
3627c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 2,
3637c478bd9Sstevel@tonic-gate 	    kstat_delta(oldsys, newsys, "cpu_ticks_user") * percent_factor);
3647c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f", 2, kstat_delta(oldsys, newsys, "cpu_ticks_kernel")
3657c478bd9Sstevel@tonic-gate 	    * percent_factor);
3667c478bd9Sstevel@tonic-gate 	adjprintf(" %*.0f\n", 2, (kstat_delta(oldsys, newsys, "cpu_ticks_idle")
3677c478bd9Sstevel@tonic-gate 	    + kstat_delta(oldsys, newsys, "cpu_ticks_wait"))
3687c478bd9Sstevel@tonic-gate 	    * percent_factor);
3697c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3737c478bd9Sstevel@tonic-gate static void
3747c478bd9Sstevel@tonic-gate print_disk(void *v, void *v2, void *d)
3757c478bd9Sstevel@tonic-gate {
3767c478bd9Sstevel@tonic-gate 	struct iodev_snapshot *iodev = (struct iodev_snapshot *)v2;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	if (iodev == NULL)
3797c478bd9Sstevel@tonic-gate 		return;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	(void) printf("%c%c ", iodev->is_name[0], iodev->is_name[2]);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate /* ARGSUSED */
3857c478bd9Sstevel@tonic-gate static void
3867c478bd9Sstevel@tonic-gate printhdr(int sig)
3877c478bd9Sstevel@tonic-gate {
3887c478bd9Sstevel@tonic-gate 	int i = df.if_max_iodevs - ss->s_nr_iodevs;
3897c478bd9Sstevel@tonic-gate 
39000c76d6fStc35445 	if (sig == SIGCONT)
39100c76d6fStc35445 		caught_cont = 1;
39200c76d6fStc35445 
3937c478bd9Sstevel@tonic-gate 	if (pflag) {
3947c478bd9Sstevel@tonic-gate 		(void) printf("     memory           page          ");
3957c478bd9Sstevel@tonic-gate 		(void) printf("executable      anonymous      filesystem \n");
3967c478bd9Sstevel@tonic-gate 		(void) printf("   swap  free  re  mf  fr  de  sr  ");
3977c478bd9Sstevel@tonic-gate 		(void) printf("epi  epo  epf  api  apo  apf  fpi  fpo  fpf\n");
3987c478bd9Sstevel@tonic-gate 		lines = REPRINT;
3997c478bd9Sstevel@tonic-gate 		return;
4007c478bd9Sstevel@tonic-gate 	}
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	(void) printf(" kthr      memory            page            ");
4037c478bd9Sstevel@tonic-gate 	(void) printf("disk          faults      cpu\n");
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	if (swflag)
4067c478bd9Sstevel@tonic-gate 		(void) printf(" r b w   swap  free  si  so pi po fr de sr ");
4077c478bd9Sstevel@tonic-gate 	else
4087c478bd9Sstevel@tonic-gate 		(void) printf(" r b w   swap  free  re  mf pi po fr de sr ");
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	(void) snapshot_walk(SNAP_IODEVS, NULL, ss, print_disk, NULL);
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate 	while (i-- > 0)
4137c478bd9Sstevel@tonic-gate 		(void) printf("-- ");
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	(void) printf("  in   sy   cs us sy id\n");
4167c478bd9Sstevel@tonic-gate 	lines = REPRINT;
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate static void
4207c478bd9Sstevel@tonic-gate sum_out(char const *pretty, kstat_t *ks, char *name)
4217c478bd9Sstevel@tonic-gate {
4227c478bd9Sstevel@tonic-gate 	kstat_named_t *ksn = kstat_data_lookup(ks, name);
4237c478bd9Sstevel@tonic-gate 	if (ksn == NULL) {
4247c478bd9Sstevel@tonic-gate 		fail(0, "kstat_data_lookup('%s', '%s') failed",
4257c478bd9Sstevel@tonic-gate 		    ks->ks_name, name);
4267c478bd9Sstevel@tonic-gate 	}
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	(void) printf("%9llu %s\n", ksn->value.ui64, pretty);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate static void
4327c478bd9Sstevel@tonic-gate dosum(struct sys_snapshot *ss)
4337c478bd9Sstevel@tonic-gate {
4347c478bd9Sstevel@tonic-gate 	uint64_t total_faults;
4357c478bd9Sstevel@tonic-gate 	kstat_named_t *ksn;
4367c478bd9Sstevel@tonic-gate 	long double nchtotal;
4377c478bd9Sstevel@tonic-gate 	uint64_t nchhits;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	sum_out("swap ins", &ss->ss_agg_vm, "swapin");
4407c478bd9Sstevel@tonic-gate 	sum_out("swap outs", &ss->ss_agg_vm, "swapout");
4417c478bd9Sstevel@tonic-gate 	sum_out("pages swapped in", &ss->ss_agg_vm, "pgswapin");
4427c478bd9Sstevel@tonic-gate 	sum_out("pages swapped out", &ss->ss_agg_vm, "pgswapout");
4437c478bd9Sstevel@tonic-gate 
4447c478bd9Sstevel@tonic-gate 	ksn = kstat_data_lookup(&ss->ss_agg_vm, "hat_fault");
4457c478bd9Sstevel@tonic-gate 	if (ksn == NULL) {
4467c478bd9Sstevel@tonic-gate 		fail(0, "kstat_data_lookup('%s', 'hat_fault') failed",
4477c478bd9Sstevel@tonic-gate 		    ss->ss_agg_vm.ks_name);
4487c478bd9Sstevel@tonic-gate 	}
4497c478bd9Sstevel@tonic-gate 	total_faults = ksn->value.ui64;
4507c478bd9Sstevel@tonic-gate 	ksn = kstat_data_lookup(&ss->ss_agg_vm, "as_fault");
4517c478bd9Sstevel@tonic-gate 	if (ksn == NULL) {
4527c478bd9Sstevel@tonic-gate 		fail(0, "kstat_data_lookup('%s', 'as_fault') failed",
4537c478bd9Sstevel@tonic-gate 		    ss->ss_agg_vm.ks_name);
4547c478bd9Sstevel@tonic-gate 	}
4557c478bd9Sstevel@tonic-gate 	total_faults += ksn->value.ui64;
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 	(void) printf("%9llu total address trans. faults taken\n",
4587c478bd9Sstevel@tonic-gate 	    total_faults);
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	sum_out("page ins", &ss->ss_agg_vm, "pgin");
4617c478bd9Sstevel@tonic-gate 	sum_out("page outs", &ss->ss_agg_vm, "pgout");
4627c478bd9Sstevel@tonic-gate 	sum_out("pages paged in", &ss->ss_agg_vm, "pgpgin");
4637c478bd9Sstevel@tonic-gate 	sum_out("pages paged out", &ss->ss_agg_vm, "pgpgout");
4647c478bd9Sstevel@tonic-gate 	sum_out("total reclaims", &ss->ss_agg_vm, "pgrec");
4657c478bd9Sstevel@tonic-gate 	sum_out("reclaims from free list", &ss->ss_agg_vm, "pgfrec");
4667c478bd9Sstevel@tonic-gate 	sum_out("micro (hat) faults", &ss->ss_agg_vm, "hat_fault");
4677c478bd9Sstevel@tonic-gate 	sum_out("minor (as) faults", &ss->ss_agg_vm, "as_fault");
4687c478bd9Sstevel@tonic-gate 	sum_out("major faults", &ss->ss_agg_vm, "maj_fault");
4697c478bd9Sstevel@tonic-gate 	sum_out("copy-on-write faults", &ss->ss_agg_vm, "cow_fault");
4707c478bd9Sstevel@tonic-gate 	sum_out("zero fill page faults", &ss->ss_agg_vm, "zfod");
4717c478bd9Sstevel@tonic-gate 	sum_out("pages examined by the clock daemon", &ss->ss_agg_vm, "scan");
4727c478bd9Sstevel@tonic-gate 	sum_out("revolutions of the clock hand", &ss->ss_agg_vm, "rev");
4737c478bd9Sstevel@tonic-gate 	sum_out("pages freed by the clock daemon", &ss->ss_agg_vm, "dfree");
4747c478bd9Sstevel@tonic-gate 	sum_out("forks", &ss->ss_agg_sys, "sysfork");
4757c478bd9Sstevel@tonic-gate 	sum_out("vforks", &ss->ss_agg_sys, "sysvfork");
4767c478bd9Sstevel@tonic-gate 	sum_out("execs", &ss->ss_agg_sys, "sysexec");
4777c478bd9Sstevel@tonic-gate 	sum_out("cpu context switches", &ss->ss_agg_sys, "pswitch");
4787c478bd9Sstevel@tonic-gate 	sum_out("device interrupts", &ss->ss_agg_sys, "intr");
4797c478bd9Sstevel@tonic-gate 	sum_out("traps", &ss->ss_agg_sys, "trap");
4807c478bd9Sstevel@tonic-gate 	sum_out("system calls", &ss->ss_agg_sys, "syscall");
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	nchtotal = (long double) ss->ss_nc.ncs_hits.value.ui64 +
4837c478bd9Sstevel@tonic-gate 	    (long double) ss->ss_nc.ncs_misses.value.ui64;
4847c478bd9Sstevel@tonic-gate 	nchhits = ss->ss_nc.ncs_hits.value.ui64;
4857c478bd9Sstevel@tonic-gate 	(void) printf("%9.0Lf total name lookups (cache hits %.0Lf%%)\n",
4867c478bd9Sstevel@tonic-gate 	    nchtotal, nchhits / denom(nchtotal) * 100);
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	sum_out("user   cpu", &ss->ss_agg_sys, "cpu_ticks_user");
4897c478bd9Sstevel@tonic-gate 	sum_out("system cpu", &ss->ss_agg_sys, "cpu_ticks_kernel");
4907c478bd9Sstevel@tonic-gate 	sum_out("idle   cpu", &ss->ss_agg_sys, "cpu_ticks_idle");
4917c478bd9Sstevel@tonic-gate 	sum_out("wait   cpu", &ss->ss_agg_sys, "cpu_ticks_wait");
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate static void
4957c478bd9Sstevel@tonic-gate dointr(struct snapshot *ss)
4967c478bd9Sstevel@tonic-gate {
4977c478bd9Sstevel@tonic-gate 	size_t i;
4987c478bd9Sstevel@tonic-gate 	ulong_t total = 0;
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	(void) printf("interrupt         total     rate\n");
5017c478bd9Sstevel@tonic-gate 	(void) printf("--------------------------------\n");
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	for (i = 0; i < ss->s_nr_intrs; i++) {
5047c478bd9Sstevel@tonic-gate 		(void) printf("%-12.8s %10lu %8.0f\n",
5057c478bd9Sstevel@tonic-gate 		    ss->s_intrs[i].is_name, ss->s_intrs[i].is_total,
5067c478bd9Sstevel@tonic-gate 		    ss->s_intrs[i].is_total / etime);
5077c478bd9Sstevel@tonic-gate 		total += ss->s_intrs[i].is_total;
5087c478bd9Sstevel@tonic-gate 	}
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	(void) printf("--------------------------------\n");
5117c478bd9Sstevel@tonic-gate 	(void) printf("Total        %10lu %8.0f\n", total, total / etime);
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate static void
51500c76d6fStc35445 docachestats(kstat_ctl_t *kc, hrtime_t interval, int forever)
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate 	struct snapshot *old;
5187c478bd9Sstevel@tonic-gate 	struct snapshot *new;
5197c478bd9Sstevel@tonic-gate 	int i;
52000c76d6fStc35445 	hrtime_t start;
5217c478bd9Sstevel@tonic-gate 
52200c76d6fStc35445 	start = gethrtime();
5237c478bd9Sstevel@tonic-gate 	old = acquire_snapshot(kc, SNAP_FLUSHES, NULL);
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	if (iter == 0) {
5267c478bd9Sstevel@tonic-gate 		(void) printf("flush statistics: (totals)\n");
5277c478bd9Sstevel@tonic-gate 		(void) printf("%8s%8s%8s%8s%8s%8s\n",
5287c478bd9Sstevel@tonic-gate 		    "usr", "ctx", "rgn", "seg", "pag", "par");
5297c478bd9Sstevel@tonic-gate 		(void) printf(" %7d %7d %7d %7d %7d %7d\n",
5307c478bd9Sstevel@tonic-gate 		    old->s_flushes.f_usr, old->s_flushes.f_ctx,
5317c478bd9Sstevel@tonic-gate 		    old->s_flushes.f_region, old->s_flushes.f_segment,
5327c478bd9Sstevel@tonic-gate 		    old->s_flushes.f_page, old->s_flushes.f_partial);
5337c478bd9Sstevel@tonic-gate 		return;
5347c478bd9Sstevel@tonic-gate 	}
5357c478bd9Sstevel@tonic-gate 
5367c478bd9Sstevel@tonic-gate 	(void) printf("flush statistics: (interval based)\n");
5377c478bd9Sstevel@tonic-gate 	for (i = 0; i < iter; i++) {
5387c478bd9Sstevel@tonic-gate 		if (i % REPRINT == 0)
5397c478bd9Sstevel@tonic-gate 			(void) printf("%8s%8s%8s%8s%8s%8s\n",
5407c478bd9Sstevel@tonic-gate 			    "usr", "ctx", "rgn", "seg", "pag", "par");
5417c478bd9Sstevel@tonic-gate 
54200c76d6fStc35445 		/* Have a kip */
54300c76d6fStc35445 		sleep_until(&start, interval, forever, &caught_cont);
54400c76d6fStc35445 
5457c478bd9Sstevel@tonic-gate 		new = acquire_snapshot(kc, SNAP_FLUSHES, NULL);
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 		(void) printf(" %7d %7d %7d %7d %7d %7d\n",
5487c478bd9Sstevel@tonic-gate 		    new->s_flushes.f_usr - old->s_flushes.f_usr,
5497c478bd9Sstevel@tonic-gate 		    new->s_flushes.f_ctx - old->s_flushes.f_ctx,
5507c478bd9Sstevel@tonic-gate 		    new->s_flushes.f_region - old->s_flushes.f_region,
5517c478bd9Sstevel@tonic-gate 		    new->s_flushes.f_segment - old->s_flushes.f_segment,
5527c478bd9Sstevel@tonic-gate 		    new->s_flushes.f_page - old->s_flushes.f_page,
5537c478bd9Sstevel@tonic-gate 		    new->s_flushes.f_partial- old->s_flushes.f_partial);
5547c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
5557c478bd9Sstevel@tonic-gate 		free_snapshot(old);
5567c478bd9Sstevel@tonic-gate 		old = new;
5577c478bd9Sstevel@tonic-gate 	}
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate static void
5617c478bd9Sstevel@tonic-gate usage(void)
5627c478bd9Sstevel@tonic-gate {
5637c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
5644944376cSJohn Levon 	    "Usage: vmstat [-cipqsS] [-T d|u] [disk ...] "
5654944376cSJohn Levon 	    "[interval [count]]\n");
5667c478bd9Sstevel@tonic-gate 	exit(1);
5677c478bd9Sstevel@tonic-gate }
568