7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill/*
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * CDDL HEADER START
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill *
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * The contents of this file are subject to the terms of the
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Common Development and Distribution License (the "License").
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * You may not use this file except in compliance with the License.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill *
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * or http://www.opensolaris.org/os/licensing.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * See the License for the specific language governing permissions
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * and limitations under the License.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill *
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * When distributing Covered Code, include this CDDL HEADER in each
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * If applicable, add the following below this CDDL HEADER, with the
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * fields enclosed by brackets "[]" replaced with your own identifying
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * information: Portions Copyright [yyyy] [name of copyright owner]
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill *
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * CDDL HEADER END
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill/*
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Copyright (c) 2011, Joyent, Inc. All rights reserved.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <sys/kstat.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <kstat.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <stdlib.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <unistd.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <assert.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <errno.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <stdio.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <string.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <strings.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <alloca.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <signal.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <sys/varargs.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#include <sys/int_limits.h>
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#define KSTAT_FIELD_USEINSTANCE 0x01
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#define KSTAT_FIELD_NODELTA 0x02
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill#define KSTAT_FIELD_FILLER 0x04
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrilltypedef struct kstat_field {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill char *ksf_header; /* header for field */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill char *ksf_name; /* name of stat, if any */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int ksf_width; /* width for field in output line */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint32_t ksf_flags; /* flags for this field, if any */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int ksf_hint; /* index hint for field in kstat */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill} kstat_field_t;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrilltypedef struct kstat_instance {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill char ksi_name[KSTAT_STRLEN]; /* name of the underlying kstat */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int ksi_instance; /* instance identifer of this kstat */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_t *ksi_ksp; /* pointer to the kstat */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint64_t *ksi_data[2]; /* pointer to two generations of data */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill hrtime_t ksi_snaptime[2]; /* hrtime for data generations */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int ksi_gen; /* current generation */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill struct kstat_instance *ksi_next; /* next in instance list */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill} kstat_instance_t;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillconst char *g_cmd = "kvmstat";
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillstatic void
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillfatal(char *fmt, ...)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill va_list ap;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int error = errno;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill va_start(ap, fmt);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) fprintf(stderr, "%s: ", g_cmd);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill /*LINTED*/
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) vfprintf(stderr, fmt, ap);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (fmt[strlen(fmt) - 1] != '\n')
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) fprintf(stderr, ": %s\n", strerror(error));
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill exit(EXIT_FAILURE);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillint
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_field_hint(kstat_t *ksp, kstat_field_t *field)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_named_t *nm = KSTAT_NAMED_PTR(ksp);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int i;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill assert(ksp->ks_type == KSTAT_TYPE_NAMED);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < ksp->ks_ndata; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (strcmp(field->ksf_name, nm[i].name) == 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (field->ksf_hint = i);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("could not find field '%s' in %s:%d\n",
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill field->ksf_name, ksp->ks_name, ksp->ks_instance);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (0);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillint
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_compare(const void *lhs, const void *rhs)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t *l = *((kstat_instance_t **)lhs);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t *r = *((kstat_instance_t **)rhs);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int rval;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if ((rval = strcmp(l->ksi_name, r->ksi_name)) != 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (rval);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (l->ksi_instance < r->ksi_instance)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (-1);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (l->ksi_instance > r->ksi_instance)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (1);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (0);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillvoid
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_update(kstat_ctl_t *kcp, kstat_instance_t **head,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill boolean_t (*interested)(kstat_t *))
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int ninstances = 0, i;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t **sorted, *ksi, *next;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_t *ksp;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kid_t kid;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if ((kid = kstat_chain_update(kcp)) == 0 && *head != NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (kid == -1)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("failed to update kstat chain");
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = *head; ksi != NULL; ksi = ksi->ksi_next)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_ksp = NULL;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksp = kcp->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t *last = NULL;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (!interested(ksp))
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill /*
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Now look to see if we have this instance and name. (Yes,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * this is a linear search; we're assuming that this list is
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * modest in size.)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = *head; ksi != NULL; ksi = ksi->ksi_next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill last = ksi;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ksi->ksi_instance != ksp->ks_instance)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (strcmp(ksi->ksi_name, ksp->ks_name) != 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_ksp = ksp;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ninstances++;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill break;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ksi != NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if ((ksi = malloc(sizeof (kstat_instance_t))) == NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("could not allocate memory for stat instance");
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill bzero(ksi, sizeof (kstat_instance_t));
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) strlcpy(ksi->ksi_name, ksp->ks_name, KSTAT_STRLEN);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_instance = ksp->ks_instance;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_ksp = ksp;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_next = NULL;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (last == NULL) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill assert(*head == NULL);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill *head = ksi;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill } else {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill last->ksi_next = ksi;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ninstances++;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill /*
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Now we know how many instances we have; iterate back over them,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * pruning the stale ones and adding the active ones to a holding
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * array in which to sort them.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill sorted = (void *)alloca(ninstances * sizeof (kstat_instance_t *));
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ninstances = 0;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = *head; ksi != NULL; ksi = next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill next = ksi->ksi_next;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ksi->ksi_ksp == NULL) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill free(ksi);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill } else {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill sorted[ninstances++] = ksi;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ninstances == 0) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill *head = NULL;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill qsort(sorted, ninstances, sizeof (kstat_instance_t *),
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instances_compare);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill *head = sorted[0];
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < ninstances; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi = sorted[i];
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_next = i < ninstances - 1 ? sorted[i + 1] : NULL;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillvoid
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_read(kstat_ctl_t *kcp, kstat_instance_t *instances,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_field_t *fields)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t *ksi;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int i, nfields;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (nfields = 0; fields[nfields].ksf_header != NULL; nfields++)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = instances; ksi != NULL; ksi = ksi->ksi_next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_t *ksp = ksi->ksi_ksp;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ksp == NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (kstat_read(kcp, ksp, NULL) == -1) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (errno == ENXIO) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill /*
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * Our kstat has been removed since the update;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * NULL it out to prevent us from trying to read
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * it again (and to indicate that it should not
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill * be displayed) and drive on.
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_ksp = NULL;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("failed to read kstat %s:%d",
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_name, ksi->ksi_instance);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ksp->ks_type != KSTAT_TYPE_NAMED) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("%s:%d is not a named kstat", ksi->ksi_name,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_instance);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ksi->ksi_data[0] == NULL) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill size_t size = nfields * sizeof (uint64_t) * 2;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint64_t *data;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if ((data = malloc(size)) == NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("could not allocate memory");
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill bzero(data, size);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_data[0] = data;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_data[1] = &data[nfields];
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < nfields; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_named_t *nm = KSTAT_NAMED_PTR(ksp);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_field_t *field = &fields[i];
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int hint = field->ksf_hint;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (field->ksf_name == NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (hint < 0 || hint >= ksp->ks_ndata ||
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill strcmp(field->ksf_name, nm[hint].name) != 0) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill hint = kstat_field_hint(ksp, field);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_data[ksi->ksi_gen][i] = nm[hint].value.ui64;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_snaptime[ksi->ksi_gen] = ksp->ks_snaptime;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_gen ^= 1;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrilluint64_t
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_delta(kstat_instance_t *ksi, int i)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int gen = ksi->ksi_gen;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint64_t delta = ksi->ksi_data[gen ^ 1][i] - ksi->ksi_data[gen][i];
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill uint64_t tdelta = ksi->ksi_snaptime[gen ^ 1] - ksi->ksi_snaptime[gen];
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (((delta * (uint64_t)NANOSEC) + (tdelta / 2)) / tdelta);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillvoid
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillkstat_instances_print(kstat_instance_t *instances, kstat_field_t *fields,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill boolean_t header)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t *ksi = instances;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int i, nfields;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (nfields = 0; fields[nfields].ksf_header != NULL; nfields++)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (header) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < nfields; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) printf("%*s%c", fields[i].ksf_width,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fields[i].ksf_header, i < nfields - 1 ? ' ' : '\n');
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (ksi = instances; ksi != NULL; ksi = ksi->ksi_next) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (ksi->ksi_snaptime[1] == 0 || ksi->ksi_ksp == NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (i = 0; i < nfields; i++) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill char trailer = i < nfields - 1 ? ' ' : '\n';
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (fields[i].ksf_flags & KSTAT_FIELD_FILLER) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) printf("%*s%c", fields[i].ksf_width,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fields[i].ksf_header, trailer);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill continue;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) printf("%*lld%c", fields[i].ksf_width,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fields[i].ksf_flags & KSTAT_FIELD_USEINSTANCE ?
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_instance :
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fields[i].ksf_flags & KSTAT_FIELD_NODELTA ?
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill ksi->ksi_data[ksi->ksi_gen ^ 1][i] :
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instances_delta(ksi, i), trailer);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillboolean_t
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillinterested(kstat_t *ksp)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill const char *module = "kvm";
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill const char *class = "misc";
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill const char *name = "vcpu-";
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (strcmp(ksp->ks_module, module) != 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (B_FALSE);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (strcmp(ksp->ks_class, class) != 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (B_FALSE);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (strstr(ksp->ks_name, name) != ksp->ks_name)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (B_FALSE);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (B_TRUE);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill/* BEGIN CSTYLED */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillchar *g_usage = "Usage: kvmstat [interval [count]]\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill "\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " Displays statistics for running kernel virtual machines, with one line\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " per virtual CPU. All statistics are reported as per-second rates.\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill "\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " The columns are as follows:\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill "\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " pid => identifier of process controlling the virtual CPU\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " vcpu => virtual CPU identifier relative to its virtual machine\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " exits => virtual machine exits for the virtual CPU\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " haltx => virtual machine exits due to the HLT instruction\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " irqx => virtual machine exits due to a pending external interrupt\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " irqwx => virtual machine exits due to an open interrupt window\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " iox => virtual machine exits due to an I/O instruction\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " mmiox => virtual machine exits due to memory mapped I/O \n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " irqs => interrupts injected into the virtual CPU\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " emul => instructions emulated in the kernel\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill " eptv => extended page table violations\n"
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill "\n";
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill/* END CSTYLED */
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillvoid
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillusage()
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) fprintf(stderr, "%s", g_usage);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill exit(EXIT_FAILURE);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill/*ARGSUSED*/
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillvoid
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillintr(int sig)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{}
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill/*ARGSUSED*/
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillint
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrillmain(int argc, char **argv)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill{
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_ctl_t *kcp;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instance_t *instances = NULL;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int i = 0;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int interval = 1;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill int count = INT32_MAX;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill struct itimerval itimer;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill struct sigaction act;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill sigset_t set;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill char *endp;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_field_t fields[] = {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "pid", "pid", 6, KSTAT_FIELD_NODELTA },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "vcpu", NULL, 4, KSTAT_FIELD_USEINSTANCE },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "|", NULL, 1, KSTAT_FIELD_FILLER },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "exits", "exits", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { ":", NULL, 1, KSTAT_FIELD_FILLER },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "haltx", "halt-exits", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "irqx", "irq-exits", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "irqwx", "irq-window-exits", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "iox", "io-exits", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "mmiox", "mmio-exits", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "|", NULL, 1, KSTAT_FIELD_FILLER },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "irqs", "irq-injections", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "emul", "insn-emulation", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { "eptv", "pf-fixed", 6 },
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill { NULL }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill };
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (argc > 1) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill interval = strtol(argv[1], &endp, 10);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (*endp != '\0' || interval <= 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill usage();
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (argc > 2) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill count = strtol(argv[2], &endp, 10);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (*endp != '\0' || count <= 0)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill usage();
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if ((kcp = kstat_open()) == NULL)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("could not open /dev/kstat");
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) sigemptyset(&act.sa_mask);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill act.sa_flags = 0;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill act.sa_handler = intr;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) sigaction(SIGALRM, &act, NULL);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) sigemptyset(&set);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) sigaddset(&set, SIGALRM);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) sigprocmask(SIG_BLOCK, &set, NULL);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill bzero(&itimer, sizeof (itimer));
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill itimer.it_value.tv_sec = interval;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill itimer.it_interval.tv_sec = interval;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (setitimer(ITIMER_REAL, &itimer, NULL) != 0) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill fatal("could not set timer to %d second%s", interval,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill interval == 1 ? "" : "s");
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) sigemptyset(&set);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill for (;;) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instances_update(kcp, &instances, interested);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instances_read(kcp, instances, fields);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (i++ > 0) {
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill kstat_instances_print(instances, fields,
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill instances != NULL && instances->ksi_next == NULL ?
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (((i - 2) % 20) == 0) : B_TRUE);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill if (i > count)
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill break;
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill (void) sigsuspend(&set);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill }
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill /*NOTREACHED*/
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill return (0);
7aa76ffc594f84c1c092911a84f85a79ddb44c73Bryan Cantrill}