1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "statcommon.h" 30*7c478bd9Sstevel@tonic-gate #include "dsr.h" 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 34*7c478bd9Sstevel@tonic-gate #include <unistd.h> 35*7c478bd9Sstevel@tonic-gate #include <strings.h> 36*7c478bd9Sstevel@tonic-gate #include <errno.h> 37*7c478bd9Sstevel@tonic-gate #include <poll.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #define ARRAY_SIZE(a) (sizeof (a) / sizeof (*a)) 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate * The time we delay before retrying after an allocation 43*7c478bd9Sstevel@tonic-gate * failure, in milliseconds 44*7c478bd9Sstevel@tonic-gate */ 45*7c478bd9Sstevel@tonic-gate #define RETRY_DELAY 200 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate static char *cpu_states[] = { 48*7c478bd9Sstevel@tonic-gate "cpu_ticks_idle", 49*7c478bd9Sstevel@tonic-gate "cpu_ticks_user", 50*7c478bd9Sstevel@tonic-gate "cpu_ticks_kernel", 51*7c478bd9Sstevel@tonic-gate "cpu_ticks_wait" 52*7c478bd9Sstevel@tonic-gate }; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate extern char cmdname[]; 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate static kstat_t * 57*7c478bd9Sstevel@tonic-gate kstat_lookup_read(kstat_ctl_t *kc, char *module, 58*7c478bd9Sstevel@tonic-gate int instance, char *name) 59*7c478bd9Sstevel@tonic-gate { 60*7c478bd9Sstevel@tonic-gate kstat_t *ksp = kstat_lookup(kc, module, instance, name); 61*7c478bd9Sstevel@tonic-gate if (ksp == NULL) 62*7c478bd9Sstevel@tonic-gate return (NULL); 63*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, NULL) == -1) 64*7c478bd9Sstevel@tonic-gate return (NULL); 65*7c478bd9Sstevel@tonic-gate return (ksp); 66*7c478bd9Sstevel@tonic-gate } 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * Note: the following helpers do not clean up on the failure case, 70*7c478bd9Sstevel@tonic-gate * because it is left to the free_snapshot() in the acquire_snapshot() 71*7c478bd9Sstevel@tonic-gate * failure path. 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate static int 75*7c478bd9Sstevel@tonic-gate acquire_cpus(struct snapshot *ss, kstat_ctl_t *kc) 76*7c478bd9Sstevel@tonic-gate { 77*7c478bd9Sstevel@tonic-gate size_t i; 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate ss->s_nr_cpus = sysconf(_SC_CPUID_MAX) + 1; 80*7c478bd9Sstevel@tonic-gate ss->s_cpus = calloc(ss->s_nr_cpus, sizeof (struct cpu_snapshot)); 81*7c478bd9Sstevel@tonic-gate if (ss->s_cpus == NULL) 82*7c478bd9Sstevel@tonic-gate goto out; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate for (i = 0; i < ss->s_nr_cpus; i++) { 85*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate ss->s_cpus[i].cs_id = ID_NO_CPU; 88*7c478bd9Sstevel@tonic-gate ss->s_cpus[i].cs_state = p_online(i, P_STATUS); 89*7c478bd9Sstevel@tonic-gate /* If no valid CPU is present, move on to the next one */ 90*7c478bd9Sstevel@tonic-gate if (ss->s_cpus[i].cs_state == -1) 91*7c478bd9Sstevel@tonic-gate continue; 92*7c478bd9Sstevel@tonic-gate ss->s_cpus[i].cs_id = i; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup_read(kc, "cpu_info", i, NULL)) == NULL) 95*7c478bd9Sstevel@tonic-gate goto out; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate (void) pset_assign(PS_QUERY, i, &ss->s_cpus[i].cs_pset_id); 98*7c478bd9Sstevel@tonic-gate if (ss->s_cpus[i].cs_pset_id == PS_NONE) 99*7c478bd9Sstevel@tonic-gate ss->s_cpus[i].cs_pset_id = ID_NO_PSET; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate if (!CPU_ACTIVE(&ss->s_cpus[i])) 102*7c478bd9Sstevel@tonic-gate continue; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup_read(kc, "cpu", i, "vm")) == NULL) 105*7c478bd9Sstevel@tonic-gate goto out; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate if (kstat_copy(ksp, &ss->s_cpus[i].cs_vm)) 108*7c478bd9Sstevel@tonic-gate goto out; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup_read(kc, "cpu", i, "sys")) == NULL) 111*7c478bd9Sstevel@tonic-gate goto out; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate if (kstat_copy(ksp, &ss->s_cpus[i].cs_sys)) 114*7c478bd9Sstevel@tonic-gate goto out; 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate errno = 0; 118*7c478bd9Sstevel@tonic-gate out: 119*7c478bd9Sstevel@tonic-gate return (errno); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate static int 123*7c478bd9Sstevel@tonic-gate acquire_psets(struct snapshot *ss) 124*7c478bd9Sstevel@tonic-gate { 125*7c478bd9Sstevel@tonic-gate psetid_t *pids = NULL; 126*7c478bd9Sstevel@tonic-gate struct pset_snapshot *ps; 127*7c478bd9Sstevel@tonic-gate size_t pids_nr; 128*7c478bd9Sstevel@tonic-gate size_t i, j; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Careful in this code. We have to use pset_list 132*7c478bd9Sstevel@tonic-gate * twice, but inbetween pids_nr can change at will. 133*7c478bd9Sstevel@tonic-gate * We delay the setting of s_nr_psets until we have 134*7c478bd9Sstevel@tonic-gate * the "final" value of pids_nr. 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate if (pset_list(NULL, &pids_nr) < 0) 138*7c478bd9Sstevel@tonic-gate return (errno); 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate if ((pids = calloc(pids_nr, sizeof (psetid_t))) == NULL) 141*7c478bd9Sstevel@tonic-gate goto out; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate if (pset_list(pids, &pids_nr) < 0) 144*7c478bd9Sstevel@tonic-gate goto out; 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate ss->s_psets = calloc(pids_nr + 1, sizeof (struct pset_snapshot)); 147*7c478bd9Sstevel@tonic-gate if (ss->s_psets == NULL) 148*7c478bd9Sstevel@tonic-gate goto out; 149*7c478bd9Sstevel@tonic-gate ss->s_nr_psets = pids_nr + 1; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate /* CPUs not in any actual pset */ 152*7c478bd9Sstevel@tonic-gate ps = &ss->s_psets[0]; 153*7c478bd9Sstevel@tonic-gate ps->ps_id = 0; 154*7c478bd9Sstevel@tonic-gate ps->ps_cpus = calloc(ss->s_nr_cpus, sizeof (struct cpu_snapshot *)); 155*7c478bd9Sstevel@tonic-gate if (ps->ps_cpus == NULL) 156*7c478bd9Sstevel@tonic-gate goto out; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate /* CPUs in a a pset */ 159*7c478bd9Sstevel@tonic-gate for (i = 1; i < ss->s_nr_psets; i++) { 160*7c478bd9Sstevel@tonic-gate ps = &ss->s_psets[i]; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate ps->ps_id = pids[i - 1]; 163*7c478bd9Sstevel@tonic-gate ps->ps_cpus = 164*7c478bd9Sstevel@tonic-gate calloc(ss->s_nr_cpus, sizeof (struct cpu_snapshot *)); 165*7c478bd9Sstevel@tonic-gate if (ps->ps_cpus == NULL) 166*7c478bd9Sstevel@tonic-gate goto out; 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate for (i = 0; i < ss->s_nr_psets; i++) { 170*7c478bd9Sstevel@tonic-gate ps = &ss->s_psets[i]; 171*7c478bd9Sstevel@tonic-gate 172*7c478bd9Sstevel@tonic-gate for (j = 0; j < ss->s_nr_cpus; j++) { 173*7c478bd9Sstevel@tonic-gate if (!CPU_ACTIVE(&ss->s_cpus[j])) 174*7c478bd9Sstevel@tonic-gate continue; 175*7c478bd9Sstevel@tonic-gate if (ss->s_cpus[j].cs_pset_id != ps->ps_id) 176*7c478bd9Sstevel@tonic-gate continue; 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate ps->ps_cpus[ps->ps_nr_cpus++] = &ss->s_cpus[j]; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate errno = 0; 183*7c478bd9Sstevel@tonic-gate out: 184*7c478bd9Sstevel@tonic-gate free(pids); 185*7c478bd9Sstevel@tonic-gate return (errno); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate static int 189*7c478bd9Sstevel@tonic-gate acquire_intrs(struct snapshot *ss, kstat_ctl_t *kc) 190*7c478bd9Sstevel@tonic-gate { 191*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 192*7c478bd9Sstevel@tonic-gate size_t i = 0; 193*7c478bd9Sstevel@tonic-gate kstat_t *sys_misc; 194*7c478bd9Sstevel@tonic-gate kstat_named_t *clock; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* clock interrupt */ 197*7c478bd9Sstevel@tonic-gate ss->s_nr_intrs = 1; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 200*7c478bd9Sstevel@tonic-gate if (ksp->ks_type == KSTAT_TYPE_INTR) 201*7c478bd9Sstevel@tonic-gate ss->s_nr_intrs++; 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate ss->s_intrs = calloc(ss->s_nr_intrs, sizeof (struct intr_snapshot)); 205*7c478bd9Sstevel@tonic-gate if (ss->s_intrs == NULL) 206*7c478bd9Sstevel@tonic-gate return (errno); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate sys_misc = kstat_lookup_read(kc, "unix", 0, "system_misc"); 209*7c478bd9Sstevel@tonic-gate if (sys_misc == NULL) 210*7c478bd9Sstevel@tonic-gate goto out; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate clock = (kstat_named_t *)kstat_data_lookup(sys_misc, "clk_intr"); 213*7c478bd9Sstevel@tonic-gate if (clock == NULL) 214*7c478bd9Sstevel@tonic-gate goto out; 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate (void) strlcpy(ss->s_intrs[0].is_name, "clock", KSTAT_STRLEN); 217*7c478bd9Sstevel@tonic-gate ss->s_intrs[0].is_total = clock->value.ui32; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate i = 1; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 222*7c478bd9Sstevel@tonic-gate kstat_intr_t *ki; 223*7c478bd9Sstevel@tonic-gate int j; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_INTR) 226*7c478bd9Sstevel@tonic-gate continue; 227*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, NULL) == -1) 228*7c478bd9Sstevel@tonic-gate goto out; 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate ki = KSTAT_INTR_PTR(ksp); 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate (void) strlcpy(ss->s_intrs[i].is_name, ksp->ks_name, 233*7c478bd9Sstevel@tonic-gate KSTAT_STRLEN); 234*7c478bd9Sstevel@tonic-gate ss->s_intrs[i].is_total = 0; 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate for (j = 0; j < KSTAT_NUM_INTRS; j++) 237*7c478bd9Sstevel@tonic-gate ss->s_intrs[i].is_total += ki->intrs[j]; 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate i++; 240*7c478bd9Sstevel@tonic-gate } 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate errno = 0; 243*7c478bd9Sstevel@tonic-gate out: 244*7c478bd9Sstevel@tonic-gate return (errno); 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate int 248*7c478bd9Sstevel@tonic-gate acquire_sys(struct snapshot *ss, kstat_ctl_t *kc) 249*7c478bd9Sstevel@tonic-gate { 250*7c478bd9Sstevel@tonic-gate size_t i; 251*7c478bd9Sstevel@tonic-gate kstat_named_t *knp; 252*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kc, "unix", 0, "sysinfo")) == NULL) 255*7c478bd9Sstevel@tonic-gate return (errno); 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &ss->s_sys.ss_sysinfo) == -1) 258*7c478bd9Sstevel@tonic-gate return (errno); 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kc, "unix", 0, "vminfo")) == NULL) 261*7c478bd9Sstevel@tonic-gate return (errno); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &ss->s_sys.ss_vminfo) == -1) 264*7c478bd9Sstevel@tonic-gate return (errno); 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kc, "unix", 0, "dnlcstats")) == NULL) 267*7c478bd9Sstevel@tonic-gate return (errno); 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &ss->s_sys.ss_nc) == -1) 270*7c478bd9Sstevel@tonic-gate return (errno); 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate if ((ksp = kstat_lookup(kc, "unix", 0, "system_misc")) == NULL) 273*7c478bd9Sstevel@tonic-gate return (errno); 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, NULL) == -1) 276*7c478bd9Sstevel@tonic-gate return (errno); 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate knp = (kstat_named_t *)kstat_data_lookup(ksp, "clk_intr"); 279*7c478bd9Sstevel@tonic-gate if (knp == NULL) 280*7c478bd9Sstevel@tonic-gate return (errno); 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate ss->s_sys.ss_ticks = knp->value.l; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate knp = (kstat_named_t *)kstat_data_lookup(ksp, "deficit"); 285*7c478bd9Sstevel@tonic-gate if (knp == NULL) 286*7c478bd9Sstevel@tonic-gate return (errno); 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate ss->s_sys.ss_deficit = knp->value.l; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate for (i = 0; i < ss->s_nr_cpus; i++) { 291*7c478bd9Sstevel@tonic-gate if (!CPU_ACTIVE(&ss->s_cpus[i])) 292*7c478bd9Sstevel@tonic-gate continue; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate if (kstat_add(&ss->s_cpus[i].cs_sys, &ss->s_sys.ss_agg_sys)) 295*7c478bd9Sstevel@tonic-gate return (errno); 296*7c478bd9Sstevel@tonic-gate if (kstat_add(&ss->s_cpus[i].cs_vm, &ss->s_sys.ss_agg_vm)) 297*7c478bd9Sstevel@tonic-gate return (errno); 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate return (0); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate struct snapshot * 304*7c478bd9Sstevel@tonic-gate acquire_snapshot(kstat_ctl_t *kc, int types, struct iodev_filter *iodev_filter) 305*7c478bd9Sstevel@tonic-gate { 306*7c478bd9Sstevel@tonic-gate struct snapshot *ss = NULL; 307*7c478bd9Sstevel@tonic-gate int err; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate retry: 310*7c478bd9Sstevel@tonic-gate err = 0; 311*7c478bd9Sstevel@tonic-gate /* ensure any partial resources are freed on a retry */ 312*7c478bd9Sstevel@tonic-gate free_snapshot(ss); 313*7c478bd9Sstevel@tonic-gate 314*7c478bd9Sstevel@tonic-gate ss = safe_alloc(sizeof (struct snapshot)); 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate (void) memset(ss, 0, sizeof (struct snapshot)); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate ss->s_types = types; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate /* wait for a possibly up-to-date chain */ 321*7c478bd9Sstevel@tonic-gate while (kstat_chain_update(kc) == -1) { 322*7c478bd9Sstevel@tonic-gate if (errno == EAGAIN) 323*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, RETRY_DELAY); 324*7c478bd9Sstevel@tonic-gate else 325*7c478bd9Sstevel@tonic-gate fail(1, "kstat_chain_update failed"); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate if (types & SNAP_FLUSHES) { 329*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 330*7c478bd9Sstevel@tonic-gate ksp = kstat_lookup(kc, "unix", 0, "flushmeter"); 331*7c478bd9Sstevel@tonic-gate if (ksp == NULL) { 332*7c478bd9Sstevel@tonic-gate fail(0, "This machine does not have " 333*7c478bd9Sstevel@tonic-gate "a virtual address cache"); 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, ksp, &ss->s_flushes) == -1) 336*7c478bd9Sstevel@tonic-gate err = errno; 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate if (!err && (types & SNAP_INTERRUPTS)) 340*7c478bd9Sstevel@tonic-gate err = acquire_intrs(ss, kc); 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate if (!err && (types & (SNAP_CPUS | SNAP_SYSTEM | SNAP_PSETS))) 343*7c478bd9Sstevel@tonic-gate err = acquire_cpus(ss, kc); 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate if (!err && (types & SNAP_PSETS)) 346*7c478bd9Sstevel@tonic-gate err = acquire_psets(ss); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate if (!err && (types & (SNAP_IODEVS | SNAP_CONTROLLERS | SNAP_IOPATHS))) 349*7c478bd9Sstevel@tonic-gate err = acquire_iodevs(ss, kc, iodev_filter); 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if (!err && (types & SNAP_SYSTEM)) 352*7c478bd9Sstevel@tonic-gate err = acquire_sys(ss, kc); 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate switch (err) { 355*7c478bd9Sstevel@tonic-gate case 0: 356*7c478bd9Sstevel@tonic-gate break; 357*7c478bd9Sstevel@tonic-gate case EAGAIN: 358*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, RETRY_DELAY); 359*7c478bd9Sstevel@tonic-gate /* a kstat disappeared from under us */ 360*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 361*7c478bd9Sstevel@tonic-gate case ENXIO: 362*7c478bd9Sstevel@tonic-gate case ENOENT: 363*7c478bd9Sstevel@tonic-gate goto retry; 364*7c478bd9Sstevel@tonic-gate default: 365*7c478bd9Sstevel@tonic-gate fail(1, "acquiring snapshot failed"); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate return (ss); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate void 372*7c478bd9Sstevel@tonic-gate free_snapshot(struct snapshot *ss) 373*7c478bd9Sstevel@tonic-gate { 374*7c478bd9Sstevel@tonic-gate size_t i; 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate if (ss == NULL) 377*7c478bd9Sstevel@tonic-gate return; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate while (ss->s_iodevs) { 380*7c478bd9Sstevel@tonic-gate struct iodev_snapshot *tmp = ss->s_iodevs; 381*7c478bd9Sstevel@tonic-gate ss->s_iodevs = ss->s_iodevs->is_next; 382*7c478bd9Sstevel@tonic-gate free_iodev(tmp); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate if (ss->s_cpus) { 386*7c478bd9Sstevel@tonic-gate for (i = 0; i < ss->s_nr_cpus; i++) { 387*7c478bd9Sstevel@tonic-gate free(ss->s_cpus[i].cs_vm.ks_data); 388*7c478bd9Sstevel@tonic-gate free(ss->s_cpus[i].cs_sys.ks_data); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate free(ss->s_cpus); 391*7c478bd9Sstevel@tonic-gate } 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate if (ss->s_psets) { 394*7c478bd9Sstevel@tonic-gate for (i = 0; i < ss->s_nr_psets; i++) 395*7c478bd9Sstevel@tonic-gate free(ss->s_psets[i].ps_cpus); 396*7c478bd9Sstevel@tonic-gate free(ss->s_psets); 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate 399*7c478bd9Sstevel@tonic-gate free(ss->s_sys.ss_agg_sys.ks_data); 400*7c478bd9Sstevel@tonic-gate free(ss->s_sys.ss_agg_vm.ks_data); 401*7c478bd9Sstevel@tonic-gate free(ss); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate kstat_ctl_t * 405*7c478bd9Sstevel@tonic-gate open_kstat(void) 406*7c478bd9Sstevel@tonic-gate { 407*7c478bd9Sstevel@tonic-gate kstat_ctl_t *kc; 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate while ((kc = kstat_open()) == NULL) { 410*7c478bd9Sstevel@tonic-gate if (errno == EAGAIN) 411*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, RETRY_DELAY); 412*7c478bd9Sstevel@tonic-gate else 413*7c478bd9Sstevel@tonic-gate fail(1, "kstat_open failed"); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate return (kc); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 420*7c478bd9Sstevel@tonic-gate void 421*7c478bd9Sstevel@tonic-gate fail(int do_perror, char *message, ...) 422*7c478bd9Sstevel@tonic-gate { 423*7c478bd9Sstevel@tonic-gate va_list args; 424*7c478bd9Sstevel@tonic-gate int save_errno = errno; 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate va_start(args, message); 427*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", cmdname); 428*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, message, args); 429*7c478bd9Sstevel@tonic-gate va_end(args); 430*7c478bd9Sstevel@tonic-gate if (do_perror) 431*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, ": %s", strerror(save_errno)); 432*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 433*7c478bd9Sstevel@tonic-gate exit(2); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate void * 437*7c478bd9Sstevel@tonic-gate safe_alloc(size_t size) 438*7c478bd9Sstevel@tonic-gate { 439*7c478bd9Sstevel@tonic-gate void *ptr; 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate while ((ptr = malloc(size)) == NULL) { 442*7c478bd9Sstevel@tonic-gate if (errno == EAGAIN) 443*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, RETRY_DELAY); 444*7c478bd9Sstevel@tonic-gate else 445*7c478bd9Sstevel@tonic-gate fail(1, "malloc failed"); 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate return (ptr); 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate char * 451*7c478bd9Sstevel@tonic-gate safe_strdup(char *str) 452*7c478bd9Sstevel@tonic-gate { 453*7c478bd9Sstevel@tonic-gate char *ret; 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate if (str == NULL) 456*7c478bd9Sstevel@tonic-gate return (NULL); 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate while ((ret = strdup(str)) == NULL) { 459*7c478bd9Sstevel@tonic-gate if (errno == EAGAIN) 460*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, RETRY_DELAY); 461*7c478bd9Sstevel@tonic-gate else 462*7c478bd9Sstevel@tonic-gate fail(1, "malloc failed"); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate return (ret); 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate uint64_t 468*7c478bd9Sstevel@tonic-gate kstat_delta(kstat_t *old, kstat_t *new, char *name) 469*7c478bd9Sstevel@tonic-gate { 470*7c478bd9Sstevel@tonic-gate kstat_named_t *knew = kstat_data_lookup(new, name); 471*7c478bd9Sstevel@tonic-gate if (old && old->ks_data) { 472*7c478bd9Sstevel@tonic-gate kstat_named_t *kold = kstat_data_lookup(old, name); 473*7c478bd9Sstevel@tonic-gate return (knew->value.ui64 - kold->value.ui64); 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate return (knew->value.ui64); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate int 479*7c478bd9Sstevel@tonic-gate kstat_copy(const kstat_t *src, kstat_t *dst) 480*7c478bd9Sstevel@tonic-gate { 481*7c478bd9Sstevel@tonic-gate *dst = *src; 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate if (src->ks_data != NULL) { 484*7c478bd9Sstevel@tonic-gate if ((dst->ks_data = malloc(src->ks_data_size)) == NULL) 485*7c478bd9Sstevel@tonic-gate return (-1); 486*7c478bd9Sstevel@tonic-gate bcopy(src->ks_data, dst->ks_data, src->ks_data_size); 487*7c478bd9Sstevel@tonic-gate } else { 488*7c478bd9Sstevel@tonic-gate dst->ks_data = NULL; 489*7c478bd9Sstevel@tonic-gate dst->ks_data_size = 0; 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate return (0); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate int 495*7c478bd9Sstevel@tonic-gate kstat_add(const kstat_t *src, kstat_t *dst) 496*7c478bd9Sstevel@tonic-gate { 497*7c478bd9Sstevel@tonic-gate size_t i; 498*7c478bd9Sstevel@tonic-gate kstat_named_t *from; 499*7c478bd9Sstevel@tonic-gate kstat_named_t *to; 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate if (dst->ks_data == NULL) 502*7c478bd9Sstevel@tonic-gate return (kstat_copy(src, dst)); 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate from = src->ks_data; 505*7c478bd9Sstevel@tonic-gate to = dst->ks_data; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate for (i = 0; i < src->ks_ndata; i++) { 508*7c478bd9Sstevel@tonic-gate /* "addition" makes little sense for strings */ 509*7c478bd9Sstevel@tonic-gate if (from->data_type != KSTAT_DATA_CHAR && 510*7c478bd9Sstevel@tonic-gate from->data_type != KSTAT_DATA_STRING) 511*7c478bd9Sstevel@tonic-gate (to)->value.ui64 += (from)->value.ui64; 512*7c478bd9Sstevel@tonic-gate from++; 513*7c478bd9Sstevel@tonic-gate to++; 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate return (0); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate uint64_t 520*7c478bd9Sstevel@tonic-gate cpu_ticks_delta(kstat_t *old, kstat_t *new) 521*7c478bd9Sstevel@tonic-gate { 522*7c478bd9Sstevel@tonic-gate uint64_t ticks = 0; 523*7c478bd9Sstevel@tonic-gate size_t i; 524*7c478bd9Sstevel@tonic-gate for (i = 0; i < ARRAY_SIZE(cpu_states); i++) 525*7c478bd9Sstevel@tonic-gate ticks += kstat_delta(old, new, cpu_states[i]); 526*7c478bd9Sstevel@tonic-gate return (ticks); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate int 530*7c478bd9Sstevel@tonic-gate nr_active_cpus(struct snapshot *ss) 531*7c478bd9Sstevel@tonic-gate { 532*7c478bd9Sstevel@tonic-gate size_t i; 533*7c478bd9Sstevel@tonic-gate int count = 0; 534*7c478bd9Sstevel@tonic-gate for (i = 0; i < ss->s_nr_cpus; i++) { 535*7c478bd9Sstevel@tonic-gate if (CPU_ACTIVE(&ss->s_cpus[i])) 536*7c478bd9Sstevel@tonic-gate count++; 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate return (count); 540*7c478bd9Sstevel@tonic-gate } 541