xref: /titanic_44/usr/src/cmd/stat/kstat/kstat.c (revision 9736aecd323ba323a24c159dc877b29795d68a0a)
166448911SDavid Höppner /*
266448911SDavid Höppner  * CDDL HEADER START
366448911SDavid Höppner  *
466448911SDavid Höppner  * The contents of this file are subject to the terms of the
566448911SDavid Höppner  * Common Development and Distribution License (the "License").
666448911SDavid Höppner  * You may not use this file except in compliance with the License.
766448911SDavid Höppner  *
866448911SDavid Höppner  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
966448911SDavid Höppner  * or http://www.opensolaris.org/os/licensing.
1066448911SDavid Höppner  * See the License for the specific language governing permissions
1166448911SDavid Höppner  * and limitations under the License.
1266448911SDavid Höppner  *
1366448911SDavid Höppner  * When distributing Covered Code, include this CDDL HEADER in each
1466448911SDavid Höppner  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1566448911SDavid Höppner  * If applicable, add the following below this CDDL HEADER, with the
1666448911SDavid Höppner  * fields enclosed by brackets "[]" replaced with your own identifying
1766448911SDavid Höppner  * information: Portions Copyright [yyyy] [name of copyright owner]
1866448911SDavid Höppner  *
1966448911SDavid Höppner  * CDDL HEADER END
2066448911SDavid Höppner  */
2166448911SDavid Höppner 
2266448911SDavid Höppner /*
2366448911SDavid Höppner  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
2466448911SDavid Höppner  * Copyright (c) 2013 David Hoeppner. All rights reserved.
2566448911SDavid Höppner  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
26*9736aecdSBryan Cantrill  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
2766448911SDavid Höppner  */
2866448911SDavid Höppner 
2966448911SDavid Höppner /*
3066448911SDavid Höppner  * Display kernel statistics
3166448911SDavid Höppner  *
3266448911SDavid Höppner  * This is a reimplementation of the perl kstat command originally found
3366448911SDavid Höppner  * under usr/src/cmd/kstat/kstat.pl
3466448911SDavid Höppner  *
3566448911SDavid Höppner  * Incompatibilities:
3666448911SDavid Höppner  *	- perl regular expressions replaced with extended REs bracketed by '/'
3766448911SDavid Höppner  *
3866448911SDavid Höppner  * Flags added:
3966448911SDavid Höppner  *	-C	similar to the -p option but value is separated by a colon
4066448911SDavid Höppner  *	-h	display help
4166448911SDavid Höppner  *	-j	json format
4266448911SDavid Höppner  */
4366448911SDavid Höppner 
4466448911SDavid Höppner #include <assert.h>
4566448911SDavid Höppner #include <ctype.h>
4666448911SDavid Höppner #include <errno.h>
4766448911SDavid Höppner #include <kstat.h>
4866448911SDavid Höppner #include <langinfo.h>
4966448911SDavid Höppner #include <libgen.h>
5066448911SDavid Höppner #include <limits.h>
5166448911SDavid Höppner #include <locale.h>
5266448911SDavid Höppner #include <signal.h>
5366448911SDavid Höppner #include <stddef.h>
5466448911SDavid Höppner #include <stdio.h>
5566448911SDavid Höppner #include <stdlib.h>
5666448911SDavid Höppner #include <string.h>
5766448911SDavid Höppner #include <strings.h>
5866448911SDavid Höppner #include <time.h>
5966448911SDavid Höppner #include <unistd.h>
6066448911SDavid Höppner #include <sys/list.h>
6166448911SDavid Höppner #include <sys/time.h>
6266448911SDavid Höppner #include <sys/types.h>
6366448911SDavid Höppner 
6466448911SDavid Höppner #include "kstat.h"
6566448911SDavid Höppner #include "statcommon.h"
6666448911SDavid Höppner 
6766448911SDavid Höppner char	*cmdname = "kstat";	/* Name of this command */
6866448911SDavid Höppner int	caught_cont = 0;	/* Have caught a SIGCONT */
6966448911SDavid Höppner 
7066448911SDavid Höppner static uint_t	g_timestamp_fmt = NODATE;
7166448911SDavid Höppner 
7266448911SDavid Höppner /* Helper flag - header was printed already? */
7366448911SDavid Höppner static boolean_t g_headerflg;
7466448911SDavid Höppner 
7566448911SDavid Höppner /* Saved command line options */
7666448911SDavid Höppner static boolean_t g_cflg = B_FALSE;
7766448911SDavid Höppner static boolean_t g_jflg = B_FALSE;
7866448911SDavid Höppner static boolean_t g_lflg = B_FALSE;
7966448911SDavid Höppner static boolean_t g_pflg = B_FALSE;
8066448911SDavid Höppner static boolean_t g_qflg = B_FALSE;
8166448911SDavid Höppner static ks_pattern_t	g_ks_class = {"*", 0};
8266448911SDavid Höppner 
8366448911SDavid Höppner /* Return zero if a selector did match */
8466448911SDavid Höppner static int	g_matched = 1;
8566448911SDavid Höppner 
8666448911SDavid Höppner /* Sorted list of kstat instances */
8766448911SDavid Höppner static list_t	instances_list;
8866448911SDavid Höppner static list_t	selector_list;
8966448911SDavid Höppner 
9066448911SDavid Höppner int
main(int argc,char ** argv)9166448911SDavid Höppner main(int argc, char **argv)
9266448911SDavid Höppner {
9366448911SDavid Höppner 	ks_selector_t	*nselector;
9466448911SDavid Höppner 	ks_selector_t	*uselector;
9566448911SDavid Höppner 	kstat_ctl_t	*kc;
9666448911SDavid Höppner 	hrtime_t	start_n;
9766448911SDavid Höppner 	hrtime_t	period_n;
9866448911SDavid Höppner 	boolean_t	errflg = B_FALSE;
9966448911SDavid Höppner 	boolean_t	nselflg = B_FALSE;
10066448911SDavid Höppner 	boolean_t	uselflg = B_FALSE;
10166448911SDavid Höppner 	char		*q;
10266448911SDavid Höppner 	int		count = 1;
10366448911SDavid Höppner 	int		infinite_cycles = 0;
10466448911SDavid Höppner 	int		interval = 0;
10566448911SDavid Höppner 	int		n = 0;
10666448911SDavid Höppner 	int		c, m, tmp;
10766448911SDavid Höppner 
10866448911SDavid Höppner 	(void) setlocale(LC_ALL, "");
10966448911SDavid Höppner #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
11066448911SDavid Höppner #define	TEXT_DOMAIN "SYS_TEST"		/* Use this only if it wasn't */
11166448911SDavid Höppner #endif
11266448911SDavid Höppner 	(void) textdomain(TEXT_DOMAIN);
11366448911SDavid Höppner 
11466448911SDavid Höppner 	/*
11566448911SDavid Höppner 	 * Create the selector list and a dummy default selector to match
11666448911SDavid Höppner 	 * everything. While we process the cmdline options we will add
11766448911SDavid Höppner 	 * selectors to this list.
11866448911SDavid Höppner 	 */
11966448911SDavid Höppner 	list_create(&selector_list, sizeof (ks_selector_t),
12066448911SDavid Höppner 	    offsetof(ks_selector_t, ks_next));
12166448911SDavid Höppner 
12266448911SDavid Höppner 	nselector = new_selector();
12366448911SDavid Höppner 
12466448911SDavid Höppner 	/*
12566448911SDavid Höppner 	 * Parse named command line arguments.
12666448911SDavid Höppner 	 */
12766448911SDavid Höppner 	while ((c = getopt(argc, argv, "h?CqjlpT:m:i:n:s:c:")) != EOF)
12866448911SDavid Höppner 		switch (c) {
12966448911SDavid Höppner 		case 'h':
13066448911SDavid Höppner 		case '?':
13166448911SDavid Höppner 			usage();
13266448911SDavid Höppner 			exit(0);
13366448911SDavid Höppner 			break;
13466448911SDavid Höppner 		case 'C':
13566448911SDavid Höppner 			g_pflg = g_cflg = B_TRUE;
13666448911SDavid Höppner 			break;
13766448911SDavid Höppner 		case 'q':
13866448911SDavid Höppner 			g_qflg = B_TRUE;
13966448911SDavid Höppner 			break;
14066448911SDavid Höppner 		case 'j':
14166448911SDavid Höppner 			g_jflg = B_TRUE;
14266448911SDavid Höppner 			break;
14366448911SDavid Höppner 		case 'l':
14466448911SDavid Höppner 			g_pflg = g_lflg = B_TRUE;
14566448911SDavid Höppner 			break;
14666448911SDavid Höppner 		case 'p':
14766448911SDavid Höppner 			g_pflg = B_TRUE;
14866448911SDavid Höppner 			break;
14966448911SDavid Höppner 		case 'T':
15066448911SDavid Höppner 			switch (*optarg) {
15166448911SDavid Höppner 			case 'd':
15266448911SDavid Höppner 				g_timestamp_fmt = DDATE;
15366448911SDavid Höppner 				break;
15466448911SDavid Höppner 			case 'u':
15566448911SDavid Höppner 				g_timestamp_fmt = UDATE;
15666448911SDavid Höppner 				break;
15766448911SDavid Höppner 			default:
15866448911SDavid Höppner 				errflg = B_TRUE;
15966448911SDavid Höppner 			}
16066448911SDavid Höppner 			break;
16166448911SDavid Höppner 		case 'm':
16266448911SDavid Höppner 			nselflg = B_TRUE;
16366448911SDavid Höppner 			nselector->ks_module.pstr =
16466448911SDavid Höppner 			    (char *)ks_safe_strdup(optarg);
16566448911SDavid Höppner 			break;
16666448911SDavid Höppner 		case 'i':
16766448911SDavid Höppner 			nselflg = B_TRUE;
16866448911SDavid Höppner 			nselector->ks_instance.pstr =
16966448911SDavid Höppner 			    (char *)ks_safe_strdup(optarg);
17066448911SDavid Höppner 			break;
17166448911SDavid Höppner 		case 'n':
17266448911SDavid Höppner 			nselflg = B_TRUE;
17366448911SDavid Höppner 			nselector->ks_name.pstr =
17466448911SDavid Höppner 			    (char *)ks_safe_strdup(optarg);
17566448911SDavid Höppner 			break;
17666448911SDavid Höppner 		case 's':
17766448911SDavid Höppner 			nselflg = B_TRUE;
17866448911SDavid Höppner 			nselector->ks_statistic.pstr =
17966448911SDavid Höppner 			    (char *)ks_safe_strdup(optarg);
18066448911SDavid Höppner 			break;
18166448911SDavid Höppner 		case 'c':
18266448911SDavid Höppner 			g_ks_class.pstr =
18366448911SDavid Höppner 			    (char *)ks_safe_strdup(optarg);
18466448911SDavid Höppner 			break;
18566448911SDavid Höppner 		default:
18666448911SDavid Höppner 			errflg = B_TRUE;
18766448911SDavid Höppner 			break;
18866448911SDavid Höppner 		}
18966448911SDavid Höppner 
19066448911SDavid Höppner 	if (g_qflg && (g_jflg || g_pflg)) {
19166448911SDavid Höppner 		(void) fprintf(stderr, gettext(
19266448911SDavid Höppner 		    "-q and -lpj are mutually exclusive\n"));
19366448911SDavid Höppner 		errflg = B_TRUE;
19466448911SDavid Höppner 	}
19566448911SDavid Höppner 
19666448911SDavid Höppner 	if (errflg) {
19766448911SDavid Höppner 		usage();
19866448911SDavid Höppner 		exit(2);
19966448911SDavid Höppner 	}
20066448911SDavid Höppner 
20166448911SDavid Höppner 	argc -= optind;
20266448911SDavid Höppner 	argv += optind;
20366448911SDavid Höppner 
20466448911SDavid Höppner 	/*
20566448911SDavid Höppner 	 * Consume the rest of the command line. Parsing the
20666448911SDavid Höppner 	 * unnamed command line arguments.
20766448911SDavid Höppner 	 */
20866448911SDavid Höppner 	while (argc--) {
20966448911SDavid Höppner 		errno = 0;
21066448911SDavid Höppner 		tmp = strtoul(*argv, &q, 10);
21166448911SDavid Höppner 		if (tmp == ULONG_MAX && errno == ERANGE) {
21266448911SDavid Höppner 			if (n == 0) {
21366448911SDavid Höppner 				(void) fprintf(stderr, gettext(
21466448911SDavid Höppner 				    "Interval is too large\n"));
21566448911SDavid Höppner 			} else if (n == 1) {
21666448911SDavid Höppner 				(void) fprintf(stderr, gettext(
21766448911SDavid Höppner 				    "Count is too large\n"));
21866448911SDavid Höppner 			}
21966448911SDavid Höppner 			usage();
22066448911SDavid Höppner 			exit(2);
22166448911SDavid Höppner 		}
22266448911SDavid Höppner 
22366448911SDavid Höppner 		if (errno != 0 || *q != '\0') {
22466448911SDavid Höppner 			m = 0;
22566448911SDavid Höppner 			uselector = new_selector();
22666448911SDavid Höppner 			while ((q = (char *)strsep(argv, ":")) != NULL) {
22766448911SDavid Höppner 				m++;
22866448911SDavid Höppner 				if (m > 4) {
22966448911SDavid Höppner 					free(uselector);
23066448911SDavid Höppner 					usage();
23166448911SDavid Höppner 					exit(2);
23266448911SDavid Höppner 				}
23366448911SDavid Höppner 
23466448911SDavid Höppner 				if (*q != '\0') {
23566448911SDavid Höppner 					switch (m) {
23666448911SDavid Höppner 					case 1:
23766448911SDavid Höppner 						uselector->ks_module.pstr =
23866448911SDavid Höppner 						    (char *)ks_safe_strdup(q);
23966448911SDavid Höppner 						break;
24066448911SDavid Höppner 					case 2:
24166448911SDavid Höppner 						uselector->ks_instance.pstr =
24266448911SDavid Höppner 						    (char *)ks_safe_strdup(q);
24366448911SDavid Höppner 						break;
24466448911SDavid Höppner 					case 3:
24566448911SDavid Höppner 						uselector->ks_name.pstr =
24666448911SDavid Höppner 						    (char *)ks_safe_strdup(q);
24766448911SDavid Höppner 						break;
24866448911SDavid Höppner 					case 4:
24966448911SDavid Höppner 						uselector->ks_statistic.pstr =
25066448911SDavid Höppner 						    (char *)ks_safe_strdup(q);
25166448911SDavid Höppner 						break;
25266448911SDavid Höppner 					default:
25366448911SDavid Höppner 						assert(B_FALSE);
25466448911SDavid Höppner 					}
25566448911SDavid Höppner 				}
25666448911SDavid Höppner 			}
25766448911SDavid Höppner 
25866448911SDavid Höppner 			uselflg = B_TRUE;
25966448911SDavid Höppner 			list_insert_tail(&selector_list, uselector);
26066448911SDavid Höppner 		} else {
26166448911SDavid Höppner 			if (tmp < 1) {
26266448911SDavid Höppner 				if (n == 0) {
26366448911SDavid Höppner 					(void) fprintf(stderr, gettext(
26466448911SDavid Höppner 					    "Interval must be an "
26566448911SDavid Höppner 					    "integer >= 1"));
26666448911SDavid Höppner 				} else if (n == 1) {
26766448911SDavid Höppner 					(void) fprintf(stderr, gettext(
26866448911SDavid Höppner 					    "Count must be an integer >= 1"));
26966448911SDavid Höppner 				}
27066448911SDavid Höppner 				usage();
27166448911SDavid Höppner 				exit(2);
27266448911SDavid Höppner 			} else {
27366448911SDavid Höppner 				if (n == 0) {
27466448911SDavid Höppner 					interval = tmp;
27566448911SDavid Höppner 					count = -1;
27666448911SDavid Höppner 				} else if (n == 1) {
27766448911SDavid Höppner 					count = tmp;
27866448911SDavid Höppner 				} else {
27966448911SDavid Höppner 					usage();
28066448911SDavid Höppner 					exit(2);
28166448911SDavid Höppner 				}
28266448911SDavid Höppner 			}
28366448911SDavid Höppner 			n++;
28466448911SDavid Höppner 		}
28566448911SDavid Höppner 		argv++;
28666448911SDavid Höppner 	}
28766448911SDavid Höppner 
28866448911SDavid Höppner 	/*
28966448911SDavid Höppner 	 * Check if we founded a named selector on the cmdline.
29066448911SDavid Höppner 	 */
29166448911SDavid Höppner 	if (uselflg) {
29266448911SDavid Höppner 		if (nselflg) {
29366448911SDavid Höppner 			(void) fprintf(stderr, gettext(
294617413d1SRichard Lowe 			    "[module[:instance[:name[:statistic]]]] and "
29566448911SDavid Höppner 			    "-m -i -n -s are mutually exclusive"));
29666448911SDavid Höppner 			usage();
29766448911SDavid Höppner 			exit(2);
29866448911SDavid Höppner 		} else {
29966448911SDavid Höppner 			free(nselector);
30066448911SDavid Höppner 		}
30166448911SDavid Höppner 	} else {
30266448911SDavid Höppner 		list_insert_tail(&selector_list, nselector);
30366448911SDavid Höppner 	}
30466448911SDavid Höppner 
30566448911SDavid Höppner 	assert(!list_is_empty(&selector_list));
30666448911SDavid Höppner 
30766448911SDavid Höppner 	list_create(&instances_list, sizeof (ks_instance_t),
30866448911SDavid Höppner 	    offsetof(ks_instance_t, ks_next));
30966448911SDavid Höppner 
31066448911SDavid Höppner 	while ((kc = kstat_open()) == NULL) {
31166448911SDavid Höppner 		if (errno == EAGAIN) {
31266448911SDavid Höppner 			(void) poll(NULL, 0, 200);
31366448911SDavid Höppner 		} else {
31466448911SDavid Höppner 			perror("kstat_open");
31566448911SDavid Höppner 			exit(3);
31666448911SDavid Höppner 		}
31766448911SDavid Höppner 	}
31866448911SDavid Höppner 
31966448911SDavid Höppner 	if (count > 1) {
32066448911SDavid Höppner 		if (signal(SIGCONT, cont_handler) == SIG_ERR) {
32166448911SDavid Höppner 			(void) fprintf(stderr, gettext(
32266448911SDavid Höppner 			    "signal failed"));
32366448911SDavid Höppner 			exit(3);
32466448911SDavid Höppner 		}
32566448911SDavid Höppner 	}
32666448911SDavid Höppner 
32766448911SDavid Höppner 	period_n = (hrtime_t)interval * NANOSEC;
32866448911SDavid Höppner 	start_n = gethrtime();
32966448911SDavid Höppner 
33066448911SDavid Höppner 	while (count == -1 || count-- > 0) {
33166448911SDavid Höppner 		ks_instances_read(kc);
33266448911SDavid Höppner 		ks_instances_print();
33366448911SDavid Höppner 
33466448911SDavid Höppner 		if (interval && count) {
33566448911SDavid Höppner 			ks_sleep_until(&start_n, period_n, infinite_cycles,
33666448911SDavid Höppner 			    &caught_cont);
33766448911SDavid Höppner 			(void) kstat_chain_update(kc);
33866448911SDavid Höppner 			(void) putchar('\n');
33966448911SDavid Höppner 		}
34066448911SDavid Höppner 	}
34166448911SDavid Höppner 
34266448911SDavid Höppner 	(void) kstat_close(kc);
34366448911SDavid Höppner 
34466448911SDavid Höppner 	return (g_matched);
34566448911SDavid Höppner }
34666448911SDavid Höppner 
34766448911SDavid Höppner /*
34866448911SDavid Höppner  * Print usage.
34966448911SDavid Höppner  */
35066448911SDavid Höppner static void
usage(void)35166448911SDavid Höppner usage(void)
35266448911SDavid Höppner {
35366448911SDavid Höppner 	(void) fprintf(stderr, gettext(
35466448911SDavid Höppner 	    "Usage:\n"
35566448911SDavid Höppner 	    "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
35666448911SDavid Höppner 	    "      [ -m module ] [ -i instance ] [ -n name ] [ -s statistic ]\n"
35766448911SDavid Höppner 	    "      [ interval [ count ] ]\n"
35866448911SDavid Höppner 	    "kstat [ -Cjlpq ] [ -T d|u ] [ -c class ]\n"
359617413d1SRichard Lowe 	    "      [ module[:instance[:name[:statistic]]] ... ]\n"
36066448911SDavid Höppner 	    "      [ interval [ count ] ]\n"));
36166448911SDavid Höppner }
36266448911SDavid Höppner 
36366448911SDavid Höppner /*
36466448911SDavid Höppner  * Sort compare function.
36566448911SDavid Höppner  */
36666448911SDavid Höppner static int
compare_instances(ks_instance_t * l_arg,ks_instance_t * r_arg)36766448911SDavid Höppner compare_instances(ks_instance_t *l_arg, ks_instance_t *r_arg)
36866448911SDavid Höppner {
36966448911SDavid Höppner 	int	rval;
37066448911SDavid Höppner 
37166448911SDavid Höppner 	rval = strcasecmp(l_arg->ks_module, r_arg->ks_module);
37266448911SDavid Höppner 	if (rval == 0) {
37366448911SDavid Höppner 		if (l_arg->ks_instance == r_arg->ks_instance) {
37466448911SDavid Höppner 			return (strcasecmp(l_arg->ks_name, r_arg->ks_name));
37566448911SDavid Höppner 		} else if (l_arg->ks_instance < r_arg->ks_instance) {
37666448911SDavid Höppner 			return (-1);
37766448911SDavid Höppner 		} else {
37866448911SDavid Höppner 			return (1);
37966448911SDavid Höppner 		}
38066448911SDavid Höppner 	} else {
38166448911SDavid Höppner 		return (rval);
38266448911SDavid Höppner 	}
38366448911SDavid Höppner }
38466448911SDavid Höppner 
38566448911SDavid Höppner static char *
ks_safe_strdup(char * str)38666448911SDavid Höppner ks_safe_strdup(char *str)
38766448911SDavid Höppner {
38866448911SDavid Höppner 	char	*ret;
38966448911SDavid Höppner 
39066448911SDavid Höppner 	if (str == NULL) {
39166448911SDavid Höppner 		return (NULL);
39266448911SDavid Höppner 	}
39366448911SDavid Höppner 
39466448911SDavid Höppner 	while ((ret = strdup(str)) == NULL) {
39566448911SDavid Höppner 		if (errno == EAGAIN) {
39666448911SDavid Höppner 			(void) poll(NULL, 0, 200);
39766448911SDavid Höppner 		} else {
39866448911SDavid Höppner 			perror("strdup");
39966448911SDavid Höppner 			exit(3);
40066448911SDavid Höppner 		}
40166448911SDavid Höppner 	}
40266448911SDavid Höppner 
40366448911SDavid Höppner 	return (ret);
40466448911SDavid Höppner }
40566448911SDavid Höppner 
40666448911SDavid Höppner static void
ks_sleep_until(hrtime_t * wakeup,hrtime_t interval,int forever,int * caught_cont)40766448911SDavid Höppner ks_sleep_until(hrtime_t *wakeup, hrtime_t interval, int forever,
40866448911SDavid Höppner     int *caught_cont)
40966448911SDavid Höppner {
41066448911SDavid Höppner 	hrtime_t	now, pause, pause_left;
41166448911SDavid Höppner 	struct timespec	pause_tv;
41266448911SDavid Höppner 	int		status;
41366448911SDavid Höppner 
41466448911SDavid Höppner 	now = gethrtime();
41566448911SDavid Höppner 	pause = *wakeup + interval - now;
41666448911SDavid Höppner 
41766448911SDavid Höppner 	if (pause <= 0 || pause < (interval / 4)) {
41866448911SDavid Höppner 		if (forever || *caught_cont) {
41966448911SDavid Höppner 			*wakeup = now + interval;
42066448911SDavid Höppner 			pause = interval;
42166448911SDavid Höppner 		} else {
42266448911SDavid Höppner 			pause = interval / 2;
42366448911SDavid Höppner 			*wakeup += interval;
42466448911SDavid Höppner 		}
42566448911SDavid Höppner 	} else {
42666448911SDavid Höppner 		*wakeup += interval;
42766448911SDavid Höppner 	}
42866448911SDavid Höppner 
42966448911SDavid Höppner 	if (pause < 1000) {
43066448911SDavid Höppner 		return;
43166448911SDavid Höppner 	}
43266448911SDavid Höppner 
43366448911SDavid Höppner 	pause_left = pause;
43466448911SDavid Höppner 	do {
43566448911SDavid Höppner 		pause_tv.tv_sec = pause_left / NANOSEC;
43666448911SDavid Höppner 		pause_tv.tv_nsec = pause_left % NANOSEC;
43766448911SDavid Höppner 		status = nanosleep(&pause_tv, (struct timespec *)NULL);
43866448911SDavid Höppner 		if (status < 0) {
43966448911SDavid Höppner 			if (errno == EINTR) {
44066448911SDavid Höppner 				now = gethrtime();
44166448911SDavid Höppner 				pause_left = *wakeup - now;
44266448911SDavid Höppner 				if (pause_left < 1000) {
44366448911SDavid Höppner 					return;
44466448911SDavid Höppner 				}
44566448911SDavid Höppner 			} else {
44666448911SDavid Höppner 				perror("nanosleep");
44766448911SDavid Höppner 				exit(3);
44866448911SDavid Höppner 			}
44966448911SDavid Höppner 		}
45066448911SDavid Höppner 	} while (status != 0);
45166448911SDavid Höppner }
45266448911SDavid Höppner 
45366448911SDavid Höppner /*
45466448911SDavid Höppner  * Inserts an instance in the per selector list.
45566448911SDavid Höppner  */
45666448911SDavid Höppner static void
nvpair_insert(ks_instance_t * ksi,char * name,ks_value_t * value,uchar_t data_type)45766448911SDavid Höppner nvpair_insert(ks_instance_t *ksi, char *name, ks_value_t *value,
45866448911SDavid Höppner     uchar_t data_type)
45966448911SDavid Höppner {
46066448911SDavid Höppner 	ks_nvpair_t	*instance;
46166448911SDavid Höppner 	ks_nvpair_t	*tmp;
46266448911SDavid Höppner 
46366448911SDavid Höppner 	instance = (ks_nvpair_t *)malloc(sizeof (ks_nvpair_t));
46466448911SDavid Höppner 	if (instance == NULL) {
46566448911SDavid Höppner 		perror("malloc");
46666448911SDavid Höppner 		exit(3);
46766448911SDavid Höppner 	}
46866448911SDavid Höppner 
46966448911SDavid Höppner 	(void) strlcpy(instance->name, name, KSTAT_STRLEN);
47066448911SDavid Höppner 	(void) memcpy(&instance->value, value, sizeof (ks_value_t));
47166448911SDavid Höppner 	instance->data_type = data_type;
47266448911SDavid Höppner 
47366448911SDavid Höppner 	tmp = list_head(&ksi->ks_nvlist);
47466448911SDavid Höppner 	while (tmp != NULL && strcasecmp(instance->name, tmp->name) > 0)
47566448911SDavid Höppner 		tmp = list_next(&ksi->ks_nvlist, tmp);
47666448911SDavid Höppner 
47766448911SDavid Höppner 	list_insert_before(&ksi->ks_nvlist, tmp, instance);
47866448911SDavid Höppner }
47966448911SDavid Höppner 
48066448911SDavid Höppner /*
48166448911SDavid Höppner  * Allocates a new all-matching selector.
48266448911SDavid Höppner  */
48366448911SDavid Höppner static ks_selector_t *
new_selector(void)48466448911SDavid Höppner new_selector(void)
48566448911SDavid Höppner {
48666448911SDavid Höppner 	ks_selector_t	*selector;
48766448911SDavid Höppner 
48866448911SDavid Höppner 	selector = (ks_selector_t *)malloc(sizeof (ks_selector_t));
48966448911SDavid Höppner 	if (selector == NULL) {
49066448911SDavid Höppner 		perror("malloc");
49166448911SDavid Höppner 		exit(3);
49266448911SDavid Höppner 	}
49366448911SDavid Höppner 
49466448911SDavid Höppner 	list_link_init(&selector->ks_next);
49566448911SDavid Höppner 
49666448911SDavid Höppner 	selector->ks_module.pstr = "*";
49766448911SDavid Höppner 	selector->ks_instance.pstr = "*";
49866448911SDavid Höppner 	selector->ks_name.pstr = "*";
49966448911SDavid Höppner 	selector->ks_statistic.pstr = "*";
50066448911SDavid Höppner 
50166448911SDavid Höppner 	return (selector);
50266448911SDavid Höppner }
50366448911SDavid Höppner 
50466448911SDavid Höppner /*
50566448911SDavid Höppner  * This function was taken from the perl kstat module code - please
50666448911SDavid Höppner  * see for further comments there.
50766448911SDavid Höppner  */
50866448911SDavid Höppner static kstat_raw_reader_t
lookup_raw_kstat_fn(char * module,char * name)50966448911SDavid Höppner lookup_raw_kstat_fn(char *module, char *name)
51066448911SDavid Höppner {
51166448911SDavid Höppner 	char		key[KSTAT_STRLEN * 2];
51266448911SDavid Höppner 	register char 	*f, *t;
51366448911SDavid Höppner 	int		n = 0;
51466448911SDavid Höppner 
51566448911SDavid Höppner 	for (f = module, t = key; *f != '\0'; f++, t++) {
51666448911SDavid Höppner 		while (*f != '\0' && isdigit(*f))
51766448911SDavid Höppner 			f++;
51866448911SDavid Höppner 		*t = *f;
51966448911SDavid Höppner 	}
52066448911SDavid Höppner 	*t++ = ':';
52166448911SDavid Höppner 
52266448911SDavid Höppner 	for (f = name; *f != '\0'; f++, t++) {
52366448911SDavid Höppner 		while (*f != '\0' && isdigit(*f))
52466448911SDavid Höppner 			f++;
52566448911SDavid Höppner 		*t = *f;
52666448911SDavid Höppner 	}
52766448911SDavid Höppner 	*t = '\0';
52866448911SDavid Höppner 
52966448911SDavid Höppner 	while (ks_raw_lookup[n].fn != NULL) {
53066448911SDavid Höppner 		if (strncmp(ks_raw_lookup[n].name, key, strlen(key)) == 0)
53166448911SDavid Höppner 			return (ks_raw_lookup[n].fn);
53266448911SDavid Höppner 		n++;
53366448911SDavid Höppner 	}
53466448911SDavid Höppner 
53566448911SDavid Höppner 	return (0);
53666448911SDavid Höppner }
53766448911SDavid Höppner 
53866448911SDavid Höppner /*
53966448911SDavid Höppner  * Match a string against a shell glob or extended regular expression.
54066448911SDavid Höppner  */
54166448911SDavid Höppner static boolean_t
ks_match(const char * str,ks_pattern_t * pattern)54266448911SDavid Höppner ks_match(const char *str, ks_pattern_t *pattern)
54366448911SDavid Höppner {
54466448911SDavid Höppner 	int	regcode;
54566448911SDavid Höppner 	char	*regstr;
54666448911SDavid Höppner 	char	*errbuf;
54766448911SDavid Höppner 	size_t	bufsz;
54866448911SDavid Höppner 
54966448911SDavid Höppner 	if (pattern->pstr != NULL && gmatch(pattern->pstr, "/*/") != 0) {
55066448911SDavid Höppner 		/* All regex patterns are strdup'd copies */
55166448911SDavid Höppner 		regstr = pattern->pstr + 1;
55266448911SDavid Höppner 		*(strrchr(regstr, '/')) = '\0';
55366448911SDavid Höppner 
55466448911SDavid Höppner 		regcode = regcomp(&pattern->preg, regstr,
55566448911SDavid Höppner 		    REG_EXTENDED | REG_NOSUB);
55666448911SDavid Höppner 		if (regcode != 0) {
55766448911SDavid Höppner 			bufsz = regerror(regcode, NULL, NULL, 0);
55866448911SDavid Höppner 			if (bufsz != 0) {
55966448911SDavid Höppner 				errbuf = malloc(bufsz);
56066448911SDavid Höppner 				if (errbuf == NULL) {
56166448911SDavid Höppner 					perror("malloc");
56266448911SDavid Höppner 					exit(3);
56366448911SDavid Höppner 				}
56466448911SDavid Höppner 				(void) regerror(regcode, NULL, errbuf, bufsz);
56566448911SDavid Höppner 				(void) fprintf(stderr, "kstat: %s\n", errbuf);
56666448911SDavid Höppner 			}
56766448911SDavid Höppner 			usage();
56866448911SDavid Höppner 			exit(2);
56966448911SDavid Höppner 		}
57066448911SDavid Höppner 
57166448911SDavid Höppner 		pattern->pstr = NULL;
57266448911SDavid Höppner 	}
57366448911SDavid Höppner 
57466448911SDavid Höppner 	if (pattern->pstr == NULL) {
57566448911SDavid Höppner 		return (regexec(&pattern->preg, str, 0, NULL, 0) == 0);
57666448911SDavid Höppner 	}
57766448911SDavid Höppner 
57866448911SDavid Höppner 	return ((gmatch(str, pattern->pstr) != 0));
57966448911SDavid Höppner }
58066448911SDavid Höppner 
58166448911SDavid Höppner /*
58266448911SDavid Höppner  * Iterate over all kernel statistics and save matches.
58366448911SDavid Höppner  */
58466448911SDavid Höppner static void
ks_instances_read(kstat_ctl_t * kc)58566448911SDavid Höppner ks_instances_read(kstat_ctl_t *kc)
58666448911SDavid Höppner {
58766448911SDavid Höppner 	kstat_raw_reader_t save_raw = NULL;
58866448911SDavid Höppner 	kid_t		id;
58966448911SDavid Höppner 	ks_selector_t	*selector;
59066448911SDavid Höppner 	ks_instance_t	*ksi;
59166448911SDavid Höppner 	ks_instance_t	*tmp;
59266448911SDavid Höppner 	kstat_t		*kp;
59366448911SDavid Höppner 	boolean_t	skip;
59466448911SDavid Höppner 
59566448911SDavid Höppner 	for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) {
59666448911SDavid Höppner 		/* Don't bother storing the kstat headers */
59766448911SDavid Höppner 		if (strncmp(kp->ks_name, "kstat_", 6) == 0) {
59866448911SDavid Höppner 			continue;
59966448911SDavid Höppner 		}
60066448911SDavid Höppner 
60166448911SDavid Höppner 		/* Don't bother storing raw stats we don't understand */
60266448911SDavid Höppner 		if (kp->ks_type == KSTAT_TYPE_RAW) {
60366448911SDavid Höppner 			save_raw = lookup_raw_kstat_fn(kp->ks_module,
60466448911SDavid Höppner 			    kp->ks_name);
60566448911SDavid Höppner 			if (save_raw == NULL) {
60666448911SDavid Höppner #ifdef REPORT_UNKNOWN
60766448911SDavid Höppner 				(void) fprintf(stderr,
60866448911SDavid Höppner 				    "Unknown kstat type %s:%d:%s - "
60966448911SDavid Höppner 				    "%d of size %d\n", kp->ks_module,
61066448911SDavid Höppner 				    kp->ks_instance, kp->ks_name,
61166448911SDavid Höppner 				    kp->ks_ndata, kp->ks_data_size);
61266448911SDavid Höppner #endif
61366448911SDavid Höppner 				continue;
61466448911SDavid Höppner 			}
61566448911SDavid Höppner 		}
61666448911SDavid Höppner 
61766448911SDavid Höppner 		/*
61866448911SDavid Höppner 		 * Iterate over the list of selectors and skip
61966448911SDavid Höppner 		 * instances we dont want. We filter for statistics
62066448911SDavid Höppner 		 * later, as we dont know them yet.
62166448911SDavid Höppner 		 */
62266448911SDavid Höppner 		skip = B_TRUE;
62366448911SDavid Höppner 		selector = list_head(&selector_list);
62466448911SDavid Höppner 		while (selector != NULL) {
625*9736aecdSBryan Cantrill 			if (ks_match(kp->ks_module, &selector->ks_module) &&
62666448911SDavid Höppner 			    ks_match(kp->ks_name, &selector->ks_name)) {
62766448911SDavid Höppner 				skip = B_FALSE;
62866448911SDavid Höppner 				break;
62966448911SDavid Höppner 			}
63066448911SDavid Höppner 			selector = list_next(&selector_list, selector);
63166448911SDavid Höppner 		}
63266448911SDavid Höppner 
63366448911SDavid Höppner 		if (skip) {
63466448911SDavid Höppner 			continue;
63566448911SDavid Höppner 		}
63666448911SDavid Höppner 
63766448911SDavid Höppner 		/*
63866448911SDavid Höppner 		 * Allocate a new instance and fill in the values
63966448911SDavid Höppner 		 * we know so far.
64066448911SDavid Höppner 		 */
64166448911SDavid Höppner 		ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t));
64266448911SDavid Höppner 		if (ksi == NULL) {
64366448911SDavid Höppner 			perror("malloc");
64466448911SDavid Höppner 			exit(3);
64566448911SDavid Höppner 		}
64666448911SDavid Höppner 
64766448911SDavid Höppner 		list_link_init(&ksi->ks_next);
64866448911SDavid Höppner 
64966448911SDavid Höppner 		(void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN);
65066448911SDavid Höppner 		(void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN);
65166448911SDavid Höppner 		(void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN);
65266448911SDavid Höppner 
65366448911SDavid Höppner 		ksi->ks_instance = kp->ks_instance;
65466448911SDavid Höppner 		ksi->ks_snaptime = kp->ks_snaptime;
65566448911SDavid Höppner 		ksi->ks_type = kp->ks_type;
65666448911SDavid Höppner 
65766448911SDavid Höppner 		list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t),
65866448911SDavid Höppner 		    offsetof(ks_nvpair_t, nv_next));
65966448911SDavid Höppner 
66066448911SDavid Höppner 		SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime);
66166448911SDavid Höppner 		SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime);
66266448911SDavid Höppner 		if (g_pflg) {
66366448911SDavid Höppner 			SAVE_STRING_X(ksi, "class", kp->ks_class);
66466448911SDavid Höppner 		}
66566448911SDavid Höppner 
66666448911SDavid Höppner 		/* Insert this instance into a sorted list */
66766448911SDavid Höppner 		tmp = list_head(&instances_list);
66866448911SDavid Höppner 		while (tmp != NULL && compare_instances(ksi, tmp) > 0)
66966448911SDavid Höppner 			tmp = list_next(&instances_list, tmp);
67066448911SDavid Höppner 
67166448911SDavid Höppner 		list_insert_before(&instances_list, tmp, ksi);
67266448911SDavid Höppner 
67366448911SDavid Höppner 		/* Read the actual statistics */
67466448911SDavid Höppner 		id = kstat_read(kc, kp, NULL);
67566448911SDavid Höppner 		if (id == -1) {
67666448911SDavid Höppner #ifdef REPORT_UNKNOWN
67766448911SDavid Höppner 			perror("kstat_read");
67866448911SDavid Höppner #endif
67966448911SDavid Höppner 			continue;
68066448911SDavid Höppner 		}
68166448911SDavid Höppner 
68266448911SDavid Höppner 		switch (kp->ks_type) {
68366448911SDavid Höppner 		case KSTAT_TYPE_RAW:
68466448911SDavid Höppner 			save_raw(kp, ksi);
68566448911SDavid Höppner 			break;
68666448911SDavid Höppner 		case KSTAT_TYPE_NAMED:
68766448911SDavid Höppner 			save_named(kp, ksi);
68866448911SDavid Höppner 			break;
68966448911SDavid Höppner 		case KSTAT_TYPE_INTR:
69066448911SDavid Höppner 			save_intr(kp, ksi);
69166448911SDavid Höppner 			break;
69266448911SDavid Höppner 		case KSTAT_TYPE_IO:
69366448911SDavid Höppner 			save_io(kp, ksi);
69466448911SDavid Höppner 			break;
69566448911SDavid Höppner 		case KSTAT_TYPE_TIMER:
69666448911SDavid Höppner 			save_timer(kp, ksi);
69766448911SDavid Höppner 			break;
69866448911SDavid Höppner 		default:
69966448911SDavid Höppner 			assert(B_FALSE); /* Invalid type */
70066448911SDavid Höppner 			break;
70166448911SDavid Höppner 		}
70266448911SDavid Höppner 	}
70366448911SDavid Höppner }
70466448911SDavid Höppner 
70566448911SDavid Höppner /*
70666448911SDavid Höppner  * Print the value of a name-value pair.
70766448911SDavid Höppner  */
70866448911SDavid Höppner static void
ks_value_print(ks_nvpair_t * nvpair)70966448911SDavid Höppner ks_value_print(ks_nvpair_t *nvpair)
71066448911SDavid Höppner {
71166448911SDavid Höppner 	switch (nvpair->data_type) {
71266448911SDavid Höppner 	case KSTAT_DATA_CHAR:
71366448911SDavid Höppner 		(void) fprintf(stdout, "%s", nvpair->value.c);
71466448911SDavid Höppner 		break;
71566448911SDavid Höppner 	case KSTAT_DATA_INT32:
71666448911SDavid Höppner 		(void) fprintf(stdout, "%d", nvpair->value.i32);
71766448911SDavid Höppner 		break;
71866448911SDavid Höppner 	case KSTAT_DATA_UINT32:
71966448911SDavid Höppner 		(void) fprintf(stdout, "%u", nvpair->value.ui32);
72066448911SDavid Höppner 		break;
72166448911SDavid Höppner 	case KSTAT_DATA_INT64:
72266448911SDavid Höppner 		(void) fprintf(stdout, "%lld", nvpair->value.i64);
72366448911SDavid Höppner 		break;
72466448911SDavid Höppner 	case KSTAT_DATA_UINT64:
72566448911SDavid Höppner 		(void) fprintf(stdout, "%llu", nvpair->value.ui64);
72666448911SDavid Höppner 		break;
72766448911SDavid Höppner 	case KSTAT_DATA_STRING:
72866448911SDavid Höppner 		(void) fprintf(stdout, "%s", KSTAT_NAMED_STR_PTR(nvpair));
72966448911SDavid Höppner 		break;
73066448911SDavid Höppner 	case KSTAT_DATA_HRTIME:
73166448911SDavid Höppner 		if (nvpair->value.ui64 == 0)
73266448911SDavid Höppner 			(void) fprintf(stdout, "0");
73366448911SDavid Höppner 		else
73466448911SDavid Höppner 			(void) fprintf(stdout, "%.9f",
73566448911SDavid Höppner 			    nvpair->value.ui64 / 1000000000.0);
73666448911SDavid Höppner 		break;
73766448911SDavid Höppner 	default:
73866448911SDavid Höppner 		assert(B_FALSE);
73966448911SDavid Höppner 	}
74066448911SDavid Höppner }
74166448911SDavid Höppner 
74266448911SDavid Höppner /*
74366448911SDavid Höppner  * Print a single instance.
74466448911SDavid Höppner  */
74566448911SDavid Höppner static void
ks_instance_print(ks_instance_t * ksi,ks_nvpair_t * nvpair)74666448911SDavid Höppner ks_instance_print(ks_instance_t *ksi, ks_nvpair_t *nvpair)
74766448911SDavid Höppner {
74866448911SDavid Höppner 	if (g_headerflg) {
74966448911SDavid Höppner 		if (!g_pflg) {
75066448911SDavid Höppner 			(void) fprintf(stdout, DFLT_FMT,
75166448911SDavid Höppner 			    ksi->ks_module, ksi->ks_instance,
75266448911SDavid Höppner 			    ksi->ks_name, ksi->ks_class);
75366448911SDavid Höppner 		}
75466448911SDavid Höppner 		g_headerflg = B_FALSE;
75566448911SDavid Höppner 	}
75666448911SDavid Höppner 
75766448911SDavid Höppner 	if (g_pflg) {
75866448911SDavid Höppner 		(void) fprintf(stdout, KS_PFMT,
75966448911SDavid Höppner 		    ksi->ks_module, ksi->ks_instance,
76066448911SDavid Höppner 		    ksi->ks_name, nvpair->name);
76166448911SDavid Höppner 		if (!g_lflg) {
76266448911SDavid Höppner 			(void) putchar(g_cflg ? ':': '\t');
76366448911SDavid Höppner 			ks_value_print(nvpair);
76466448911SDavid Höppner 		}
76566448911SDavid Höppner 	} else {
76666448911SDavid Höppner 		(void) fprintf(stdout, KS_DFMT, nvpair->name);
76766448911SDavid Höppner 		ks_value_print(nvpair);
76866448911SDavid Höppner 	}
76966448911SDavid Höppner 
77066448911SDavid Höppner 	(void) putchar('\n');
77166448911SDavid Höppner }
77266448911SDavid Höppner 
77366448911SDavid Höppner /*
77466448911SDavid Höppner  * Print a single instance in JSON format.
77566448911SDavid Höppner  */
77666448911SDavid Höppner static void
ks_instance_print_json(ks_instance_t * ksi,ks_nvpair_t * nvpair)77766448911SDavid Höppner ks_instance_print_json(ks_instance_t *ksi, ks_nvpair_t *nvpair)
77866448911SDavid Höppner {
77966448911SDavid Höppner 	if (g_headerflg) {
78066448911SDavid Höppner 		(void) fprintf(stdout, JSON_FMT,
78166448911SDavid Höppner 		    ksi->ks_module, ksi->ks_instance,
78266448911SDavid Höppner 		    ksi->ks_name, ksi->ks_class,
78366448911SDavid Höppner 		    ksi->ks_type);
78466448911SDavid Höppner 
78566448911SDavid Höppner 		if (ksi->ks_snaptime == 0)
78666448911SDavid Höppner 			(void) fprintf(stdout, "\t\"snaptime\": 0,\n");
78766448911SDavid Höppner 		else
78866448911SDavid Höppner 			(void) fprintf(stdout, "\t\"snaptime\": %.9f,\n",
78966448911SDavid Höppner 			    ksi->ks_snaptime / 1000000000.0);
79066448911SDavid Höppner 
79166448911SDavid Höppner 		(void) fprintf(stdout, "\t\"data\": {\n");
79266448911SDavid Höppner 
79366448911SDavid Höppner 		g_headerflg = B_FALSE;
79466448911SDavid Höppner 	}
79566448911SDavid Höppner 
79666448911SDavid Höppner 	(void) fprintf(stdout, KS_JFMT, nvpair->name);
79766448911SDavid Höppner 	if (nvpair->data_type == KSTAT_DATA_STRING) {
79866448911SDavid Höppner 		(void) putchar('\"');
79966448911SDavid Höppner 		ks_value_print(nvpair);
80066448911SDavid Höppner 		(void) putchar('\"');
80166448911SDavid Höppner 	} else {
80266448911SDavid Höppner 		ks_value_print(nvpair);
80366448911SDavid Höppner 	}
80466448911SDavid Höppner 	if (nvpair != list_tail(&ksi->ks_nvlist))
80566448911SDavid Höppner 		(void) putchar(',');
80666448911SDavid Höppner 
80766448911SDavid Höppner 	(void) putchar('\n');
80866448911SDavid Höppner }
80966448911SDavid Höppner 
81066448911SDavid Höppner /*
81166448911SDavid Höppner  * Print all instances.
81266448911SDavid Höppner  */
81366448911SDavid Höppner static void
ks_instances_print(void)81466448911SDavid Höppner ks_instances_print(void)
81566448911SDavid Höppner {
81666448911SDavid Höppner 	ks_selector_t	*selector;
81766448911SDavid Höppner 	ks_instance_t	*ksi, *ktmp;
81866448911SDavid Höppner 	ks_nvpair_t	*nvpair, *ntmp;
81966448911SDavid Höppner 	void		(*ks_print_fn)(ks_instance_t *, ks_nvpair_t *);
82066448911SDavid Höppner 	char		*ks_number;
82166448911SDavid Höppner 
82266448911SDavid Höppner 	if (g_timestamp_fmt != NODATE)
82366448911SDavid Höppner 		print_timestamp(g_timestamp_fmt);
82466448911SDavid Höppner 
82566448911SDavid Höppner 	if (g_jflg) {
82666448911SDavid Höppner 		ks_print_fn = &ks_instance_print_json;
82766448911SDavid Höppner 		(void) putchar('[');
82866448911SDavid Höppner 	} else {
82966448911SDavid Höppner 		ks_print_fn = &ks_instance_print;
83066448911SDavid Höppner 	}
83166448911SDavid Höppner 
83266448911SDavid Höppner 	/* Iterate over each selector */
83366448911SDavid Höppner 	selector = list_head(&selector_list);
83466448911SDavid Höppner 	while (selector != NULL) {
83566448911SDavid Höppner 
83666448911SDavid Höppner 		/* Iterate over each instance */
83766448911SDavid Höppner 		for (ksi = list_head(&instances_list); ksi != NULL;
83866448911SDavid Höppner 		    ksi = list_next(&instances_list, ksi)) {
83966448911SDavid Höppner 
84066448911SDavid Höppner 			(void) asprintf(&ks_number, "%d", ksi->ks_instance);
84166448911SDavid Höppner 			if (!(ks_match(ksi->ks_module, &selector->ks_module) &&
84266448911SDavid Höppner 			    ks_match(ksi->ks_name, &selector->ks_name) &&
84366448911SDavid Höppner 			    ks_match(ks_number, &selector->ks_instance) &&
84466448911SDavid Höppner 			    ks_match(ksi->ks_class, &g_ks_class))) {
84566448911SDavid Höppner 				free(ks_number);
84666448911SDavid Höppner 				continue;
84766448911SDavid Höppner 			}
84866448911SDavid Höppner 
84966448911SDavid Höppner 			free(ks_number);
85066448911SDavid Höppner 
85166448911SDavid Höppner 			/* Finally iterate over each statistic */
85266448911SDavid Höppner 			g_headerflg = B_TRUE;
85366448911SDavid Höppner 			for (nvpair = list_head(&ksi->ks_nvlist);
85466448911SDavid Höppner 			    nvpair != NULL;
85566448911SDavid Höppner 			    nvpair = list_next(&ksi->ks_nvlist, nvpair)) {
85666448911SDavid Höppner 				if (!ks_match(nvpair->name,
85766448911SDavid Höppner 				    &selector->ks_statistic))
85866448911SDavid Höppner 					continue;
85966448911SDavid Höppner 
86066448911SDavid Höppner 				g_matched = 0;
86166448911SDavid Höppner 				if (!g_qflg)
86266448911SDavid Höppner 					(*ks_print_fn)(ksi, nvpair);
86366448911SDavid Höppner 			}
86466448911SDavid Höppner 
86566448911SDavid Höppner 			if (!g_headerflg) {
86666448911SDavid Höppner 				if (g_jflg) {
86766448911SDavid Höppner 					(void) fprintf(stdout, "\t}\n}");
86866448911SDavid Höppner 					if (ksi != list_tail(&instances_list))
86966448911SDavid Höppner 						(void) putchar(',');
87066448911SDavid Höppner 				} else if (!g_pflg) {
87166448911SDavid Höppner 					(void) putchar('\n');
87266448911SDavid Höppner 				}
87366448911SDavid Höppner 			}
87466448911SDavid Höppner 		}
87566448911SDavid Höppner 
87666448911SDavid Höppner 		selector = list_next(&selector_list, selector);
87766448911SDavid Höppner 	}
87866448911SDavid Höppner 
87966448911SDavid Höppner 	if (g_jflg)
88066448911SDavid Höppner 		(void) fprintf(stdout, "]\n");
88166448911SDavid Höppner 
88266448911SDavid Höppner 	(void) fflush(stdout);
88366448911SDavid Höppner 
88466448911SDavid Höppner 	/* Free the instances list */
88566448911SDavid Höppner 	ksi = list_head(&instances_list);
88666448911SDavid Höppner 	while (ksi != NULL) {
88766448911SDavid Höppner 		nvpair = list_head(&ksi->ks_nvlist);
88866448911SDavid Höppner 		while (nvpair != NULL) {
88966448911SDavid Höppner 			ntmp = nvpair;
89066448911SDavid Höppner 			nvpair = list_next(&ksi->ks_nvlist, nvpair);
89166448911SDavid Höppner 			list_remove(&ksi->ks_nvlist, ntmp);
89266448911SDavid Höppner 			if (ntmp->data_type == KSTAT_DATA_STRING)
89366448911SDavid Höppner 				free(ntmp->value.str.addr.ptr);
89466448911SDavid Höppner 			free(ntmp);
89566448911SDavid Höppner 		}
89666448911SDavid Höppner 
89766448911SDavid Höppner 		ktmp = ksi;
89866448911SDavid Höppner 		ksi = list_next(&instances_list, ksi);
89966448911SDavid Höppner 		list_remove(&instances_list, ktmp);
90066448911SDavid Höppner 		list_destroy(&ktmp->ks_nvlist);
90166448911SDavid Höppner 		free(ktmp);
90266448911SDavid Höppner 	}
90366448911SDavid Höppner }
90466448911SDavid Höppner 
90566448911SDavid Höppner static void
save_cpu_stat(kstat_t * kp,ks_instance_t * ksi)90666448911SDavid Höppner save_cpu_stat(kstat_t *kp, ks_instance_t *ksi)
90766448911SDavid Höppner {
90866448911SDavid Höppner 	cpu_stat_t	*stat;
90966448911SDavid Höppner 	cpu_sysinfo_t	*sysinfo;
91066448911SDavid Höppner 	cpu_syswait_t	*syswait;
91166448911SDavid Höppner 	cpu_vminfo_t	*vminfo;
91266448911SDavid Höppner 
91366448911SDavid Höppner 	stat = (cpu_stat_t *)(kp->ks_data);
91466448911SDavid Höppner 	sysinfo = &stat->cpu_sysinfo;
91566448911SDavid Höppner 	syswait = &stat->cpu_syswait;
91666448911SDavid Höppner 	vminfo  = &stat->cpu_vminfo;
91766448911SDavid Höppner 
91866448911SDavid Höppner 	SAVE_UINT32_X(ksi, "idle", sysinfo->cpu[CPU_IDLE]);
91966448911SDavid Höppner 	SAVE_UINT32_X(ksi, "user", sysinfo->cpu[CPU_USER]);
92066448911SDavid Höppner 	SAVE_UINT32_X(ksi, "kernel", sysinfo->cpu[CPU_KERNEL]);
92166448911SDavid Höppner 	SAVE_UINT32_X(ksi, "wait", sysinfo->cpu[CPU_WAIT]);
9225918f984SRichard Lowe 	SAVE_UINT32_X(ksi, "wait_io", sysinfo->wait[W_IO]);
9235918f984SRichard Lowe 	SAVE_UINT32_X(ksi, "wait_swap", sysinfo->wait[W_SWAP]);
9245918f984SRichard Lowe 	SAVE_UINT32_X(ksi, "wait_pio", sysinfo->wait[W_PIO]);
92566448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, bread);
92666448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, bwrite);
92766448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, lread);
92866448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, lwrite);
92966448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, phread);
93066448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, phwrite);
93166448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, pswitch);
93266448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, trap);
93366448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, intr);
93466448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, syscall);
93566448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, sysread);
93666448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, syswrite);
93766448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, sysfork);
93866448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, sysvfork);
93966448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, sysexec);
94066448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, readch);
94166448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, writech);
94266448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, rcvint);
94366448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, xmtint);
94466448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, mdmint);
94566448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, rawch);
94666448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, canch);
94766448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, outch);
94866448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, msg);
94966448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, sema);
95066448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, namei);
95166448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, ufsiget);
95266448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, ufsdirblk);
95366448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, ufsipage);
95466448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, ufsinopage);
95566448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, inodeovf);
95666448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, fileovf);
95766448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, procovf);
95866448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, intrthread);
95966448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, intrblk);
96066448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, idlethread);
96166448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, inv_swtch);
96266448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, nthreads);
96366448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, cpumigrate);
96466448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, xcalls);
96566448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, mutex_adenters);
96666448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, rw_rdfails);
96766448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, rw_wrfails);
96866448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, modload);
96966448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, modunload);
97066448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, bawrite);
97166448911SDavid Höppner #ifdef	STATISTICS	/* see header file */
97266448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, rw_enters);
97366448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, win_uo_cnt);
97466448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, win_uu_cnt);
97566448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, win_so_cnt);
97666448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, win_su_cnt);
97766448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, win_suo_cnt);
97866448911SDavid Höppner #endif
97966448911SDavid Höppner 
98066448911SDavid Höppner 	SAVE_INT32(ksi, syswait, iowait);
98166448911SDavid Höppner 	SAVE_INT32(ksi, syswait, swap);
98266448911SDavid Höppner 	SAVE_INT32(ksi, syswait, physio);
98366448911SDavid Höppner 
98466448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgrec);
98566448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgfrec);
98666448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgin);
98766448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgpgin);
98866448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgout);
98966448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgpgout);
99066448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, swapin);
99166448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgswapin);
99266448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, swapout);
99366448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgswapout);
99466448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, zfod);
99566448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, dfree);
99666448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, scan);
99766448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, rev);
99866448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, hat_fault);
99966448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, as_fault);
100066448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, maj_fault);
100166448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, cow_fault);
100266448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, prot_fault);
100366448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, softlock);
100466448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, kernel_asflt);
100566448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, pgrrun);
100666448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, execpgin);
100766448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, execpgout);
100866448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, execfree);
100966448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, anonpgin);
101066448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, anonpgout);
101166448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, anonfree);
101266448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, fspgin);
101366448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, fspgout);
101466448911SDavid Höppner 	SAVE_UINT32(ksi, vminfo, fsfree);
101566448911SDavid Höppner }
101666448911SDavid Höppner 
101766448911SDavid Höppner static void
save_var(kstat_t * kp,ks_instance_t * ksi)101866448911SDavid Höppner save_var(kstat_t *kp, ks_instance_t *ksi)
101966448911SDavid Höppner {
102066448911SDavid Höppner 	struct var	*var = (struct var *)(kp->ks_data);
102166448911SDavid Höppner 
102266448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (struct var));
102366448911SDavid Höppner 
102466448911SDavid Höppner 	SAVE_INT32(ksi, var, v_buf);
102566448911SDavid Höppner 	SAVE_INT32(ksi, var, v_call);
102666448911SDavid Höppner 	SAVE_INT32(ksi, var, v_proc);
102766448911SDavid Höppner 	SAVE_INT32(ksi, var, v_maxupttl);
102866448911SDavid Höppner 	SAVE_INT32(ksi, var, v_nglobpris);
102966448911SDavid Höppner 	SAVE_INT32(ksi, var, v_maxsyspri);
103066448911SDavid Höppner 	SAVE_INT32(ksi, var, v_clist);
103166448911SDavid Höppner 	SAVE_INT32(ksi, var, v_maxup);
103266448911SDavid Höppner 	SAVE_INT32(ksi, var, v_hbuf);
103366448911SDavid Höppner 	SAVE_INT32(ksi, var, v_hmask);
103466448911SDavid Höppner 	SAVE_INT32(ksi, var, v_pbuf);
103566448911SDavid Höppner 	SAVE_INT32(ksi, var, v_sptmap);
103666448911SDavid Höppner 	SAVE_INT32(ksi, var, v_maxpmem);
103766448911SDavid Höppner 	SAVE_INT32(ksi, var, v_autoup);
103866448911SDavid Höppner 	SAVE_INT32(ksi, var, v_bufhwm);
103966448911SDavid Höppner }
104066448911SDavid Höppner 
104166448911SDavid Höppner static void
save_ncstats(kstat_t * kp,ks_instance_t * ksi)104266448911SDavid Höppner save_ncstats(kstat_t *kp, ks_instance_t *ksi)
104366448911SDavid Höppner {
104466448911SDavid Höppner 	struct ncstats	*ncstats = (struct ncstats *)(kp->ks_data);
104566448911SDavid Höppner 
104666448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (struct ncstats));
104766448911SDavid Höppner 
104866448911SDavid Höppner 	SAVE_INT32(ksi, ncstats, hits);
104966448911SDavid Höppner 	SAVE_INT32(ksi, ncstats, misses);
105066448911SDavid Höppner 	SAVE_INT32(ksi, ncstats, enters);
105166448911SDavid Höppner 	SAVE_INT32(ksi, ncstats, dbl_enters);
105266448911SDavid Höppner 	SAVE_INT32(ksi, ncstats, long_enter);
105366448911SDavid Höppner 	SAVE_INT32(ksi, ncstats, long_look);
105466448911SDavid Höppner 	SAVE_INT32(ksi, ncstats, move_to_front);
105566448911SDavid Höppner 	SAVE_INT32(ksi, ncstats, purges);
105666448911SDavid Höppner }
105766448911SDavid Höppner 
105866448911SDavid Höppner static void
save_sysinfo(kstat_t * kp,ks_instance_t * ksi)105966448911SDavid Höppner save_sysinfo(kstat_t *kp, ks_instance_t *ksi)
106066448911SDavid Höppner {
106166448911SDavid Höppner 	sysinfo_t	*sysinfo = (sysinfo_t *)(kp->ks_data);
106266448911SDavid Höppner 
106366448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (sysinfo_t));
106466448911SDavid Höppner 
106566448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, updates);
106666448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, runque);
106766448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, runocc);
106866448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, swpque);
106966448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, swpocc);
107066448911SDavid Höppner 	SAVE_UINT32(ksi, sysinfo, waiting);
107166448911SDavid Höppner }
107266448911SDavid Höppner 
107366448911SDavid Höppner static void
save_vminfo(kstat_t * kp,ks_instance_t * ksi)107466448911SDavid Höppner save_vminfo(kstat_t *kp, ks_instance_t *ksi)
107566448911SDavid Höppner {
107666448911SDavid Höppner 	vminfo_t	*vminfo = (vminfo_t *)(kp->ks_data);
107766448911SDavid Höppner 
107866448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (vminfo_t));
107966448911SDavid Höppner 
108066448911SDavid Höppner 	SAVE_UINT64(ksi, vminfo, freemem);
108166448911SDavid Höppner 	SAVE_UINT64(ksi, vminfo, swap_resv);
108266448911SDavid Höppner 	SAVE_UINT64(ksi, vminfo, swap_alloc);
108366448911SDavid Höppner 	SAVE_UINT64(ksi, vminfo, swap_avail);
108466448911SDavid Höppner 	SAVE_UINT64(ksi, vminfo, swap_free);
108566448911SDavid Höppner 	SAVE_UINT64(ksi, vminfo, updates);
108666448911SDavid Höppner }
108766448911SDavid Höppner 
108866448911SDavid Höppner static void
save_nfs(kstat_t * kp,ks_instance_t * ksi)108966448911SDavid Höppner save_nfs(kstat_t *kp, ks_instance_t *ksi)
109066448911SDavid Höppner {
109166448911SDavid Höppner 	struct mntinfo_kstat *mntinfo = (struct mntinfo_kstat *)(kp->ks_data);
109266448911SDavid Höppner 
109366448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (struct mntinfo_kstat));
109466448911SDavid Höppner 
109566448911SDavid Höppner 	SAVE_STRING(ksi, mntinfo, mik_proto);
109666448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_vers);
109766448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_flags);
109866448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_secmod);
109966448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_curread);
110066448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_curwrite);
110166448911SDavid Höppner 	SAVE_INT32(ksi, mntinfo, mik_timeo);
110266448911SDavid Höppner 	SAVE_INT32(ksi, mntinfo, mik_retrans);
110366448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_acregmin);
110466448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_acregmax);
110566448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_acdirmin);
110666448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_acdirmax);
110766448911SDavid Höppner 	SAVE_UINT32_X(ksi, "lookup_srtt", mntinfo->mik_timers[0].srtt);
110866448911SDavid Höppner 	SAVE_UINT32_X(ksi, "lookup_deviate", mntinfo->mik_timers[0].deviate);
110966448911SDavid Höppner 	SAVE_UINT32_X(ksi, "lookup_rtxcur", mntinfo->mik_timers[0].rtxcur);
111066448911SDavid Höppner 	SAVE_UINT32_X(ksi, "read_srtt", mntinfo->mik_timers[1].srtt);
111166448911SDavid Höppner 	SAVE_UINT32_X(ksi, "read_deviate", mntinfo->mik_timers[1].deviate);
111266448911SDavid Höppner 	SAVE_UINT32_X(ksi, "read_rtxcur", mntinfo->mik_timers[1].rtxcur);
111366448911SDavid Höppner 	SAVE_UINT32_X(ksi, "write_srtt", mntinfo->mik_timers[2].srtt);
111466448911SDavid Höppner 	SAVE_UINT32_X(ksi, "write_deviate", mntinfo->mik_timers[2].deviate);
111566448911SDavid Höppner 	SAVE_UINT32_X(ksi, "write_rtxcur", mntinfo->mik_timers[2].rtxcur);
111666448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_noresponse);
111766448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_failover);
111866448911SDavid Höppner 	SAVE_UINT32(ksi, mntinfo, mik_remap);
111966448911SDavid Höppner 	SAVE_STRING(ksi, mntinfo, mik_curserver);
112066448911SDavid Höppner }
112166448911SDavid Höppner 
112266448911SDavid Höppner #ifdef __sparc
112366448911SDavid Höppner static void
save_sfmmu_global_stat(kstat_t * kp,ks_instance_t * ksi)112466448911SDavid Höppner save_sfmmu_global_stat(kstat_t *kp, ks_instance_t *ksi)
112566448911SDavid Höppner {
112666448911SDavid Höppner 	struct sfmmu_global_stat *sfmmug =
112766448911SDavid Höppner 	    (struct sfmmu_global_stat *)(kp->ks_data);
112866448911SDavid Höppner 
112966448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (struct sfmmu_global_stat));
113066448911SDavid Höppner 
113166448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_exceptions);
113266448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_raise_exception);
113366448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_pagefaults);
113466448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_uhash_searches);
113566448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_uhash_links);
113666448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_khash_searches);
113766448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_khash_links);
113866448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_swapout);
113966448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_alloc);
114066448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_allocfail);
114166448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_sectsb_create);
114266448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_alloc);
114366448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_alloc);
114466448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_scd_1sttsb_allocfail);
114566448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_scd_2ndtsb_allocfail);
114666448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tteload8k);
114766448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tteload64k);
114866448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tteload512k);
114966448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tteload4m);
115066448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tteload32m);
115166448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tteload256m);
115266448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_load8k);
115366448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_load4m);
115466448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk_hit);
115566448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk8_ncreate);
115666448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk8_nalloc);
115766448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk1_ncreate);
115866448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk1_nalloc);
115966448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk_slab_cnt);
116066448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_cnt);
116166448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk_recurse_cnt);
116266448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_hblk_reserve_hit);
116366448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_get_free_success);
116466448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_get_free_throttle);
116566448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_get_free_fail);
116666448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_put_free_success);
116766448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_put_free_fail);
116866448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_pgcolor_conflict);
116966448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_uncache_conflict);
117066448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_unload_conflict);
117166448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_ism_uncache);
117266448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_ism_recache);
117366448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_recache);
117466448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_steal_count);
117566448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_pagesync);
117666448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_clrwrt);
117766448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_pagesync_invalid);
117866448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_kernel_xcalls);
117966448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_user_xcalls);
118066448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_grow);
118166448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_shrink);
118266448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_resize_failures);
118366448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tsb_reloc);
118466448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_user_vtop);
118566448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_ctx_inv);
118666448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_tlb_reprog_pgsz);
118766448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_region_remap_demap);
118866448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_create_scd);
118966448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_join_scd);
119066448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_leave_scd);
119166448911SDavid Höppner 	SAVE_INT32(ksi, sfmmug, sf_destroy_scd);
119266448911SDavid Höppner }
119366448911SDavid Höppner #endif
119466448911SDavid Höppner 
119566448911SDavid Höppner #ifdef __sparc
119666448911SDavid Höppner static void
save_sfmmu_tsbsize_stat(kstat_t * kp,ks_instance_t * ksi)119766448911SDavid Höppner save_sfmmu_tsbsize_stat(kstat_t *kp, ks_instance_t *ksi)
119866448911SDavid Höppner {
119966448911SDavid Höppner 	struct sfmmu_tsbsize_stat *sfmmut;
120066448911SDavid Höppner 
120166448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (struct sfmmu_tsbsize_stat));
120266448911SDavid Höppner 	sfmmut = (struct sfmmu_tsbsize_stat *)(kp->ks_data);
120366448911SDavid Höppner 
120466448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_8k);
120566448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_16k);
120666448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_32k);
120766448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_64k);
120866448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_128k);
120966448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_256k);
121066448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_512k);
121166448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_1m);
121266448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_2m);
121366448911SDavid Höppner 	SAVE_INT32(ksi, sfmmut, sf_tsbsz_4m);
121466448911SDavid Höppner }
121566448911SDavid Höppner #endif
121666448911SDavid Höppner 
121766448911SDavid Höppner #ifdef __sparc
121866448911SDavid Höppner static void
save_simmstat(kstat_t * kp,ks_instance_t * ksi)121966448911SDavid Höppner save_simmstat(kstat_t *kp, ks_instance_t *ksi)
122066448911SDavid Höppner {
122166448911SDavid Höppner 	uchar_t	*simmstat;
122266448911SDavid Höppner 	char	*simm_buf;
122366448911SDavid Höppner 	char	*list = NULL;
122466448911SDavid Höppner 	int	i;
122566448911SDavid Höppner 
122666448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (uchar_t) * SIMM_COUNT);
122766448911SDavid Höppner 
122866448911SDavid Höppner 	for (i = 0, simmstat = (uchar_t *)(kp->ks_data); i < SIMM_COUNT - 1;
122966448911SDavid Höppner 	    i++, simmstat++) {
123066448911SDavid Höppner 		if (list == NULL) {
123166448911SDavid Höppner 			(void) asprintf(&simm_buf, "%d,", *simmstat);
123266448911SDavid Höppner 		} else {
123366448911SDavid Höppner 			(void) asprintf(&simm_buf, "%s%d,", list, *simmstat);
123466448911SDavid Höppner 			free(list);
123566448911SDavid Höppner 		}
123666448911SDavid Höppner 		list = simm_buf;
123766448911SDavid Höppner 	}
123866448911SDavid Höppner 
123966448911SDavid Höppner 	(void) asprintf(&simm_buf, "%s%d", list, *simmstat);
124066448911SDavid Höppner 	SAVE_STRING_X(ksi, "status", simm_buf);
124166448911SDavid Höppner 	free(list);
124266448911SDavid Höppner 	free(simm_buf);
124366448911SDavid Höppner }
124466448911SDavid Höppner #endif
124566448911SDavid Höppner 
124666448911SDavid Höppner #ifdef __sparc
124766448911SDavid Höppner /*
124866448911SDavid Höppner  * Helper function for save_temperature().
124966448911SDavid Höppner  */
125066448911SDavid Höppner static char *
short_array_to_string(short * shortp,int len)125166448911SDavid Höppner short_array_to_string(short *shortp, int len)
125266448911SDavid Höppner {
125366448911SDavid Höppner 	char	*list = NULL;
125466448911SDavid Höppner 	char	*list_buf;
125566448911SDavid Höppner 
125666448911SDavid Höppner 	for (; len > 1; len--, shortp++) {
125766448911SDavid Höppner 		if (list == NULL) {
1258e633f2d7SRichard Lowe 			(void) asprintf(&list_buf, "%hd,", *shortp);
125966448911SDavid Höppner 		} else {
1260e633f2d7SRichard Lowe 			(void) asprintf(&list_buf, "%s%hd,", list, *shortp);
126166448911SDavid Höppner 			free(list);
126266448911SDavid Höppner 		}
126366448911SDavid Höppner 		list = list_buf;
126466448911SDavid Höppner 	}
126566448911SDavid Höppner 
1266e633f2d7SRichard Lowe 	(void) asprintf(&list_buf, "%s%hd", list, *shortp);
126766448911SDavid Höppner 	free(list);
126866448911SDavid Höppner 	return (list_buf);
126966448911SDavid Höppner }
127066448911SDavid Höppner 
127166448911SDavid Höppner static void
save_temperature(kstat_t * kp,ks_instance_t * ksi)127266448911SDavid Höppner save_temperature(kstat_t *kp, ks_instance_t *ksi)
127366448911SDavid Höppner {
127466448911SDavid Höppner 	struct temp_stats *temps = (struct temp_stats *)(kp->ks_data);
127566448911SDavid Höppner 	char	*buf;
127666448911SDavid Höppner 
127766448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (struct temp_stats));
127866448911SDavid Höppner 
127966448911SDavid Höppner 	SAVE_UINT32(ksi, temps, index);
128066448911SDavid Höppner 
128166448911SDavid Höppner 	buf = short_array_to_string(temps->l1, L1_SZ);
128266448911SDavid Höppner 	SAVE_STRING_X(ksi, "l1", buf);
128366448911SDavid Höppner 	free(buf);
128466448911SDavid Höppner 
128566448911SDavid Höppner 	buf = short_array_to_string(temps->l2, L2_SZ);
128666448911SDavid Höppner 	SAVE_STRING_X(ksi, "l2", buf);
128766448911SDavid Höppner 	free(buf);
128866448911SDavid Höppner 
128966448911SDavid Höppner 	buf = short_array_to_string(temps->l3, L3_SZ);
129066448911SDavid Höppner 	SAVE_STRING_X(ksi, "l3", buf);
129166448911SDavid Höppner 	free(buf);
129266448911SDavid Höppner 
129366448911SDavid Höppner 	buf = short_array_to_string(temps->l4, L4_SZ);
129466448911SDavid Höppner 	SAVE_STRING_X(ksi, "l4", buf);
129566448911SDavid Höppner 	free(buf);
129666448911SDavid Höppner 
129766448911SDavid Höppner 	buf = short_array_to_string(temps->l5, L5_SZ);
129866448911SDavid Höppner 	SAVE_STRING_X(ksi, "l5", buf);
129966448911SDavid Höppner 	free(buf);
130066448911SDavid Höppner 
130166448911SDavid Höppner 	SAVE_INT32(ksi, temps, max);
130266448911SDavid Höppner 	SAVE_INT32(ksi, temps, min);
130366448911SDavid Höppner 	SAVE_INT32(ksi, temps, state);
130466448911SDavid Höppner 	SAVE_INT32(ksi, temps, temp_cnt);
130566448911SDavid Höppner 	SAVE_INT32(ksi, temps, shutdown_cnt);
130666448911SDavid Höppner 	SAVE_INT32(ksi, temps, version);
130766448911SDavid Höppner 	SAVE_INT32(ksi, temps, trend);
130866448911SDavid Höppner 	SAVE_INT32(ksi, temps, override);
130966448911SDavid Höppner }
131066448911SDavid Höppner #endif
131166448911SDavid Höppner 
131266448911SDavid Höppner #ifdef __sparc
131366448911SDavid Höppner static void
save_temp_over(kstat_t * kp,ks_instance_t * ksi)131466448911SDavid Höppner save_temp_over(kstat_t *kp, ks_instance_t *ksi)
131566448911SDavid Höppner {
131666448911SDavid Höppner 	short	*sh = (short *)(kp->ks_data);
131766448911SDavid Höppner 	char	*value;
131866448911SDavid Höppner 
131966448911SDavid Höppner 	assert(kp->ks_data_size == sizeof (short));
132066448911SDavid Höppner 
132166448911SDavid Höppner 	(void) asprintf(&value, "%hu", *sh);
132266448911SDavid Höppner 	SAVE_STRING_X(ksi, "override", value);
132366448911SDavid Höppner 	free(value);
132466448911SDavid Höppner }
132566448911SDavid Höppner #endif
132666448911SDavid Höppner 
132766448911SDavid Höppner #ifdef __sparc
132866448911SDavid Höppner static void
save_ps_shadow(kstat_t * kp,ks_instance_t * ksi)132966448911SDavid Höppner save_ps_shadow(kstat_t *kp, ks_instance_t *ksi)
133066448911SDavid Höppner {
133166448911SDavid Höppner 	uchar_t	*uchar = (uchar_t *)(kp->ks_data);
133266448911SDavid Höppner 
133366448911SDavid Höppner 	assert(kp->ks_data_size == SYS_PS_COUNT);
133466448911SDavid Höppner 
133566448911SDavid Höppner 	SAVE_CHAR_X(ksi, "core_0", *uchar++);
133666448911SDavid Höppner 	SAVE_CHAR_X(ksi, "core_1", *uchar++);
133766448911SDavid Höppner 	SAVE_CHAR_X(ksi, "core_2", *uchar++);
133866448911SDavid Höppner 	SAVE_CHAR_X(ksi, "core_3", *uchar++);
133966448911SDavid Höppner 	SAVE_CHAR_X(ksi, "core_4", *uchar++);
134066448911SDavid Höppner 	SAVE_CHAR_X(ksi, "core_5", *uchar++);
134166448911SDavid Höppner 	SAVE_CHAR_X(ksi, "core_6", *uchar++);
134266448911SDavid Höppner 	SAVE_CHAR_X(ksi, "core_7", *uchar++);
134366448911SDavid Höppner 	SAVE_CHAR_X(ksi, "pps_0", *uchar++);
134466448911SDavid Höppner 	SAVE_CHAR_X(ksi, "clk_33", *uchar++);
134566448911SDavid Höppner 	SAVE_CHAR_X(ksi, "clk_50", *uchar++);
134666448911SDavid Höppner 	SAVE_CHAR_X(ksi, "v5_p", *uchar++);
134766448911SDavid Höppner 	SAVE_CHAR_X(ksi, "v12_p", *uchar++);
134866448911SDavid Höppner 	SAVE_CHAR_X(ksi, "v5_aux", *uchar++);
134966448911SDavid Höppner 	SAVE_CHAR_X(ksi, "v5_p_pch", *uchar++);
135066448911SDavid Höppner 	SAVE_CHAR_X(ksi, "v12_p_pch", *uchar++);
135166448911SDavid Höppner 	SAVE_CHAR_X(ksi, "v3_pch", *uchar++);
135266448911SDavid Höppner 	SAVE_CHAR_X(ksi, "v5_pch", *uchar++);
135366448911SDavid Höppner 	SAVE_CHAR_X(ksi, "p_fan", *uchar++);
135466448911SDavid Höppner }
135566448911SDavid Höppner #endif
135666448911SDavid Höppner 
135766448911SDavid Höppner #ifdef __sparc
135866448911SDavid Höppner static void
save_fault_list(kstat_t * kp,ks_instance_t * ksi)135966448911SDavid Höppner save_fault_list(kstat_t *kp, ks_instance_t *ksi)
136066448911SDavid Höppner {
136166448911SDavid Höppner 	struct ft_list *fault;
136266448911SDavid Höppner 	char	name[KSTAT_STRLEN + 7];
136366448911SDavid Höppner 	int	i;
136466448911SDavid Höppner 
136566448911SDavid Höppner 	for (i = 1, fault = (struct ft_list *)(kp->ks_data);
136666448911SDavid Höppner 	    i <= 999999 && i <= kp->ks_data_size / sizeof (struct ft_list);
136766448911SDavid Höppner 	    i++, fault++) {
136866448911SDavid Höppner 		(void) snprintf(name, sizeof (name), "unit_%d", i);
136966448911SDavid Höppner 		SAVE_INT32_X(ksi, name, fault->unit);
137066448911SDavid Höppner 		(void) snprintf(name, sizeof (name), "type_%d", i);
137166448911SDavid Höppner 		SAVE_INT32_X(ksi, name, fault->type);
137266448911SDavid Höppner 		(void) snprintf(name, sizeof (name), "fclass_%d", i);
137366448911SDavid Höppner 		SAVE_INT32_X(ksi, name, fault->fclass);
137466448911SDavid Höppner 		(void) snprintf(name, sizeof (name), "create_time_%d", i);
137566448911SDavid Höppner 		SAVE_HRTIME_X(ksi, name, fault->create_time);
137666448911SDavid Höppner 		(void) snprintf(name, sizeof (name), "msg_%d", i);
1377e633f2d7SRichard Lowe 		SAVE_STRING_X(ksi, name, fault->msg);
137866448911SDavid Höppner 	}
137966448911SDavid Höppner }
138066448911SDavid Höppner #endif
138166448911SDavid Höppner 
138266448911SDavid Höppner static void
save_named(kstat_t * kp,ks_instance_t * ksi)138366448911SDavid Höppner save_named(kstat_t *kp, ks_instance_t *ksi)
138466448911SDavid Höppner {
138566448911SDavid Höppner 	kstat_named_t *knp;
138666448911SDavid Höppner 	int	n;
138766448911SDavid Höppner 
138866448911SDavid Höppner 	for (n = kp->ks_ndata, knp = KSTAT_NAMED_PTR(kp); n > 0; n--, knp++) {
138966448911SDavid Höppner 		switch (knp->data_type) {
139066448911SDavid Höppner 		case KSTAT_DATA_CHAR:
139166448911SDavid Höppner 			nvpair_insert(ksi, knp->name,
139266448911SDavid Höppner 			    (ks_value_t *)&knp->value, KSTAT_DATA_CHAR);
139366448911SDavid Höppner 			break;
139466448911SDavid Höppner 		case KSTAT_DATA_INT32:
139566448911SDavid Höppner 			nvpair_insert(ksi, knp->name,
139666448911SDavid Höppner 			    (ks_value_t *)&knp->value, KSTAT_DATA_INT32);
139766448911SDavid Höppner 			break;
139866448911SDavid Höppner 		case KSTAT_DATA_UINT32:
139966448911SDavid Höppner 			nvpair_insert(ksi, knp->name,
140066448911SDavid Höppner 			    (ks_value_t *)&knp->value, KSTAT_DATA_UINT32);
140166448911SDavid Höppner 			break;
140266448911SDavid Höppner 		case KSTAT_DATA_INT64:
140366448911SDavid Höppner 			nvpair_insert(ksi, knp->name,
140466448911SDavid Höppner 			    (ks_value_t *)&knp->value, KSTAT_DATA_INT64);
140566448911SDavid Höppner 			break;
140666448911SDavid Höppner 		case KSTAT_DATA_UINT64:
140766448911SDavid Höppner 			nvpair_insert(ksi, knp->name,
140866448911SDavid Höppner 			    (ks_value_t *)&knp->value, KSTAT_DATA_UINT64);
140966448911SDavid Höppner 			break;
141066448911SDavid Höppner 		case KSTAT_DATA_STRING:
141166448911SDavid Höppner 			SAVE_STRING_X(ksi, knp->name, KSTAT_NAMED_STR_PTR(knp));
141266448911SDavid Höppner 			break;
141366448911SDavid Höppner 		default:
141466448911SDavid Höppner 			assert(B_FALSE); /* Invalid data type */
141566448911SDavid Höppner 			break;
141666448911SDavid Höppner 		}
141766448911SDavid Höppner 	}
141866448911SDavid Höppner }
141966448911SDavid Höppner 
142066448911SDavid Höppner static void
save_intr(kstat_t * kp,ks_instance_t * ksi)142166448911SDavid Höppner save_intr(kstat_t *kp, ks_instance_t *ksi)
142266448911SDavid Höppner {
142366448911SDavid Höppner 	kstat_intr_t *intr = KSTAT_INTR_PTR(kp);
142466448911SDavid Höppner 	char	*intr_names[] = {"hard", "soft", "watchdog", "spurious",
142566448911SDavid Höppner 	    "multiple_service"};
142666448911SDavid Höppner 	int	n;
142766448911SDavid Höppner 
142866448911SDavid Höppner 	for (n = 0; n < KSTAT_NUM_INTRS; n++)
142966448911SDavid Höppner 		SAVE_UINT32_X(ksi, intr_names[n], intr->intrs[n]);
143066448911SDavid Höppner }
143166448911SDavid Höppner 
143266448911SDavid Höppner static void
save_io(kstat_t * kp,ks_instance_t * ksi)143366448911SDavid Höppner save_io(kstat_t *kp, ks_instance_t *ksi)
143466448911SDavid Höppner {
143566448911SDavid Höppner 	kstat_io_t	*ksio = KSTAT_IO_PTR(kp);
143666448911SDavid Höppner 
143766448911SDavid Höppner 	SAVE_UINT64(ksi, ksio, nread);
143866448911SDavid Höppner 	SAVE_UINT64(ksi, ksio, nwritten);
143966448911SDavid Höppner 	SAVE_UINT32(ksi, ksio, reads);
144066448911SDavid Höppner 	SAVE_UINT32(ksi, ksio, writes);
144166448911SDavid Höppner 	SAVE_HRTIME(ksi, ksio, wtime);
144266448911SDavid Höppner 	SAVE_HRTIME(ksi, ksio, wlentime);
144366448911SDavid Höppner 	SAVE_HRTIME(ksi, ksio, wlastupdate);
144466448911SDavid Höppner 	SAVE_HRTIME(ksi, ksio, rtime);
144566448911SDavid Höppner 	SAVE_HRTIME(ksi, ksio, rlentime);
144666448911SDavid Höppner 	SAVE_HRTIME(ksi, ksio, rlastupdate);
144766448911SDavid Höppner 	SAVE_UINT32(ksi, ksio, wcnt);
144866448911SDavid Höppner 	SAVE_UINT32(ksi, ksio, rcnt);
144966448911SDavid Höppner }
145066448911SDavid Höppner 
145166448911SDavid Höppner static void
save_timer(kstat_t * kp,ks_instance_t * ksi)145266448911SDavid Höppner save_timer(kstat_t *kp, ks_instance_t *ksi)
145366448911SDavid Höppner {
145466448911SDavid Höppner 	kstat_timer_t	*ktimer = KSTAT_TIMER_PTR(kp);
145566448911SDavid Höppner 
145666448911SDavid Höppner 	SAVE_STRING(ksi, ktimer, name);
145766448911SDavid Höppner 	SAVE_UINT64(ksi, ktimer, num_events);
145866448911SDavid Höppner 	SAVE_HRTIME(ksi, ktimer, elapsed_time);
145966448911SDavid Höppner 	SAVE_HRTIME(ksi, ktimer, min_time);
146066448911SDavid Höppner 	SAVE_HRTIME(ksi, ktimer, max_time);
146166448911SDavid Höppner 	SAVE_HRTIME(ksi, ktimer, start_time);
146266448911SDavid Höppner 	SAVE_HRTIME(ksi, ktimer, stop_time);
146366448911SDavid Höppner }
1464