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 1995-2002 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #include <stdio.h> 29*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 30*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 31*7c478bd9Sstevel@tonic-gate #include <unistd.h> /* sleep() */ 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <errno.h> 34*7c478bd9Sstevel@tonic-gate #include <syslog.h> 35*7c478bd9Sstevel@tonic-gate #include <thread.h> 36*7c478bd9Sstevel@tonic-gate #include <time.h> 37*7c478bd9Sstevel@tonic-gate #include <kstat.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/sysinfo.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 40*7c478bd9Sstevel@tonic-gate #include "powerd.h" 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate /* 43*7c478bd9Sstevel@tonic-gate * External Variables 44*7c478bd9Sstevel@tonic-gate */ 45*7c478bd9Sstevel@tonic-gate extern pwr_info_t *info; 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * State Variables 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate static kstat_ctl_t *kc; /* libkstat cookie */ 51*7c478bd9Sstevel@tonic-gate static int ncpus; 52*7c478bd9Sstevel@tonic-gate static kstat_t **cpu_stats_list = NULL; 53*7c478bd9Sstevel@tonic-gate static kstat_t old_cpu_stats, new_cpu_stats; 54*7c478bd9Sstevel@tonic-gate static hrtime_t tty_snaptime; 55*7c478bd9Sstevel@tonic-gate static kstat_t *load_ave_ksp; 56*7c478bd9Sstevel@tonic-gate static ulong_t load_ave; 57*7c478bd9Sstevel@tonic-gate static hrtime_t last_load_ave_change; 58*7c478bd9Sstevel@tonic-gate static kstat_t *conskbd_ksp, *consms_ksp; 59*7c478bd9Sstevel@tonic-gate static kstat_t *nfs_client2_kstat, *nfs_client3_kstat; 60*7c478bd9Sstevel@tonic-gate static kstat_t *nfs_server2_kstat, *nfs_server3_kstat; 61*7c478bd9Sstevel@tonic-gate static uint64_t old_nfs_calls, new_nfs_calls; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate typedef struct activity_data { 64*7c478bd9Sstevel@tonic-gate struct activity_data *next; 65*7c478bd9Sstevel@tonic-gate struct activity_data *prev; 66*7c478bd9Sstevel@tonic-gate int activity_delta; 67*7c478bd9Sstevel@tonic-gate hrtime_t snaptime; 68*7c478bd9Sstevel@tonic-gate } activity_data_t; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate #define NULLACTIVITY (activity_data_t *)0 71*7c478bd9Sstevel@tonic-gate static activity_data_t *disk_act_start = NULLACTIVITY; 72*7c478bd9Sstevel@tonic-gate static activity_data_t *disk_act_end = NULLACTIVITY; 73*7c478bd9Sstevel@tonic-gate static activity_data_t *tty_act_start = NULLACTIVITY; 74*7c478bd9Sstevel@tonic-gate static activity_data_t *tty_act_end = NULLACTIVITY; 75*7c478bd9Sstevel@tonic-gate static activity_data_t *nfs_act_start = NULLACTIVITY; 76*7c478bd9Sstevel@tonic-gate static activity_data_t *nfs_act_end = NULLACTIVITY; 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate struct diskinfo { 79*7c478bd9Sstevel@tonic-gate struct diskinfo *next; 80*7c478bd9Sstevel@tonic-gate kstat_t *ks; 81*7c478bd9Sstevel@tonic-gate kstat_io_t new_kios, old_kios; 82*7c478bd9Sstevel@tonic-gate }; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate #define NULLDISK (struct diskinfo *)0 85*7c478bd9Sstevel@tonic-gate static struct diskinfo zerodisk = { NULL, NULL }; 86*7c478bd9Sstevel@tonic-gate static struct diskinfo *firstdisk = NULLDISK; 87*7c478bd9Sstevel@tonic-gate static struct diskinfo *lastdisk = NULLDISK; 88*7c478bd9Sstevel@tonic-gate static struct diskinfo *snip = NULLDISK; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate #define CPU_STAT(ksp, name) (((kstat_named_t *)safe_kstat_data_lookup( \ 91*7c478bd9Sstevel@tonic-gate (ksp), (name)))->value.ui64) 92*7c478bd9Sstevel@tonic-gate #define DISK_DELTA(x) (disk->new_kios.x - disk->old_kios.x) 93*7c478bd9Sstevel@tonic-gate #define CPU_DELTA(x) (CPU_STAT(&new_cpu_stats, (x)) - \ 94*7c478bd9Sstevel@tonic-gate CPU_STAT(&old_cpu_stats, (x))) 95*7c478bd9Sstevel@tonic-gate #define FSHIFT 8 96*7c478bd9Sstevel@tonic-gate #define FSCALE (1<<FSHIFT) 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate /* 99*7c478bd9Sstevel@tonic-gate * Local Functions 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate static void init_all(void); 102*7c478bd9Sstevel@tonic-gate static void init_disks(void); 103*7c478bd9Sstevel@tonic-gate static void cpu_stats_init(void); 104*7c478bd9Sstevel@tonic-gate static void load_ave_init(void); 105*7c478bd9Sstevel@tonic-gate static void nfs_init(void); 106*7c478bd9Sstevel@tonic-gate static void conskbd_init(void); 107*7c478bd9Sstevel@tonic-gate static void consms_init(void); 108*7c478bd9Sstevel@tonic-gate static int diskinfo_load(void); 109*7c478bd9Sstevel@tonic-gate static int cpu_stats_load(void); 110*7c478bd9Sstevel@tonic-gate static int load_ave_load(void); 111*7c478bd9Sstevel@tonic-gate static int nfs_load(void); 112*7c478bd9Sstevel@tonic-gate static void fail(char *, ...); 113*7c478bd9Sstevel@tonic-gate static void safe_zalloc(void **, int, int); 114*7c478bd9Sstevel@tonic-gate static void *safe_kstat_data_lookup(kstat_t *, char *); 115*7c478bd9Sstevel@tonic-gate static int kscmp(kstat_t *, kstat_t *); 116*7c478bd9Sstevel@tonic-gate static void keep_activity_data(activity_data_t **, activity_data_t **, 117*7c478bd9Sstevel@tonic-gate int *, int, hrtime_t); 118*7c478bd9Sstevel@tonic-gate static int check_activity(activity_data_t *, int, hrtime_t *, int); 119*7c478bd9Sstevel@tonic-gate static void kstat_copy(kstat_t *, kstat_t *, int); 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate void 122*7c478bd9Sstevel@tonic-gate sysstat_init() 123*7c478bd9Sstevel@tonic-gate { 124*7c478bd9Sstevel@tonic-gate info->pd_ttychars_sum = 0; 125*7c478bd9Sstevel@tonic-gate info->pd_loadaverage = 0; 126*7c478bd9Sstevel@tonic-gate info->pd_diskreads_sum = 0; 127*7c478bd9Sstevel@tonic-gate info->pd_nfsreqs_sum = 0; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate if ((kc = kstat_open()) == NULL) { 130*7c478bd9Sstevel@tonic-gate fail("kstat_open(): can't open /dev/kstat"); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate init_all(); 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate static void 136*7c478bd9Sstevel@tonic-gate init_all(void) 137*7c478bd9Sstevel@tonic-gate { 138*7c478bd9Sstevel@tonic-gate char *msg = "kstat_read(): can't read kstat"; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate init_disks(); 141*7c478bd9Sstevel@tonic-gate if (diskinfo_load() != 0) { 142*7c478bd9Sstevel@tonic-gate fail(msg); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate cpu_stats_init(); 146*7c478bd9Sstevel@tonic-gate if (cpu_stats_load() != 0) { 147*7c478bd9Sstevel@tonic-gate fail(msg); 148*7c478bd9Sstevel@tonic-gate } 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate load_ave_init(); 151*7c478bd9Sstevel@tonic-gate last_load_ave_change = gethrtime(); 152*7c478bd9Sstevel@tonic-gate if (load_ave_load() != 0) { 153*7c478bd9Sstevel@tonic-gate fail(msg); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate nfs_init(); 157*7c478bd9Sstevel@tonic-gate if (nfs_load() != 0) { 158*7c478bd9Sstevel@tonic-gate fail(msg); 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate conskbd_init(); 161*7c478bd9Sstevel@tonic-gate consms_init(); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate int 165*7c478bd9Sstevel@tonic-gate last_disk_activity(hrtime_t *hr_now, int threshold) 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate return (check_activity(disk_act_start, info->pd_diskreads_sum, hr_now, 168*7c478bd9Sstevel@tonic-gate threshold)); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate int 172*7c478bd9Sstevel@tonic-gate last_tty_activity(hrtime_t *hr_now, int threshold) 173*7c478bd9Sstevel@tonic-gate { 174*7c478bd9Sstevel@tonic-gate return (check_activity(tty_act_start, info->pd_ttychars_sum, hr_now, 175*7c478bd9Sstevel@tonic-gate threshold)); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate int 179*7c478bd9Sstevel@tonic-gate last_load_ave_activity(hrtime_t *hr_now) 180*7c478bd9Sstevel@tonic-gate { 181*7c478bd9Sstevel@tonic-gate return ((*hr_now - last_load_ave_change) / NANOSEC); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate int 185*7c478bd9Sstevel@tonic-gate last_nfs_activity(hrtime_t *hr_now, int threshold) 186*7c478bd9Sstevel@tonic-gate { 187*7c478bd9Sstevel@tonic-gate return (check_activity(nfs_act_start, info->pd_nfsreqs_sum, hr_now, 188*7c478bd9Sstevel@tonic-gate threshold)); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate static void 192*7c478bd9Sstevel@tonic-gate init_disks(void) 193*7c478bd9Sstevel@tonic-gate { 194*7c478bd9Sstevel@tonic-gate struct diskinfo *disk, *prevdisk, *comp; 195*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate disk = &zerodisk; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate /* 200*7c478bd9Sstevel@tonic-gate * Patch the snip in the diskinfo list (see below) 201*7c478bd9Sstevel@tonic-gate */ 202*7c478bd9Sstevel@tonic-gate if (snip) { 203*7c478bd9Sstevel@tonic-gate lastdisk->next = snip; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 207*7c478bd9Sstevel@tonic-gate if (ksp->ks_type != KSTAT_TYPE_IO || 208*7c478bd9Sstevel@tonic-gate strcmp(ksp->ks_class, "disk") != 0) { 209*7c478bd9Sstevel@tonic-gate continue; 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate prevdisk = disk; 212*7c478bd9Sstevel@tonic-gate if (disk->next) { 213*7c478bd9Sstevel@tonic-gate disk = disk->next; 214*7c478bd9Sstevel@tonic-gate } else { 215*7c478bd9Sstevel@tonic-gate safe_zalloc((void **)&disk->next, 216*7c478bd9Sstevel@tonic-gate sizeof (struct diskinfo), 0); 217*7c478bd9Sstevel@tonic-gate disk = disk->next; 218*7c478bd9Sstevel@tonic-gate disk->next = NULLDISK; 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate disk->ks = ksp; 221*7c478bd9Sstevel@tonic-gate (void *) memset((void *)&disk->new_kios, 0, 222*7c478bd9Sstevel@tonic-gate sizeof (kstat_io_t)); 223*7c478bd9Sstevel@tonic-gate disk->new_kios.wlastupdate = disk->ks->ks_crtime; 224*7c478bd9Sstevel@tonic-gate disk->new_kios.rlastupdate = disk->ks->ks_crtime; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * Insertion sort on (ks_module, ks_instance, ks_name) 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate comp = &zerodisk; 230*7c478bd9Sstevel@tonic-gate while (kscmp(disk->ks, comp->next->ks) > 0) { 231*7c478bd9Sstevel@tonic-gate comp = comp->next; 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate if (prevdisk != comp) { 234*7c478bd9Sstevel@tonic-gate prevdisk->next = disk->next; 235*7c478bd9Sstevel@tonic-gate disk->next = comp->next; 236*7c478bd9Sstevel@tonic-gate comp->next = disk; 237*7c478bd9Sstevel@tonic-gate disk = prevdisk; 238*7c478bd9Sstevel@tonic-gate } 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate /* 241*7c478bd9Sstevel@tonic-gate * Put a snip in the linked list of diskinfos. The idea: 242*7c478bd9Sstevel@tonic-gate * If there was a state change such that now there are fewer 243*7c478bd9Sstevel@tonic-gate * disks, we snip the list and retain the tail, rather than 244*7c478bd9Sstevel@tonic-gate * freeing it. At the next state change, we clip the tail back on. 245*7c478bd9Sstevel@tonic-gate * This prevents a lot of malloc/free activity, and it's simpler. 246*7c478bd9Sstevel@tonic-gate */ 247*7c478bd9Sstevel@tonic-gate lastdisk = disk; 248*7c478bd9Sstevel@tonic-gate snip = disk->next; 249*7c478bd9Sstevel@tonic-gate disk->next = NULLDISK; 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate firstdisk = zerodisk.next; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate static int 255*7c478bd9Sstevel@tonic-gate diskinfo_load(void) 256*7c478bd9Sstevel@tonic-gate { 257*7c478bd9Sstevel@tonic-gate struct diskinfo *disk; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate for (disk = firstdisk; disk; disk = disk->next) { 260*7c478bd9Sstevel@tonic-gate disk->old_kios = disk->new_kios; 261*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, disk->ks, 262*7c478bd9Sstevel@tonic-gate (void *)&disk->new_kios) == -1) { 263*7c478bd9Sstevel@tonic-gate return (1); 264*7c478bd9Sstevel@tonic-gate } 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate return (0); 268*7c478bd9Sstevel@tonic-gate } 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate int 271*7c478bd9Sstevel@tonic-gate check_disks(hrtime_t *hr_now, int threshold) 272*7c478bd9Sstevel@tonic-gate { 273*7c478bd9Sstevel@tonic-gate struct diskinfo *disk; 274*7c478bd9Sstevel@tonic-gate int delta = 0; 275*7c478bd9Sstevel@tonic-gate hrtime_t time = 0; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate while (kstat_chain_update(kc) || diskinfo_load()) { 278*7c478bd9Sstevel@tonic-gate init_all(); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate for (disk = firstdisk; disk; disk = disk->next) { 281*7c478bd9Sstevel@tonic-gate if (time == 0) { 282*7c478bd9Sstevel@tonic-gate time = disk->new_kios.wlastupdate; 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate delta += DISK_DELTA(reads); 285*7c478bd9Sstevel@tonic-gate if (DISK_DELTA(reads) > 0) { 286*7c478bd9Sstevel@tonic-gate time = MAX(time, disk->new_kios.wlastupdate); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate keep_activity_data(&disk_act_start, &disk_act_end, 290*7c478bd9Sstevel@tonic-gate &info->pd_diskreads_sum, delta, time); 291*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 292*7c478bd9Sstevel@tonic-gate (void) printf(" Disk reads = %d\n", delta); 293*7c478bd9Sstevel@tonic-gate #endif 294*7c478bd9Sstevel@tonic-gate return (check_activity(disk_act_start, info->pd_diskreads_sum, hr_now, 295*7c478bd9Sstevel@tonic-gate threshold)); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate static void 299*7c478bd9Sstevel@tonic-gate cpu_stats_init(void) 300*7c478bd9Sstevel@tonic-gate { 301*7c478bd9Sstevel@tonic-gate kstat_t *ksp; 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate ncpus = 0; 304*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 305*7c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "cpu") == 0 && 306*7c478bd9Sstevel@tonic-gate strcmp(ksp->ks_name, "sys") == 0) 307*7c478bd9Sstevel@tonic-gate ncpus++; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate safe_zalloc((void **)&cpu_stats_list, ncpus * sizeof (*cpu_stats_list), 311*7c478bd9Sstevel@tonic-gate 1); 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate ncpus = 0; 314*7c478bd9Sstevel@tonic-gate for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { 315*7c478bd9Sstevel@tonic-gate if (strcmp(ksp->ks_module, "cpu") == 0 && 316*7c478bd9Sstevel@tonic-gate strcmp(ksp->ks_name, "sys") == 0 && 317*7c478bd9Sstevel@tonic-gate kstat_read(kc, ksp, NULL) != -1) 318*7c478bd9Sstevel@tonic-gate cpu_stats_list[ncpus++] = ksp; 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if (ncpus == 0) 322*7c478bd9Sstevel@tonic-gate fail("can't find any cpu statistics"); 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate static int 326*7c478bd9Sstevel@tonic-gate cpu_stats_load(void) 327*7c478bd9Sstevel@tonic-gate { 328*7c478bd9Sstevel@tonic-gate int i, j; 329*7c478bd9Sstevel@tonic-gate kstat_named_t *nkp, *tkp; 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate tty_snaptime = 0; 332*7c478bd9Sstevel@tonic-gate kstat_copy(&new_cpu_stats, &old_cpu_stats, 1); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate /* 335*7c478bd9Sstevel@tonic-gate * Sum across all cpus 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate for (i = 0; i < ncpus; i++) { 338*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, cpu_stats_list[i], NULL) == -1) 339*7c478bd9Sstevel@tonic-gate return (1); 340*7c478bd9Sstevel@tonic-gate 341*7c478bd9Sstevel@tonic-gate if (i == 0) { 342*7c478bd9Sstevel@tonic-gate kstat_copy(cpu_stats_list[i], &new_cpu_stats, 1); 343*7c478bd9Sstevel@tonic-gate continue; 344*7c478bd9Sstevel@tonic-gate } else { 345*7c478bd9Sstevel@tonic-gate /* 346*7c478bd9Sstevel@tonic-gate * Other CPUs' statistics are accumulated in 347*7c478bd9Sstevel@tonic-gate * new_cpu_stats, initialized at the first iteration of 348*7c478bd9Sstevel@tonic-gate * the loop. 349*7c478bd9Sstevel@tonic-gate */ 350*7c478bd9Sstevel@tonic-gate nkp = (kstat_named_t *)new_cpu_stats.ks_data; 351*7c478bd9Sstevel@tonic-gate tkp = (kstat_named_t *)cpu_stats_list[i]->ks_data; 352*7c478bd9Sstevel@tonic-gate for (j = 0; j < cpu_stats_list[i]->ks_ndata; j++) 353*7c478bd9Sstevel@tonic-gate (nkp++)->value.ui64 += (tkp++)->value.ui64; 354*7c478bd9Sstevel@tonic-gate tty_snaptime = MAX(tty_snaptime, 355*7c478bd9Sstevel@tonic-gate cpu_stats_list[i]->ks_snaptime); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate return (0); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate int 363*7c478bd9Sstevel@tonic-gate check_tty(hrtime_t *hr_now, int threshold) 364*7c478bd9Sstevel@tonic-gate { 365*7c478bd9Sstevel@tonic-gate int delta; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate while (kstat_chain_update(kc) || cpu_stats_load()) { 368*7c478bd9Sstevel@tonic-gate init_all(); 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate delta = CPU_DELTA("rawch") + CPU_DELTA("outch"); 371*7c478bd9Sstevel@tonic-gate keep_activity_data(&tty_act_start, &tty_act_end, 372*7c478bd9Sstevel@tonic-gate &info->pd_ttychars_sum, delta, tty_snaptime); 373*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 374*7c478bd9Sstevel@tonic-gate (void) printf(" Tty chars = %d\n", delta); 375*7c478bd9Sstevel@tonic-gate #endif 376*7c478bd9Sstevel@tonic-gate return (check_activity(tty_act_start, info->pd_ttychars_sum, hr_now, 377*7c478bd9Sstevel@tonic-gate threshold)); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate static void 381*7c478bd9Sstevel@tonic-gate load_ave_init(void) 382*7c478bd9Sstevel@tonic-gate { 383*7c478bd9Sstevel@tonic-gate if ((load_ave_ksp = kstat_lookup(kc, "unix", 0, "system_misc")) == 384*7c478bd9Sstevel@tonic-gate NULL) { 385*7c478bd9Sstevel@tonic-gate fail("kstat_lookup('unix', 0, 'system_misc') failed"); 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate static int 390*7c478bd9Sstevel@tonic-gate load_ave_load(void) 391*7c478bd9Sstevel@tonic-gate { 392*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, load_ave_ksp, NULL) == -1) { 393*7c478bd9Sstevel@tonic-gate return (1); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate load_ave = ((kstat_named_t *)safe_kstat_data_lookup( 396*7c478bd9Sstevel@tonic-gate load_ave_ksp, "avenrun_1min"))->value.l; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate return (0); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate int 402*7c478bd9Sstevel@tonic-gate check_load_ave(hrtime_t *hr_now, float threshold) 403*7c478bd9Sstevel@tonic-gate { 404*7c478bd9Sstevel@tonic-gate while (kstat_chain_update(kc) || load_ave_load()) { 405*7c478bd9Sstevel@tonic-gate init_all(); 406*7c478bd9Sstevel@tonic-gate } 407*7c478bd9Sstevel@tonic-gate info->pd_loadaverage = (double)load_ave / FSCALE; 408*7c478bd9Sstevel@tonic-gate if (info->pd_loadaverage > threshold) { 409*7c478bd9Sstevel@tonic-gate last_load_ave_change = load_ave_ksp->ks_snaptime; 410*7c478bd9Sstevel@tonic-gate } 411*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 412*7c478bd9Sstevel@tonic-gate (void) printf(" Load average = %f\n", ((double)load_ave / FSCALE)); 413*7c478bd9Sstevel@tonic-gate #endif 414*7c478bd9Sstevel@tonic-gate return ((*hr_now - last_load_ave_change) / NANOSEC); 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate static void 418*7c478bd9Sstevel@tonic-gate nfs_init(void) 419*7c478bd9Sstevel@tonic-gate { 420*7c478bd9Sstevel@tonic-gate nfs_client2_kstat = kstat_lookup(kc, "nfs", 0, "rfsreqcnt_v2"); 421*7c478bd9Sstevel@tonic-gate nfs_client3_kstat = kstat_lookup(kc, "nfs", 0, "rfsreqcnt_v3"); 422*7c478bd9Sstevel@tonic-gate nfs_server2_kstat = kstat_lookup(kc, "nfs", 0, "rfsproccnt_v2"); 423*7c478bd9Sstevel@tonic-gate nfs_server3_kstat = kstat_lookup(kc, "nfs", 0, "rfsproccnt_v3"); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate static int 427*7c478bd9Sstevel@tonic-gate nfs_load(void) 428*7c478bd9Sstevel@tonic-gate { 429*7c478bd9Sstevel@tonic-gate kstat_named_t *kstat_ptr; 430*7c478bd9Sstevel@tonic-gate int index; 431*7c478bd9Sstevel@tonic-gate uint64_t total_calls = 0; 432*7c478bd9Sstevel@tonic-gate uint64_t getattr_calls = 0; 433*7c478bd9Sstevel@tonic-gate uint64_t null_calls = 0; 434*7c478bd9Sstevel@tonic-gate uint64_t access_calls = 0; 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate if (!nfs_client2_kstat && !nfs_client3_kstat && !nfs_server2_kstat && 437*7c478bd9Sstevel@tonic-gate !nfs_server3_kstat) { 438*7c478bd9Sstevel@tonic-gate return (0); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate /* 442*7c478bd9Sstevel@tonic-gate * NFS client "getattr", NFS3 client "access", and NFS server "null" 443*7c478bd9Sstevel@tonic-gate * requests are excluded from consideration. 444*7c478bd9Sstevel@tonic-gate */ 445*7c478bd9Sstevel@tonic-gate if (nfs_client2_kstat) { 446*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, nfs_client2_kstat, NULL) == -1) { 447*7c478bd9Sstevel@tonic-gate return (1); 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate kstat_ptr = KSTAT_NAMED_PTR(nfs_client2_kstat); 450*7c478bd9Sstevel@tonic-gate for (index = 0; index < nfs_client2_kstat->ks_ndata; index++) { 451*7c478bd9Sstevel@tonic-gate total_calls += kstat_ptr[index].value.ui64; 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate getattr_calls = 454*7c478bd9Sstevel@tonic-gate ((kstat_named_t *)safe_kstat_data_lookup( 455*7c478bd9Sstevel@tonic-gate nfs_client2_kstat, "getattr"))->value.ui64; 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate if (nfs_client3_kstat) { 459*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, nfs_client3_kstat, NULL) == -1) { 460*7c478bd9Sstevel@tonic-gate return (1); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate kstat_ptr = KSTAT_NAMED_PTR(nfs_client3_kstat); 463*7c478bd9Sstevel@tonic-gate for (index = 0; index < nfs_client3_kstat->ks_ndata; index++) { 464*7c478bd9Sstevel@tonic-gate total_calls += kstat_ptr[index].value.ui64; 465*7c478bd9Sstevel@tonic-gate } 466*7c478bd9Sstevel@tonic-gate getattr_calls += 467*7c478bd9Sstevel@tonic-gate ((kstat_named_t *)safe_kstat_data_lookup( 468*7c478bd9Sstevel@tonic-gate nfs_client3_kstat, "getattr"))->value.ui64; 469*7c478bd9Sstevel@tonic-gate access_calls = 470*7c478bd9Sstevel@tonic-gate ((kstat_named_t *)safe_kstat_data_lookup( 471*7c478bd9Sstevel@tonic-gate nfs_client3_kstat, "access"))->value.ui64; 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate if (nfs_server2_kstat) { 475*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, nfs_server2_kstat, NULL) == -1) { 476*7c478bd9Sstevel@tonic-gate return (1); 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate kstat_ptr = KSTAT_NAMED_PTR(nfs_server2_kstat); 479*7c478bd9Sstevel@tonic-gate for (index = 0; index < nfs_server2_kstat->ks_ndata; index++) { 480*7c478bd9Sstevel@tonic-gate total_calls += kstat_ptr[index].value.ui64; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate null_calls = 483*7c478bd9Sstevel@tonic-gate ((kstat_named_t *)safe_kstat_data_lookup( 484*7c478bd9Sstevel@tonic-gate nfs_server2_kstat, "null"))->value.ui64; 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate if (nfs_server3_kstat) { 488*7c478bd9Sstevel@tonic-gate if (kstat_read(kc, nfs_server3_kstat, NULL) == -1) { 489*7c478bd9Sstevel@tonic-gate return (1); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate kstat_ptr = KSTAT_NAMED_PTR(nfs_server3_kstat); 492*7c478bd9Sstevel@tonic-gate for (index = 0; index < nfs_server3_kstat->ks_ndata; index++) { 493*7c478bd9Sstevel@tonic-gate total_calls += kstat_ptr[index].value.ui64; 494*7c478bd9Sstevel@tonic-gate } 495*7c478bd9Sstevel@tonic-gate null_calls += 496*7c478bd9Sstevel@tonic-gate ((kstat_named_t *)safe_kstat_data_lookup( 497*7c478bd9Sstevel@tonic-gate nfs_server3_kstat, "null"))->value.ui64; 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate old_nfs_calls = new_nfs_calls; 501*7c478bd9Sstevel@tonic-gate new_nfs_calls = total_calls - 502*7c478bd9Sstevel@tonic-gate (getattr_calls + access_calls + null_calls); 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate return (0); 505*7c478bd9Sstevel@tonic-gate } 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate int 508*7c478bd9Sstevel@tonic-gate check_nfs(hrtime_t *hr_now, int threshold) 509*7c478bd9Sstevel@tonic-gate { 510*7c478bd9Sstevel@tonic-gate int delta; 511*7c478bd9Sstevel@tonic-gate hrtime_t time = 0; 512*7c478bd9Sstevel@tonic-gate 513*7c478bd9Sstevel@tonic-gate while (kstat_chain_update(kc) || nfs_load()) { 514*7c478bd9Sstevel@tonic-gate init_all(); 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate if (!nfs_client2_kstat && !nfs_client3_kstat && !nfs_server2_kstat && 518*7c478bd9Sstevel@tonic-gate !nfs_server3_kstat) { 519*7c478bd9Sstevel@tonic-gate return (0); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate if (nfs_client2_kstat) { 523*7c478bd9Sstevel@tonic-gate time = MAX(time, nfs_client2_kstat->ks_snaptime); 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate if (nfs_client3_kstat) { 526*7c478bd9Sstevel@tonic-gate time = MAX(time, nfs_client3_kstat->ks_snaptime); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate if (nfs_server2_kstat) { 529*7c478bd9Sstevel@tonic-gate time = MAX(time, nfs_server2_kstat->ks_snaptime); 530*7c478bd9Sstevel@tonic-gate } 531*7c478bd9Sstevel@tonic-gate if (nfs_server3_kstat) { 532*7c478bd9Sstevel@tonic-gate time = MAX(time, nfs_server3_kstat->ks_snaptime); 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate delta = (int)(new_nfs_calls - old_nfs_calls); 535*7c478bd9Sstevel@tonic-gate keep_activity_data(&nfs_act_start, &nfs_act_end, 536*7c478bd9Sstevel@tonic-gate &info->pd_nfsreqs_sum, delta, time); 537*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 538*7c478bd9Sstevel@tonic-gate (void) printf(" NFS requests = %d\n", delta); 539*7c478bd9Sstevel@tonic-gate #endif 540*7c478bd9Sstevel@tonic-gate return (check_activity(nfs_act_start, info->pd_nfsreqs_sum, hr_now, 541*7c478bd9Sstevel@tonic-gate threshold)); 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate static void 545*7c478bd9Sstevel@tonic-gate conskbd_init(void) 546*7c478bd9Sstevel@tonic-gate { 547*7c478bd9Sstevel@tonic-gate conskbd_ksp = kstat_lookup(kc, "conskbd", 0, "activity"); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate /* 551*7c478bd9Sstevel@tonic-gate * Return the number of seconds since the last keystroke on console keyboard. 552*7c478bd9Sstevel@tonic-gate * Caller responsible for error reporting. 553*7c478bd9Sstevel@tonic-gate */ 554*7c478bd9Sstevel@tonic-gate long 555*7c478bd9Sstevel@tonic-gate conskbd_idle_time(void) 556*7c478bd9Sstevel@tonic-gate { 557*7c478bd9Sstevel@tonic-gate void *p; 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate if (conskbd_ksp == NULL || kstat_read(kc, conskbd_ksp, NULL) == -1 || 560*7c478bd9Sstevel@tonic-gate (p = kstat_data_lookup(conskbd_ksp, "idle_sec")) == NULL) 561*7c478bd9Sstevel@tonic-gate return ((time_t)-1); 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate return (((kstat_named_t *)p)->value.l); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate static void 567*7c478bd9Sstevel@tonic-gate consms_init(void) 568*7c478bd9Sstevel@tonic-gate { 569*7c478bd9Sstevel@tonic-gate consms_ksp = kstat_lookup(kc, "consms", 0, "activity"); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate /* 573*7c478bd9Sstevel@tonic-gate * Return the number of seconds since the most recent action (movement or 574*7c478bd9Sstevel@tonic-gate * click) of the console mouse. Caller responsible for error reporting. 575*7c478bd9Sstevel@tonic-gate */ 576*7c478bd9Sstevel@tonic-gate long 577*7c478bd9Sstevel@tonic-gate consms_idle_time(void) 578*7c478bd9Sstevel@tonic-gate { 579*7c478bd9Sstevel@tonic-gate void *p; 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate if (consms_ksp == NULL || kstat_read(kc, consms_ksp, NULL) == -1 || 582*7c478bd9Sstevel@tonic-gate (p = kstat_data_lookup(consms_ksp, "idle_sec")) == NULL) 583*7c478bd9Sstevel@tonic-gate return ((time_t)-1); 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate return (((kstat_named_t *)p)->value.l); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate static void 589*7c478bd9Sstevel@tonic-gate fail(char *fmt, ...) 590*7c478bd9Sstevel@tonic-gate { 591*7c478bd9Sstevel@tonic-gate char new_fmt[256]; 592*7c478bd9Sstevel@tonic-gate va_list args; 593*7c478bd9Sstevel@tonic-gate size_t len; 594*7c478bd9Sstevel@tonic-gate 595*7c478bd9Sstevel@tonic-gate len = sizeof (new_fmt); 596*7c478bd9Sstevel@tonic-gate va_start(args, fmt); 597*7c478bd9Sstevel@tonic-gate if (snprintf(new_fmt, len, "powerd: %s", fmt) > len) 598*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "powerd: syslog message too large"); 599*7c478bd9Sstevel@tonic-gate else 600*7c478bd9Sstevel@tonic-gate vsyslog(LOG_ERR, new_fmt, args); 601*7c478bd9Sstevel@tonic-gate va_end(args); 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate thr_exit((void *) 0); 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate static void 607*7c478bd9Sstevel@tonic-gate safe_zalloc(void **ptr, int size, int free_first) 608*7c478bd9Sstevel@tonic-gate { 609*7c478bd9Sstevel@tonic-gate if (free_first && *ptr != NULL) { 610*7c478bd9Sstevel@tonic-gate free(*ptr); 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate if ((*ptr = (void *) malloc(size)) == NULL) { 613*7c478bd9Sstevel@tonic-gate fail("malloc failed"); 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate (void *) memset(*ptr, 0, size); 616*7c478bd9Sstevel@tonic-gate } 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate static void * 619*7c478bd9Sstevel@tonic-gate safe_kstat_data_lookup(kstat_t *ksp, char *name) 620*7c478bd9Sstevel@tonic-gate { 621*7c478bd9Sstevel@tonic-gate void *fp = kstat_data_lookup(ksp, name); 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 624*7c478bd9Sstevel@tonic-gate fail("kstat_data_lookup('%s', '%s') failed", 625*7c478bd9Sstevel@tonic-gate ksp->ks_name, name); 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate return (fp); 628*7c478bd9Sstevel@tonic-gate } 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate static int 631*7c478bd9Sstevel@tonic-gate kscmp(kstat_t *ks1, kstat_t *ks2) 632*7c478bd9Sstevel@tonic-gate { 633*7c478bd9Sstevel@tonic-gate int cmp; 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate cmp = strcmp(ks1->ks_module, ks2->ks_module); 636*7c478bd9Sstevel@tonic-gate if (cmp != 0) { 637*7c478bd9Sstevel@tonic-gate return (cmp); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate cmp = ks1->ks_instance - ks2->ks_instance; 640*7c478bd9Sstevel@tonic-gate if (cmp != 0) { 641*7c478bd9Sstevel@tonic-gate return (cmp); 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate return (strcmp(ks1->ks_name, ks2->ks_name)); 644*7c478bd9Sstevel@tonic-gate } 645*7c478bd9Sstevel@tonic-gate 646*7c478bd9Sstevel@tonic-gate static void 647*7c478bd9Sstevel@tonic-gate keep_activity_data(activity_data_t **act_start, activity_data_t **act_end, 648*7c478bd9Sstevel@tonic-gate int *delta_sum, int delta, hrtime_t time) 649*7c478bd9Sstevel@tonic-gate { 650*7c478bd9Sstevel@tonic-gate activity_data_t *node = NULLACTIVITY; 651*7c478bd9Sstevel@tonic-gate hrtime_t hr_now; 652*7c478bd9Sstevel@tonic-gate int idle_time = info->pd_idle_time * 60; 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate /* 655*7c478bd9Sstevel@tonic-gate * Add new nodes to the beginning of the list. 656*7c478bd9Sstevel@tonic-gate */ 657*7c478bd9Sstevel@tonic-gate safe_zalloc((void **)&node, sizeof (activity_data_t), 0); 658*7c478bd9Sstevel@tonic-gate node->activity_delta = delta; 659*7c478bd9Sstevel@tonic-gate *delta_sum += delta; 660*7c478bd9Sstevel@tonic-gate node->snaptime = time; 661*7c478bd9Sstevel@tonic-gate node->next = *act_start; 662*7c478bd9Sstevel@tonic-gate if (*act_start == NULLACTIVITY) { 663*7c478bd9Sstevel@tonic-gate *act_end = node; 664*7c478bd9Sstevel@tonic-gate } else { 665*7c478bd9Sstevel@tonic-gate (*act_start)->prev = node; 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate *act_start = node; 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate /* 670*7c478bd9Sstevel@tonic-gate * Remove nodes that are time-stamped later than the idle time. 671*7c478bd9Sstevel@tonic-gate */ 672*7c478bd9Sstevel@tonic-gate hr_now = gethrtime(); 673*7c478bd9Sstevel@tonic-gate node = *act_end; 674*7c478bd9Sstevel@tonic-gate while ((int)((hr_now - node->snaptime) / NANOSEC) > idle_time && 675*7c478bd9Sstevel@tonic-gate node->prev != NULLACTIVITY) { 676*7c478bd9Sstevel@tonic-gate *delta_sum -= node->activity_delta; 677*7c478bd9Sstevel@tonic-gate *act_end = node->prev; 678*7c478bd9Sstevel@tonic-gate (*act_end)->next = NULLACTIVITY; 679*7c478bd9Sstevel@tonic-gate free(node); 680*7c478bd9Sstevel@tonic-gate node = *act_end; 681*7c478bd9Sstevel@tonic-gate } 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate static int 685*7c478bd9Sstevel@tonic-gate check_activity(activity_data_t *act_start, int delta_sum, hrtime_t *time, 686*7c478bd9Sstevel@tonic-gate int thold) 687*7c478bd9Sstevel@tonic-gate { 688*7c478bd9Sstevel@tonic-gate activity_data_t *node; 689*7c478bd9Sstevel@tonic-gate int sum = 0; 690*7c478bd9Sstevel@tonic-gate int idle_time = info->pd_idle_time * 60; 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate /* 693*7c478bd9Sstevel@tonic-gate * No need to walk the list if the sum of the deltas are not greater 694*7c478bd9Sstevel@tonic-gate * than the threshold value. 695*7c478bd9Sstevel@tonic-gate */ 696*7c478bd9Sstevel@tonic-gate if (delta_sum <= thold) { 697*7c478bd9Sstevel@tonic-gate return (idle_time); 698*7c478bd9Sstevel@tonic-gate } 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate /* 701*7c478bd9Sstevel@tonic-gate * Walk through the list and add up the activity deltas. When the 702*7c478bd9Sstevel@tonic-gate * sum is greater than the threshold value, difference of current 703*7c478bd9Sstevel@tonic-gate * time and the snaptime of that node will give us the idle time. 704*7c478bd9Sstevel@tonic-gate */ 705*7c478bd9Sstevel@tonic-gate node = act_start; 706*7c478bd9Sstevel@tonic-gate while (node->next != NULLACTIVITY) { 707*7c478bd9Sstevel@tonic-gate sum += node->activity_delta; 708*7c478bd9Sstevel@tonic-gate if (sum > thold) { 709*7c478bd9Sstevel@tonic-gate return ((*time - node->snaptime) / NANOSEC); 710*7c478bd9Sstevel@tonic-gate } 711*7c478bd9Sstevel@tonic-gate node = node->next; 712*7c478bd9Sstevel@tonic-gate } 713*7c478bd9Sstevel@tonic-gate sum += node->activity_delta; 714*7c478bd9Sstevel@tonic-gate if (sum > thold) { 715*7c478bd9Sstevel@tonic-gate return ((*time - node->snaptime) / NANOSEC); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate return (idle_time); 719*7c478bd9Sstevel@tonic-gate } 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate static void 722*7c478bd9Sstevel@tonic-gate kstat_copy(kstat_t *src, kstat_t *dst, int fr) 723*7c478bd9Sstevel@tonic-gate { 724*7c478bd9Sstevel@tonic-gate if (fr) 725*7c478bd9Sstevel@tonic-gate free(dst->ks_data); 726*7c478bd9Sstevel@tonic-gate 727*7c478bd9Sstevel@tonic-gate *dst = *src; 728*7c478bd9Sstevel@tonic-gate if (src->ks_data != NULL) { 729*7c478bd9Sstevel@tonic-gate safe_zalloc(&dst->ks_data, src->ks_data_size, 0); 730*7c478bd9Sstevel@tonic-gate (void) memcpy(dst->ks_data, src->ks_data, src->ks_data_size); 731*7c478bd9Sstevel@tonic-gate } else { 732*7c478bd9Sstevel@tonic-gate dst->ks_data = NULL; 733*7c478bd9Sstevel@tonic-gate dst->ks_data_size = 0; 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate } 736