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 2005 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 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * sar generates a report either from an input data file or by invoking sadc to 35*7c478bd9Sstevel@tonic-gate * read system activity counters at the specified intervals. 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * usage: sar [-ubdycwaqvmpgrkA] [-o file] t [n] 38*7c478bd9Sstevel@tonic-gate * sar [-ubdycwaqvmpgrkA][-s hh:mm][-e hh:mm][-i ss][-f file] 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/sysinfo.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <ctype.h> 50*7c478bd9Sstevel@tonic-gate #include <errno.h> 51*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 52*7c478bd9Sstevel@tonic-gate #include <limits.h> 53*7c478bd9Sstevel@tonic-gate #include <signal.h> 54*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 55*7c478bd9Sstevel@tonic-gate #include <stdio.h> 56*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 57*7c478bd9Sstevel@tonic-gate #include <string.h> 58*7c478bd9Sstevel@tonic-gate #include <time.h> 59*7c478bd9Sstevel@tonic-gate #include <unistd.h> 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #include "sa.h" 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #define PGTOBLK(x) ((x) * (pagesize >> 9)) 64*7c478bd9Sstevel@tonic-gate #define BLKTOPG(x) ((x) / (pagesize >> 9)) 65*7c478bd9Sstevel@tonic-gate #define BLKS(x) ((x) >> 9) 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate static void prpass(int); 68*7c478bd9Sstevel@tonic-gate static void prtopt(void); 69*7c478bd9Sstevel@tonic-gate static void prtavg(void); 70*7c478bd9Sstevel@tonic-gate static void prttim(void); 71*7c478bd9Sstevel@tonic-gate static void prtmachid(void); 72*7c478bd9Sstevel@tonic-gate static void prthdg(void); 73*7c478bd9Sstevel@tonic-gate static void tsttab(void); 74*7c478bd9Sstevel@tonic-gate static void update_counters(void); 75*7c478bd9Sstevel@tonic-gate static void usage(void); 76*7c478bd9Sstevel@tonic-gate static void fail(int, char *, ...); 77*7c478bd9Sstevel@tonic-gate static void safe_zalloc(void **, int, int); 78*7c478bd9Sstevel@tonic-gate static int safe_read(int, void *, size_t); 79*7c478bd9Sstevel@tonic-gate static void safe_write(int, void *, size_t); 80*7c478bd9Sstevel@tonic-gate static int safe_strtoi(char const *, char *); 81*7c478bd9Sstevel@tonic-gate static void ulong_delta(ulong_t *, ulong_t *, ulong_t *, ulong_t *, 82*7c478bd9Sstevel@tonic-gate int, int); 83*7c478bd9Sstevel@tonic-gate static float denom(float); 84*7c478bd9Sstevel@tonic-gate static float freq(float, float); 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate static struct sa nx, ox, ax, dx; 87*7c478bd9Sstevel@tonic-gate static iodevinfo_t *nxio, *oxio, *axio, *dxio; 88*7c478bd9Sstevel@tonic-gate static struct tm *curt, args, arge; 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate static int sflg, eflg, iflg, oflg, fflg; 91*7c478bd9Sstevel@tonic-gate static int realtime, passno = 0, do_disk; 92*7c478bd9Sstevel@tonic-gate static int t = 0, n = 0, lines = 0; 93*7c478bd9Sstevel@tonic-gate static int hz; 94*7c478bd9Sstevel@tonic-gate static int niodevs; 95*7c478bd9Sstevel@tonic-gate static int tabflg; 96*7c478bd9Sstevel@tonic-gate static char options[30], fopt[30]; 97*7c478bd9Sstevel@tonic-gate static float tdiff, sec_diff, totsec_diff = 0.0, percent; 98*7c478bd9Sstevel@tonic-gate static time_t ts, te; /* time interval start and end */ 99*7c478bd9Sstevel@tonic-gate static float start_time, end_time, isec; 100*7c478bd9Sstevel@tonic-gate static int fin, fout; 101*7c478bd9Sstevel@tonic-gate static pid_t childid; 102*7c478bd9Sstevel@tonic-gate static int pipedes[2]; 103*7c478bd9Sstevel@tonic-gate static char arg1[10], arg2[10]; 104*7c478bd9Sstevel@tonic-gate static int pagesize; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate /* 107*7c478bd9Sstevel@tonic-gate * To avoid overflow in the kmem allocation data, declare a copy of the 108*7c478bd9Sstevel@tonic-gate * main kmeminfo_t type with larger data types. Use this for storing 109*7c478bd9Sstevel@tonic-gate * the data held to display average values 110*7c478bd9Sstevel@tonic-gate */ 111*7c478bd9Sstevel@tonic-gate static struct kmeminfo_l 112*7c478bd9Sstevel@tonic-gate { 113*7c478bd9Sstevel@tonic-gate u_longlong_t km_mem[KMEM_NCLASS]; 114*7c478bd9Sstevel@tonic-gate u_longlong_t km_alloc[KMEM_NCLASS]; 115*7c478bd9Sstevel@tonic-gate u_longlong_t km_fail[KMEM_NCLASS]; 116*7c478bd9Sstevel@tonic-gate } kmi; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate int 119*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 120*7c478bd9Sstevel@tonic-gate { 121*7c478bd9Sstevel@tonic-gate char flnm[PATH_MAX], ofile[PATH_MAX]; 122*7c478bd9Sstevel@tonic-gate char ccc; 123*7c478bd9Sstevel@tonic-gate time_t temp; 124*7c478bd9Sstevel@tonic-gate int i, jj = 0; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate pagesize = sysconf(_SC_PAGESIZE); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* 129*7c478bd9Sstevel@tonic-gate * Process options with arguments and pack options 130*7c478bd9Sstevel@tonic-gate * without arguments. 131*7c478bd9Sstevel@tonic-gate */ 132*7c478bd9Sstevel@tonic-gate while ((i = getopt(argc, argv, "ubdycwaqvmpgrkAo:s:e:i:f:")) != EOF) 133*7c478bd9Sstevel@tonic-gate switch (ccc = (char)i) { 134*7c478bd9Sstevel@tonic-gate case 'o': 135*7c478bd9Sstevel@tonic-gate oflg++; 136*7c478bd9Sstevel@tonic-gate if (strlcpy(ofile, optarg, sizeof (ofile)) >= 137*7c478bd9Sstevel@tonic-gate sizeof (ofile)) { 138*7c478bd9Sstevel@tonic-gate fail(2, "-o filename is too long: %s", optarg); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate break; 141*7c478bd9Sstevel@tonic-gate case 's': 142*7c478bd9Sstevel@tonic-gate if (sscanf(optarg, "%d:%d:%d", 143*7c478bd9Sstevel@tonic-gate &args.tm_hour, &args.tm_min, &args.tm_sec) < 1) 144*7c478bd9Sstevel@tonic-gate fail(0, "-%c %s -- illegal option argument", 145*7c478bd9Sstevel@tonic-gate ccc, optarg); 146*7c478bd9Sstevel@tonic-gate else { 147*7c478bd9Sstevel@tonic-gate sflg++, 148*7c478bd9Sstevel@tonic-gate start_time = args.tm_hour*3600.0 + 149*7c478bd9Sstevel@tonic-gate args.tm_min*60.0 + 150*7c478bd9Sstevel@tonic-gate args.tm_sec; 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate break; 153*7c478bd9Sstevel@tonic-gate case 'e': 154*7c478bd9Sstevel@tonic-gate if (sscanf(optarg, "%d:%d:%d", 155*7c478bd9Sstevel@tonic-gate &arge.tm_hour, &arge.tm_min, &arge.tm_sec) < 1) 156*7c478bd9Sstevel@tonic-gate fail(0, "-%c %s -- illegal option argument", 157*7c478bd9Sstevel@tonic-gate ccc, optarg); 158*7c478bd9Sstevel@tonic-gate else { 159*7c478bd9Sstevel@tonic-gate eflg++; 160*7c478bd9Sstevel@tonic-gate end_time = arge.tm_hour*3600.0 + 161*7c478bd9Sstevel@tonic-gate arge.tm_min*60.0 + 162*7c478bd9Sstevel@tonic-gate arge.tm_sec; 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate break; 165*7c478bd9Sstevel@tonic-gate case 'i': 166*7c478bd9Sstevel@tonic-gate if (sscanf(optarg, "%f", &isec) < 1) 167*7c478bd9Sstevel@tonic-gate fail(0, "-%c %s -- illegal option argument", 168*7c478bd9Sstevel@tonic-gate ccc, optarg); 169*7c478bd9Sstevel@tonic-gate else { 170*7c478bd9Sstevel@tonic-gate if (isec > 0.0) 171*7c478bd9Sstevel@tonic-gate iflg++; 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate break; 174*7c478bd9Sstevel@tonic-gate case 'f': 175*7c478bd9Sstevel@tonic-gate fflg++; 176*7c478bd9Sstevel@tonic-gate if (strlcpy(flnm, optarg, sizeof (flnm)) >= 177*7c478bd9Sstevel@tonic-gate sizeof (ofile)) { 178*7c478bd9Sstevel@tonic-gate fail(2, "-f filename is too long: %s", optarg); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate break; 181*7c478bd9Sstevel@tonic-gate case '?': 182*7c478bd9Sstevel@tonic-gate usage(); 183*7c478bd9Sstevel@tonic-gate exit(1); 184*7c478bd9Sstevel@tonic-gate break; 185*7c478bd9Sstevel@tonic-gate default: 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* 188*7c478bd9Sstevel@tonic-gate * Check for repeated options. To make sure 189*7c478bd9Sstevel@tonic-gate * that options[30] does not overflow. 190*7c478bd9Sstevel@tonic-gate */ 191*7c478bd9Sstevel@tonic-gate if (strchr(options, ccc) == NULL) 192*7c478bd9Sstevel@tonic-gate (void) strncat(options, &ccc, 1); 193*7c478bd9Sstevel@tonic-gate break; 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* 197*7c478bd9Sstevel@tonic-gate * Are starting and ending times consistent? 198*7c478bd9Sstevel@tonic-gate */ 199*7c478bd9Sstevel@tonic-gate if ((sflg) && (eflg) && (end_time <= start_time)) 200*7c478bd9Sstevel@tonic-gate fail(0, "ending time <= starting time"); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* 203*7c478bd9Sstevel@tonic-gate * Determine if t and n arguments are given, and whether to run in real 204*7c478bd9Sstevel@tonic-gate * time or from a file. 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate switch (argc - optind) { 207*7c478bd9Sstevel@tonic-gate case 0: /* Get input data from file */ 208*7c478bd9Sstevel@tonic-gate if (fflg == 0) { 209*7c478bd9Sstevel@tonic-gate temp = time(NULL); 210*7c478bd9Sstevel@tonic-gate curt = localtime(&temp); 211*7c478bd9Sstevel@tonic-gate (void) snprintf(flnm, PATH_MAX, "/var/adm/sa/sa%.2d", 212*7c478bd9Sstevel@tonic-gate curt->tm_mday); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate if ((fin = open(flnm, 0)) == -1) 215*7c478bd9Sstevel@tonic-gate fail(1, "can't open %s", flnm); 216*7c478bd9Sstevel@tonic-gate break; 217*7c478bd9Sstevel@tonic-gate case 1: /* Real time data; one cycle */ 218*7c478bd9Sstevel@tonic-gate realtime++; 219*7c478bd9Sstevel@tonic-gate t = safe_strtoi(argv[optind], "invalid sampling interval"); 220*7c478bd9Sstevel@tonic-gate n = 2; 221*7c478bd9Sstevel@tonic-gate break; 222*7c478bd9Sstevel@tonic-gate case 2: /* Real time data; specified cycles */ 223*7c478bd9Sstevel@tonic-gate default: 224*7c478bd9Sstevel@tonic-gate realtime++; 225*7c478bd9Sstevel@tonic-gate t = safe_strtoi(argv[optind], "invalid sampling interval"); 226*7c478bd9Sstevel@tonic-gate n = 1 + safe_strtoi(argv[optind+1], "invalid sample count"); 227*7c478bd9Sstevel@tonic-gate break; 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* 231*7c478bd9Sstevel@tonic-gate * "u" is the default option, which displays CPU utilization. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate if (strlen(options) == 0) 234*7c478bd9Sstevel@tonic-gate (void) strcpy(options, "u"); 235*7c478bd9Sstevel@tonic-gate 236*7c478bd9Sstevel@tonic-gate /* 237*7c478bd9Sstevel@tonic-gate * "A" means all data options. 238*7c478bd9Sstevel@tonic-gate */ 239*7c478bd9Sstevel@tonic-gate if (strchr(options, 'A') != NULL) 240*7c478bd9Sstevel@tonic-gate (void) strcpy(options, "udqbwcayvmpgrk"); 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate if (realtime) { 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * Get input data from sadc via pipe. 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate if (t <= 0) 247*7c478bd9Sstevel@tonic-gate fail(0, "sampling interval t <= 0 sec"); 248*7c478bd9Sstevel@tonic-gate if (n < 2) 249*7c478bd9Sstevel@tonic-gate fail(0, "number of sample intervals n <= 0"); 250*7c478bd9Sstevel@tonic-gate (void) sprintf(arg1, "%d", t); 251*7c478bd9Sstevel@tonic-gate (void) sprintf(arg2, "%d", n); 252*7c478bd9Sstevel@tonic-gate if (pipe(pipedes) == -1) 253*7c478bd9Sstevel@tonic-gate fail(1, "pipe failed"); 254*7c478bd9Sstevel@tonic-gate if ((childid = fork()) == 0) { 255*7c478bd9Sstevel@tonic-gate /* 256*7c478bd9Sstevel@tonic-gate * Child: shift pipedes[write] to stdout, 257*7c478bd9Sstevel@tonic-gate * and close the pipe entries. 258*7c478bd9Sstevel@tonic-gate */ 259*7c478bd9Sstevel@tonic-gate (void) dup2(pipedes[1], 1); 260*7c478bd9Sstevel@tonic-gate if (pipedes[0] != 1) 261*7c478bd9Sstevel@tonic-gate (void) close(pipedes[0]); 262*7c478bd9Sstevel@tonic-gate if (pipedes[1] != 1) 263*7c478bd9Sstevel@tonic-gate (void) close(pipedes[1]); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate if (execlp("/usr/lib/sa/sadc", 266*7c478bd9Sstevel@tonic-gate "/usr/lib/sa/sadc", arg1, arg2, 0) == -1) 267*7c478bd9Sstevel@tonic-gate fail(1, "exec of /usr/lib/sa/sadc failed"); 268*7c478bd9Sstevel@tonic-gate } else if (childid == -1) { 269*7c478bd9Sstevel@tonic-gate fail(1, "Could not fork to exec sadc"); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate /* 272*7c478bd9Sstevel@tonic-gate * Parent: close unused output. 273*7c478bd9Sstevel@tonic-gate */ 274*7c478bd9Sstevel@tonic-gate fin = pipedes[0]; 275*7c478bd9Sstevel@tonic-gate (void) close(pipedes[1]); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate if (oflg) { 279*7c478bd9Sstevel@tonic-gate if (strcmp(ofile, flnm) == 0) 280*7c478bd9Sstevel@tonic-gate fail(0, "output file name same as input file name"); 281*7c478bd9Sstevel@tonic-gate fout = creat(ofile, 00644); 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate hz = sysconf(_SC_CLK_TCK); 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate nxio = oxio = dxio = axio = NULL; 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate if (realtime) { 289*7c478bd9Sstevel@tonic-gate /* 290*7c478bd9Sstevel@tonic-gate * Make single pass, processing all options. 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate (void) strcpy(fopt, options); 293*7c478bd9Sstevel@tonic-gate passno++; 294*7c478bd9Sstevel@tonic-gate prpass(realtime); 295*7c478bd9Sstevel@tonic-gate (void) kill(childid, SIGINT); 296*7c478bd9Sstevel@tonic-gate (void) wait(NULL); 297*7c478bd9Sstevel@tonic-gate } else { 298*7c478bd9Sstevel@tonic-gate /* 299*7c478bd9Sstevel@tonic-gate * Make multiple passes, one for each option. 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate while (strlen(strncpy(fopt, &options[jj++], 1))) { 302*7c478bd9Sstevel@tonic-gate if (lseek(fin, 0, SEEK_SET) == (off_t)-1) 303*7c478bd9Sstevel@tonic-gate fail(0, "lseek failed"); 304*7c478bd9Sstevel@tonic-gate passno++; 305*7c478bd9Sstevel@tonic-gate prpass(realtime); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate return (0); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate /* 313*7c478bd9Sstevel@tonic-gate * Read records from input, classify, and decide on printing. 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate static void 316*7c478bd9Sstevel@tonic-gate prpass(int input_pipe) 317*7c478bd9Sstevel@tonic-gate { 318*7c478bd9Sstevel@tonic-gate size_t size; 319*7c478bd9Sstevel@tonic-gate int i, j, state_change, recno = 0; 320*7c478bd9Sstevel@tonic-gate kid_t kid; 321*7c478bd9Sstevel@tonic-gate float trec, tnext = 0; 322*7c478bd9Sstevel@tonic-gate ulong_t old_niodevs = 0, prev_niodevs = 0; 323*7c478bd9Sstevel@tonic-gate iodevinfo_t *aio, *dio, *oio; 324*7c478bd9Sstevel@tonic-gate struct stat in_stat; 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate do_disk = (strchr(fopt, 'd') != NULL); 327*7c478bd9Sstevel@tonic-gate if (!input_pipe && fstat(fin, &in_stat) == -1) 328*7c478bd9Sstevel@tonic-gate fail(1, "unable to stat data file"); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate if (sflg) 331*7c478bd9Sstevel@tonic-gate tnext = start_time; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate while (safe_read(fin, &nx, sizeof (struct sa))) { 334*7c478bd9Sstevel@tonic-gate /* 335*7c478bd9Sstevel@tonic-gate * sadc is the only utility used to generate sar data 336*7c478bd9Sstevel@tonic-gate * and it uses the valid field as follows: 337*7c478bd9Sstevel@tonic-gate * 0 - dummy record 338*7c478bd9Sstevel@tonic-gate * 1 - data record 339*7c478bd9Sstevel@tonic-gate * We can use this fact to improve sar's ability to detect 340*7c478bd9Sstevel@tonic-gate * bad data, since any value apart from 0 or 1 can be 341*7c478bd9Sstevel@tonic-gate * interpreted as invalid data. 342*7c478bd9Sstevel@tonic-gate */ 343*7c478bd9Sstevel@tonic-gate if (nx.valid != 0 && nx.valid != 1) 344*7c478bd9Sstevel@tonic-gate fail(2, "data file not in sar format"); 345*7c478bd9Sstevel@tonic-gate state_change = 0; 346*7c478bd9Sstevel@tonic-gate niodevs = nx.niodevs; 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * niodevs has the value of current number of devices 349*7c478bd9Sstevel@tonic-gate * from nx structure. 350*7c478bd9Sstevel@tonic-gate * 351*7c478bd9Sstevel@tonic-gate * The following 'if' condition is to decide whether memory 352*7c478bd9Sstevel@tonic-gate * has to be allocated or not if already allocated memory is 353*7c478bd9Sstevel@tonic-gate * bigger or smaller than memory needed to store the current 354*7c478bd9Sstevel@tonic-gate * niodevs details in memory. 355*7c478bd9Sstevel@tonic-gate * 356*7c478bd9Sstevel@tonic-gate * when first while loop starts, pre_niodevs has 0 and then 357*7c478bd9Sstevel@tonic-gate * always get initialized to the current number of devices 358*7c478bd9Sstevel@tonic-gate * from nx.niodevs if it is different from previously read 359*7c478bd9Sstevel@tonic-gate * niodevs. 360*7c478bd9Sstevel@tonic-gate * 361*7c478bd9Sstevel@tonic-gate * if the current niodevs has the same value of previously 362*7c478bd9Sstevel@tonic-gate * allocated memory i.e, for prev_niodevs, it skips the 363*7c478bd9Sstevel@tonic-gate * following 'if' loop or otherwise it allocates memory for 364*7c478bd9Sstevel@tonic-gate * current devises (niodevs) and stores that value in 365*7c478bd9Sstevel@tonic-gate * prev_niodevs for next time when loop continues to read 366*7c478bd9Sstevel@tonic-gate * from the file. 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate if (niodevs != prev_niodevs) { 369*7c478bd9Sstevel@tonic-gate off_t curr_pos; 370*7c478bd9Sstevel@tonic-gate /* 371*7c478bd9Sstevel@tonic-gate * The required buffer size must fit in a size_t. 372*7c478bd9Sstevel@tonic-gate */ 373*7c478bd9Sstevel@tonic-gate if (SIZE_MAX / sizeof (iodevinfo_t) < niodevs) 374*7c478bd9Sstevel@tonic-gate fail(2, "insufficient address space to hold " 375*7c478bd9Sstevel@tonic-gate "%lu device records", niodevs); 376*7c478bd9Sstevel@tonic-gate size = niodevs * sizeof (iodevinfo_t); 377*7c478bd9Sstevel@tonic-gate prev_niodevs = niodevs; 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * The data file must exceed this size to be valid. 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate if (!input_pipe) { 382*7c478bd9Sstevel@tonic-gate if ((curr_pos = lseek(fin, 0, SEEK_CUR)) == 383*7c478bd9Sstevel@tonic-gate (off_t)-1) 384*7c478bd9Sstevel@tonic-gate fail(1, "lseek failed"); 385*7c478bd9Sstevel@tonic-gate if (in_stat.st_size < curr_pos || 386*7c478bd9Sstevel@tonic-gate size > in_stat.st_size - curr_pos) 387*7c478bd9Sstevel@tonic-gate fail(2, "data file corrupt; specified size" 388*7c478bd9Sstevel@tonic-gate "exceeds actual"); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate safe_zalloc((void **)&nxio, size, 1); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate if (niodevs != old_niodevs) 394*7c478bd9Sstevel@tonic-gate state_change = 1; 395*7c478bd9Sstevel@tonic-gate for (i = 0; i < niodevs; i++) { 396*7c478bd9Sstevel@tonic-gate if (safe_read(fin, &nxio[i], sizeof (iodevinfo_t)) == 0) 397*7c478bd9Sstevel@tonic-gate fail(1, "premature end-of-file seen"); 398*7c478bd9Sstevel@tonic-gate if (i < old_niodevs && 399*7c478bd9Sstevel@tonic-gate nxio[i].ks.ks_kid != oxio[i].ks.ks_kid) 400*7c478bd9Sstevel@tonic-gate state_change = 1; 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate curt = localtime(&nx.ts); 403*7c478bd9Sstevel@tonic-gate trec = curt->tm_hour * 3600.0 + 404*7c478bd9Sstevel@tonic-gate curt->tm_min * 60.0 + 405*7c478bd9Sstevel@tonic-gate curt->tm_sec; 406*7c478bd9Sstevel@tonic-gate if ((recno == 0) && (trec < start_time)) 407*7c478bd9Sstevel@tonic-gate continue; 408*7c478bd9Sstevel@tonic-gate if ((eflg) && (trec > end_time)) 409*7c478bd9Sstevel@tonic-gate break; 410*7c478bd9Sstevel@tonic-gate if ((oflg) && (passno == 1)) { 411*7c478bd9Sstevel@tonic-gate safe_write(fout, &nx, sizeof (struct sa)); 412*7c478bd9Sstevel@tonic-gate for (i = 0; i < niodevs; i++) 413*7c478bd9Sstevel@tonic-gate safe_write(fout, &nxio[i], 414*7c478bd9Sstevel@tonic-gate sizeof (iodevinfo_t)); 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate if (recno == 0) { 418*7c478bd9Sstevel@tonic-gate if (passno == 1) 419*7c478bd9Sstevel@tonic-gate prtmachid(); 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate prthdg(); 422*7c478bd9Sstevel@tonic-gate recno = 1; 423*7c478bd9Sstevel@tonic-gate if ((iflg) && (tnext == 0)) 424*7c478bd9Sstevel@tonic-gate tnext = trec; 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate if (nx.valid == 0) { 428*7c478bd9Sstevel@tonic-gate /* 429*7c478bd9Sstevel@tonic-gate * This dummy record signifies system restart 430*7c478bd9Sstevel@tonic-gate * New initial values of counters follow in next 431*7c478bd9Sstevel@tonic-gate * record. 432*7c478bd9Sstevel@tonic-gate */ 433*7c478bd9Sstevel@tonic-gate if (!realtime) { 434*7c478bd9Sstevel@tonic-gate prttim(); 435*7c478bd9Sstevel@tonic-gate (void) printf("\tunix restarts\n"); 436*7c478bd9Sstevel@tonic-gate recno = 1; 437*7c478bd9Sstevel@tonic-gate continue; 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate if ((iflg) && (trec < tnext)) 441*7c478bd9Sstevel@tonic-gate continue; 442*7c478bd9Sstevel@tonic-gate 443*7c478bd9Sstevel@tonic-gate if (state_change) { 444*7c478bd9Sstevel@tonic-gate /* 445*7c478bd9Sstevel@tonic-gate * Either the number of devices or the ordering of 446*7c478bd9Sstevel@tonic-gate * the kstats has changed. We need to re-organise 447*7c478bd9Sstevel@tonic-gate * the layout of our avg/delta arrays so that we 448*7c478bd9Sstevel@tonic-gate * can cope with this in update_counters(). 449*7c478bd9Sstevel@tonic-gate */ 450*7c478bd9Sstevel@tonic-gate size = niodevs * sizeof (iodevinfo_t); 451*7c478bd9Sstevel@tonic-gate safe_zalloc((void *)&aio, size, 0); 452*7c478bd9Sstevel@tonic-gate safe_zalloc((void *)&dio, size, 0); 453*7c478bd9Sstevel@tonic-gate safe_zalloc((void *)&oio, size, 0); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate /* 456*7c478bd9Sstevel@tonic-gate * Loop through all the newly read iodev's, locate 457*7c478bd9Sstevel@tonic-gate * the corresponding entry in the old arrays and 458*7c478bd9Sstevel@tonic-gate * copy the entries into the same bucket of the 459*7c478bd9Sstevel@tonic-gate * new arrays. 460*7c478bd9Sstevel@tonic-gate */ 461*7c478bd9Sstevel@tonic-gate for (i = 0; i < niodevs; i++) { 462*7c478bd9Sstevel@tonic-gate kid = nxio[i].ks.ks_kid; 463*7c478bd9Sstevel@tonic-gate for (j = 0; j < old_niodevs; j++) { 464*7c478bd9Sstevel@tonic-gate if (oxio[j].ks.ks_kid == kid) { 465*7c478bd9Sstevel@tonic-gate oio[i] = oxio[j]; 466*7c478bd9Sstevel@tonic-gate aio[i] = axio[j]; 467*7c478bd9Sstevel@tonic-gate dio[i] = dxio[j]; 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate } 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate free(axio); 473*7c478bd9Sstevel@tonic-gate free(oxio); 474*7c478bd9Sstevel@tonic-gate free(dxio); 475*7c478bd9Sstevel@tonic-gate 476*7c478bd9Sstevel@tonic-gate axio = aio; 477*7c478bd9Sstevel@tonic-gate oxio = oio; 478*7c478bd9Sstevel@tonic-gate dxio = dio; 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate old_niodevs = niodevs; 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate if (recno++ > 1) { 484*7c478bd9Sstevel@tonic-gate ts = ox.csi.cpu[0] + ox.csi.cpu[1] + 485*7c478bd9Sstevel@tonic-gate ox.csi.cpu[2] + ox.csi.cpu[3]; 486*7c478bd9Sstevel@tonic-gate te = nx.csi.cpu[0] + nx.csi.cpu[1] + 487*7c478bd9Sstevel@tonic-gate nx.csi.cpu[2] + nx.csi.cpu[3]; 488*7c478bd9Sstevel@tonic-gate tdiff = (float)(te - ts); 489*7c478bd9Sstevel@tonic-gate sec_diff = tdiff / hz; 490*7c478bd9Sstevel@tonic-gate percent = 100.0 / tdiff; 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate /* 493*7c478bd9Sstevel@tonic-gate * If the CPU stat counters have rolled 494*7c478bd9Sstevel@tonic-gate * backward, this is our best indication that 495*7c478bd9Sstevel@tonic-gate * a CPU has been offlined. We don't have 496*7c478bd9Sstevel@tonic-gate * enough data to compute a sensible delta, so 497*7c478bd9Sstevel@tonic-gate * toss out this interval, but compute the next 498*7c478bd9Sstevel@tonic-gate * interval's delta from these values. 499*7c478bd9Sstevel@tonic-gate */ 500*7c478bd9Sstevel@tonic-gate if (tdiff <= 0) { 501*7c478bd9Sstevel@tonic-gate ox = nx; 502*7c478bd9Sstevel@tonic-gate continue; 503*7c478bd9Sstevel@tonic-gate } 504*7c478bd9Sstevel@tonic-gate update_counters(); 505*7c478bd9Sstevel@tonic-gate prtopt(); 506*7c478bd9Sstevel@tonic-gate lines++; 507*7c478bd9Sstevel@tonic-gate if (passno == 1) 508*7c478bd9Sstevel@tonic-gate totsec_diff += sec_diff; 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate ox = nx; /* Age the data */ 511*7c478bd9Sstevel@tonic-gate (void) memcpy(oxio, nxio, niodevs * sizeof (iodevinfo_t)); 512*7c478bd9Sstevel@tonic-gate if (isec > 0) 513*7c478bd9Sstevel@tonic-gate while (tnext <= trec) 514*7c478bd9Sstevel@tonic-gate tnext += isec; 515*7c478bd9Sstevel@tonic-gate } 516*7c478bd9Sstevel@tonic-gate /* 517*7c478bd9Sstevel@tonic-gate * After this place, all functions are using niodevs to access the 518*7c478bd9Sstevel@tonic-gate * memory for device details. Here, old_niodevs has the correct value 519*7c478bd9Sstevel@tonic-gate * of memory allocated for storing device information. Since niodevs 520*7c478bd9Sstevel@tonic-gate * doesn't have correct value, sometimes, it was corrupting memory. 521*7c478bd9Sstevel@tonic-gate */ 522*7c478bd9Sstevel@tonic-gate niodevs = old_niodevs; 523*7c478bd9Sstevel@tonic-gate if (lines > 1) 524*7c478bd9Sstevel@tonic-gate prtavg(); 525*7c478bd9Sstevel@tonic-gate (void) memset(&ax, 0, sizeof (ax)); /* Zero out the accumulators. */ 526*7c478bd9Sstevel@tonic-gate (void) memset(&kmi, 0, sizeof (kmi)); 527*7c478bd9Sstevel@tonic-gate lines = 0; 528*7c478bd9Sstevel@tonic-gate /* 529*7c478bd9Sstevel@tonic-gate * axio will not be allocated if the user specified -e or -s, and 530*7c478bd9Sstevel@tonic-gate * no records in the file fell inside the specified time range. 531*7c478bd9Sstevel@tonic-gate */ 532*7c478bd9Sstevel@tonic-gate if (axio) { 533*7c478bd9Sstevel@tonic-gate (void) memset(axio, 0, niodevs * sizeof (iodevinfo_t)); 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate /* 538*7c478bd9Sstevel@tonic-gate * Print time label routine. 539*7c478bd9Sstevel@tonic-gate */ 540*7c478bd9Sstevel@tonic-gate static void 541*7c478bd9Sstevel@tonic-gate prttim(void) 542*7c478bd9Sstevel@tonic-gate { 543*7c478bd9Sstevel@tonic-gate curt = localtime(&nx.ts); 544*7c478bd9Sstevel@tonic-gate (void) printf("%.2d:%.2d:%.2d", curt->tm_hour, curt->tm_min, 545*7c478bd9Sstevel@tonic-gate curt->tm_sec); 546*7c478bd9Sstevel@tonic-gate tabflg = 1; 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate /* 550*7c478bd9Sstevel@tonic-gate * Test if 8-spaces to be added routine. 551*7c478bd9Sstevel@tonic-gate */ 552*7c478bd9Sstevel@tonic-gate static void 553*7c478bd9Sstevel@tonic-gate tsttab(void) 554*7c478bd9Sstevel@tonic-gate { 555*7c478bd9Sstevel@tonic-gate if (tabflg == 0) 556*7c478bd9Sstevel@tonic-gate (void) printf(" "); 557*7c478bd9Sstevel@tonic-gate else 558*7c478bd9Sstevel@tonic-gate tabflg = 0; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate /* 562*7c478bd9Sstevel@tonic-gate * Print machine identification. 563*7c478bd9Sstevel@tonic-gate */ 564*7c478bd9Sstevel@tonic-gate static void 565*7c478bd9Sstevel@tonic-gate prtmachid(void) 566*7c478bd9Sstevel@tonic-gate { 567*7c478bd9Sstevel@tonic-gate struct utsname name; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate (void) uname(&name); 570*7c478bd9Sstevel@tonic-gate (void) printf("\n%s %s %s %s %s %.2d/%.2d/%.4d\n", 571*7c478bd9Sstevel@tonic-gate name.sysname, name.nodename, name.release, name.version, 572*7c478bd9Sstevel@tonic-gate name.machine, curt->tm_mon + 1, curt->tm_mday, 573*7c478bd9Sstevel@tonic-gate curt->tm_year + 1900); 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate /* 577*7c478bd9Sstevel@tonic-gate * Print report heading routine. 578*7c478bd9Sstevel@tonic-gate */ 579*7c478bd9Sstevel@tonic-gate static void 580*7c478bd9Sstevel@tonic-gate prthdg(void) 581*7c478bd9Sstevel@tonic-gate { 582*7c478bd9Sstevel@tonic-gate int jj = 0; 583*7c478bd9Sstevel@tonic-gate char ccc; 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 586*7c478bd9Sstevel@tonic-gate prttim(); 587*7c478bd9Sstevel@tonic-gate while ((ccc = fopt[jj++]) != NULL) { 588*7c478bd9Sstevel@tonic-gate tsttab(); 589*7c478bd9Sstevel@tonic-gate switch (ccc) { 590*7c478bd9Sstevel@tonic-gate case 'u': 591*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %7s %7s\n", 592*7c478bd9Sstevel@tonic-gate "%usr", 593*7c478bd9Sstevel@tonic-gate "%sys", 594*7c478bd9Sstevel@tonic-gate "%wio", 595*7c478bd9Sstevel@tonic-gate "%idle"); 596*7c478bd9Sstevel@tonic-gate break; 597*7c478bd9Sstevel@tonic-gate case 'b': 598*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %7s %7s %7s %7s %7s %7s\n", 599*7c478bd9Sstevel@tonic-gate "bread/s", 600*7c478bd9Sstevel@tonic-gate "lread/s", 601*7c478bd9Sstevel@tonic-gate "%rcache", 602*7c478bd9Sstevel@tonic-gate "bwrit/s", 603*7c478bd9Sstevel@tonic-gate "lwrit/s", 604*7c478bd9Sstevel@tonic-gate "%wcache", 605*7c478bd9Sstevel@tonic-gate "pread/s", 606*7c478bd9Sstevel@tonic-gate "pwrit/s"); 607*7c478bd9Sstevel@tonic-gate break; 608*7c478bd9Sstevel@tonic-gate case 'd': 609*7c478bd9Sstevel@tonic-gate (void) printf(" %-8.8s %7s %7s %7s %7s %7s %7s\n", 610*7c478bd9Sstevel@tonic-gate "device", 611*7c478bd9Sstevel@tonic-gate "%busy", 612*7c478bd9Sstevel@tonic-gate "avque", 613*7c478bd9Sstevel@tonic-gate "r+w/s", 614*7c478bd9Sstevel@tonic-gate "blks/s", 615*7c478bd9Sstevel@tonic-gate "avwait", 616*7c478bd9Sstevel@tonic-gate "avserv"); 617*7c478bd9Sstevel@tonic-gate break; 618*7c478bd9Sstevel@tonic-gate case 'y': 619*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %7s %7s %7s %7s\n", 620*7c478bd9Sstevel@tonic-gate "rawch/s", 621*7c478bd9Sstevel@tonic-gate "canch/s", 622*7c478bd9Sstevel@tonic-gate "outch/s", 623*7c478bd9Sstevel@tonic-gate "rcvin/s", 624*7c478bd9Sstevel@tonic-gate "xmtin/s", 625*7c478bd9Sstevel@tonic-gate "mdmin/s"); 626*7c478bd9Sstevel@tonic-gate break; 627*7c478bd9Sstevel@tonic-gate case 'c': 628*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %7s %7s %7s %7s %7s\n", 629*7c478bd9Sstevel@tonic-gate "scall/s", 630*7c478bd9Sstevel@tonic-gate "sread/s", 631*7c478bd9Sstevel@tonic-gate "swrit/s", 632*7c478bd9Sstevel@tonic-gate "fork/s", 633*7c478bd9Sstevel@tonic-gate "exec/s", 634*7c478bd9Sstevel@tonic-gate "rchar/s", 635*7c478bd9Sstevel@tonic-gate "wchar/s"); 636*7c478bd9Sstevel@tonic-gate break; 637*7c478bd9Sstevel@tonic-gate case 'w': 638*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %7s %7s %7s\n", 639*7c478bd9Sstevel@tonic-gate "swpin/s", 640*7c478bd9Sstevel@tonic-gate "bswin/s", 641*7c478bd9Sstevel@tonic-gate "swpot/s", 642*7c478bd9Sstevel@tonic-gate "bswot/s", 643*7c478bd9Sstevel@tonic-gate "pswch/s"); 644*7c478bd9Sstevel@tonic-gate break; 645*7c478bd9Sstevel@tonic-gate case 'a': 646*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %7s\n", 647*7c478bd9Sstevel@tonic-gate "iget/s", 648*7c478bd9Sstevel@tonic-gate "namei/s", 649*7c478bd9Sstevel@tonic-gate "dirbk/s"); 650*7c478bd9Sstevel@tonic-gate break; 651*7c478bd9Sstevel@tonic-gate case 'q': 652*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %7s %7s\n", 653*7c478bd9Sstevel@tonic-gate "runq-sz", 654*7c478bd9Sstevel@tonic-gate "%runocc", 655*7c478bd9Sstevel@tonic-gate "swpq-sz", 656*7c478bd9Sstevel@tonic-gate "%swpocc"); 657*7c478bd9Sstevel@tonic-gate break; 658*7c478bd9Sstevel@tonic-gate case 'v': 659*7c478bd9Sstevel@tonic-gate (void) printf(" %s %s %s %s\n", 660*7c478bd9Sstevel@tonic-gate "proc-sz ov", 661*7c478bd9Sstevel@tonic-gate "inod-sz ov", 662*7c478bd9Sstevel@tonic-gate "file-sz ov", 663*7c478bd9Sstevel@tonic-gate "lock-sz"); 664*7c478bd9Sstevel@tonic-gate break; 665*7c478bd9Sstevel@tonic-gate case 'm': 666*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s\n", 667*7c478bd9Sstevel@tonic-gate "msg/s", 668*7c478bd9Sstevel@tonic-gate "sema/s"); 669*7c478bd9Sstevel@tonic-gate break; 670*7c478bd9Sstevel@tonic-gate case 'p': 671*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %7s %7s %7s %7s\n", 672*7c478bd9Sstevel@tonic-gate "atch/s", 673*7c478bd9Sstevel@tonic-gate "pgin/s", 674*7c478bd9Sstevel@tonic-gate "ppgin/s", 675*7c478bd9Sstevel@tonic-gate "pflt/s", 676*7c478bd9Sstevel@tonic-gate "vflt/s", 677*7c478bd9Sstevel@tonic-gate "slock/s"); 678*7c478bd9Sstevel@tonic-gate break; 679*7c478bd9Sstevel@tonic-gate case 'g': 680*7c478bd9Sstevel@tonic-gate (void) printf(" %8s %8s %8s %8s %8s\n", 681*7c478bd9Sstevel@tonic-gate "pgout/s", 682*7c478bd9Sstevel@tonic-gate "ppgout/s", 683*7c478bd9Sstevel@tonic-gate "pgfree/s", 684*7c478bd9Sstevel@tonic-gate "pgscan/s", 685*7c478bd9Sstevel@tonic-gate "%ufs_ipf"); 686*7c478bd9Sstevel@tonic-gate break; 687*7c478bd9Sstevel@tonic-gate case 'r': 688*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %8s\n", 689*7c478bd9Sstevel@tonic-gate "freemem", 690*7c478bd9Sstevel@tonic-gate "freeswap"); 691*7c478bd9Sstevel@tonic-gate break; 692*7c478bd9Sstevel@tonic-gate case 'k': 693*7c478bd9Sstevel@tonic-gate (void) printf(" %7s %7s %5s %7s %7s %5s %11s %5s\n", 694*7c478bd9Sstevel@tonic-gate "sml_mem", 695*7c478bd9Sstevel@tonic-gate "alloc", 696*7c478bd9Sstevel@tonic-gate "fail", 697*7c478bd9Sstevel@tonic-gate "lg_mem", 698*7c478bd9Sstevel@tonic-gate "alloc", 699*7c478bd9Sstevel@tonic-gate "fail", 700*7c478bd9Sstevel@tonic-gate "ovsz_alloc", 701*7c478bd9Sstevel@tonic-gate "fail"); 702*7c478bd9Sstevel@tonic-gate break; 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate if (jj > 2 || do_disk) 706*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 707*7c478bd9Sstevel@tonic-gate } 708*7c478bd9Sstevel@tonic-gate 709*7c478bd9Sstevel@tonic-gate /* 710*7c478bd9Sstevel@tonic-gate * compute deltas and update accumulators 711*7c478bd9Sstevel@tonic-gate */ 712*7c478bd9Sstevel@tonic-gate static void 713*7c478bd9Sstevel@tonic-gate update_counters(void) 714*7c478bd9Sstevel@tonic-gate { 715*7c478bd9Sstevel@tonic-gate int i; 716*7c478bd9Sstevel@tonic-gate iodevinfo_t *nio, *oio, *aio, *dio; 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate ulong_delta((ulong_t *)&nx.csi, (ulong_t *)&ox.csi, 719*7c478bd9Sstevel@tonic-gate (ulong_t *)&dx.csi, (ulong_t *)&ax.csi, 0, sizeof (ax.csi)); 720*7c478bd9Sstevel@tonic-gate ulong_delta((ulong_t *)&nx.si, (ulong_t *)&ox.si, 721*7c478bd9Sstevel@tonic-gate (ulong_t *)&dx.si, (ulong_t *)&ax.si, 0, sizeof (ax.si)); 722*7c478bd9Sstevel@tonic-gate ulong_delta((ulong_t *)&nx.cvmi, (ulong_t *)&ox.cvmi, 723*7c478bd9Sstevel@tonic-gate (ulong_t *)&dx.cvmi, (ulong_t *)&ax.cvmi, 0, 724*7c478bd9Sstevel@tonic-gate sizeof (ax.cvmi)); 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate ax.vmi.freemem += dx.vmi.freemem = nx.vmi.freemem - ox.vmi.freemem; 727*7c478bd9Sstevel@tonic-gate ax.vmi.swap_avail += dx.vmi.swap_avail = 728*7c478bd9Sstevel@tonic-gate nx.vmi.swap_avail - ox.vmi.swap_avail; 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate nio = nxio; 731*7c478bd9Sstevel@tonic-gate oio = oxio; 732*7c478bd9Sstevel@tonic-gate aio = axio; 733*7c478bd9Sstevel@tonic-gate dio = dxio; 734*7c478bd9Sstevel@tonic-gate for (i = 0; i < niodevs; i++) { 735*7c478bd9Sstevel@tonic-gate aio->kios.wlastupdate += dio->kios.wlastupdate 736*7c478bd9Sstevel@tonic-gate = nio->kios.wlastupdate - oio->kios.wlastupdate; 737*7c478bd9Sstevel@tonic-gate aio->kios.reads += dio->kios.reads 738*7c478bd9Sstevel@tonic-gate = nio->kios.reads - oio->kios.reads; 739*7c478bd9Sstevel@tonic-gate aio->kios.writes += dio->kios.writes 740*7c478bd9Sstevel@tonic-gate = nio->kios.writes - oio->kios.writes; 741*7c478bd9Sstevel@tonic-gate aio->kios.nread += dio->kios.nread 742*7c478bd9Sstevel@tonic-gate = nio->kios.nread - oio->kios.nread; 743*7c478bd9Sstevel@tonic-gate aio->kios.nwritten += dio->kios.nwritten 744*7c478bd9Sstevel@tonic-gate = nio->kios.nwritten - oio->kios.nwritten; 745*7c478bd9Sstevel@tonic-gate aio->kios.wlentime += dio->kios.wlentime 746*7c478bd9Sstevel@tonic-gate = nio->kios.wlentime - oio->kios.wlentime; 747*7c478bd9Sstevel@tonic-gate aio->kios.rlentime += dio->kios.rlentime 748*7c478bd9Sstevel@tonic-gate = nio->kios.rlentime - oio->kios.rlentime; 749*7c478bd9Sstevel@tonic-gate aio->kios.wtime += dio->kios.wtime 750*7c478bd9Sstevel@tonic-gate = nio->kios.wtime - oio->kios.wtime; 751*7c478bd9Sstevel@tonic-gate aio->kios.rtime += dio->kios.rtime 752*7c478bd9Sstevel@tonic-gate = nio->kios.rtime - oio->kios.rtime; 753*7c478bd9Sstevel@tonic-gate nio++; 754*7c478bd9Sstevel@tonic-gate oio++; 755*7c478bd9Sstevel@tonic-gate aio++; 756*7c478bd9Sstevel@tonic-gate dio++; 757*7c478bd9Sstevel@tonic-gate } 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate static void 761*7c478bd9Sstevel@tonic-gate prt_u_opt(struct sa *xx) 762*7c478bd9Sstevel@tonic-gate { 763*7c478bd9Sstevel@tonic-gate (void) printf(" %7.0f %7.0f %7.0f %7.0f\n", 764*7c478bd9Sstevel@tonic-gate (float)xx->csi.cpu[1] * percent, 765*7c478bd9Sstevel@tonic-gate (float)xx->csi.cpu[2] * percent, 766*7c478bd9Sstevel@tonic-gate (float)xx->csi.cpu[3] * percent, 767*7c478bd9Sstevel@tonic-gate (float)xx->csi.cpu[0] * percent); 768*7c478bd9Sstevel@tonic-gate } 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate static void 771*7c478bd9Sstevel@tonic-gate prt_b_opt(struct sa *xx) 772*7c478bd9Sstevel@tonic-gate { 773*7c478bd9Sstevel@tonic-gate (void) printf(" %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f\n", 774*7c478bd9Sstevel@tonic-gate (float)xx->csi.bread / sec_diff, 775*7c478bd9Sstevel@tonic-gate (float)xx->csi.lread / sec_diff, 776*7c478bd9Sstevel@tonic-gate freq((float)xx->csi.lread, (float)xx->csi.bread), 777*7c478bd9Sstevel@tonic-gate (float)xx->csi.bwrite / sec_diff, 778*7c478bd9Sstevel@tonic-gate (float)xx->csi.lwrite / sec_diff, 779*7c478bd9Sstevel@tonic-gate freq((float)xx->csi.lwrite, (float)xx->csi.bwrite), 780*7c478bd9Sstevel@tonic-gate (float)xx->csi.phread / sec_diff, 781*7c478bd9Sstevel@tonic-gate (float)xx->csi.phwrite / sec_diff); 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate static void 785*7c478bd9Sstevel@tonic-gate prt_d_opt(int ii, iodevinfo_t *xio) 786*7c478bd9Sstevel@tonic-gate { 787*7c478bd9Sstevel@tonic-gate double etime, hr_etime, tps, avq, avs; 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate tsttab(); 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate hr_etime = (double)xio[ii].kios.wlastupdate; 792*7c478bd9Sstevel@tonic-gate if (hr_etime == 0.0) 793*7c478bd9Sstevel@tonic-gate hr_etime = (double)NANOSEC; 794*7c478bd9Sstevel@tonic-gate etime = hr_etime / (double)NANOSEC; 795*7c478bd9Sstevel@tonic-gate tps = (double)(xio[ii].kios.reads + xio[ii].kios.writes) / etime; 796*7c478bd9Sstevel@tonic-gate avq = (double)xio[ii].kios.wlentime / hr_etime; 797*7c478bd9Sstevel@tonic-gate avs = (double)xio[ii].kios.rlentime / hr_etime; 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate (void) printf(" %-8.8s ", nxio[ii].ks.ks_name); 800*7c478bd9Sstevel@tonic-gate (void) printf("%7.0f %7.1f %7.0f %7.0f %7.1f %7.1f\n", 801*7c478bd9Sstevel@tonic-gate (double)xio[ii].kios.rtime * 100.0 / hr_etime, 802*7c478bd9Sstevel@tonic-gate avq + avs, 803*7c478bd9Sstevel@tonic-gate tps, 804*7c478bd9Sstevel@tonic-gate BLKS(xio[ii].kios.nread + xio[ii].kios.nwritten) / etime, 805*7c478bd9Sstevel@tonic-gate (tps > 0 ? avq / tps * 1000.0 : 0.0), 806*7c478bd9Sstevel@tonic-gate (tps > 0 ? avs / tps * 1000.0 : 0.0)); 807*7c478bd9Sstevel@tonic-gate } 808*7c478bd9Sstevel@tonic-gate 809*7c478bd9Sstevel@tonic-gate static void 810*7c478bd9Sstevel@tonic-gate prt_y_opt(struct sa *xx) 811*7c478bd9Sstevel@tonic-gate { 812*7c478bd9Sstevel@tonic-gate (void) printf(" %7.0f %7.0f %7.0f %7.0f %7.0f %7.0f\n", 813*7c478bd9Sstevel@tonic-gate (float)xx->csi.rawch / sec_diff, 814*7c478bd9Sstevel@tonic-gate (float)xx->csi.canch / sec_diff, 815*7c478bd9Sstevel@tonic-gate (float)xx->csi.outch / sec_diff, 816*7c478bd9Sstevel@tonic-gate (float)xx->csi.rcvint / sec_diff, 817*7c478bd9Sstevel@tonic-gate (float)xx->csi.xmtint / sec_diff, 818*7c478bd9Sstevel@tonic-gate (float)xx->csi.mdmint / sec_diff); 819*7c478bd9Sstevel@tonic-gate } 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate static void 822*7c478bd9Sstevel@tonic-gate prt_c_opt(struct sa *xx) 823*7c478bd9Sstevel@tonic-gate { 824*7c478bd9Sstevel@tonic-gate (void) printf(" %7.0f %7.0f %7.0f %7.2f %7.2f %7.0f %7.0f\n", 825*7c478bd9Sstevel@tonic-gate (float)xx->csi.syscall / sec_diff, 826*7c478bd9Sstevel@tonic-gate (float)xx->csi.sysread / sec_diff, 827*7c478bd9Sstevel@tonic-gate (float)xx->csi.syswrite / sec_diff, 828*7c478bd9Sstevel@tonic-gate (float)(xx->csi.sysfork + xx->csi.sysvfork) / sec_diff, 829*7c478bd9Sstevel@tonic-gate (float)xx->csi.sysexec / sec_diff, 830*7c478bd9Sstevel@tonic-gate (float)xx->csi.readch / sec_diff, 831*7c478bd9Sstevel@tonic-gate (float)xx->csi.writech / sec_diff); 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate static void 835*7c478bd9Sstevel@tonic-gate prt_w_opt(struct sa *xx) 836*7c478bd9Sstevel@tonic-gate { 837*7c478bd9Sstevel@tonic-gate (void) printf(" %7.2f %7.1f %7.2f %7.1f %7.0f\n", 838*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.swapin / sec_diff, 839*7c478bd9Sstevel@tonic-gate (float)PGTOBLK(xx->cvmi.pgswapin) / sec_diff, 840*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.swapout / sec_diff, 841*7c478bd9Sstevel@tonic-gate (float)PGTOBLK(xx->cvmi.pgswapout) / sec_diff, 842*7c478bd9Sstevel@tonic-gate (float)xx->csi.pswitch / sec_diff); 843*7c478bd9Sstevel@tonic-gate } 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate static void 846*7c478bd9Sstevel@tonic-gate prt_a_opt(struct sa *xx) 847*7c478bd9Sstevel@tonic-gate { 848*7c478bd9Sstevel@tonic-gate (void) printf(" %7.0f %7.0f %7.0f\n", 849*7c478bd9Sstevel@tonic-gate (float)xx->csi.ufsiget / sec_diff, 850*7c478bd9Sstevel@tonic-gate (float)xx->csi.namei / sec_diff, 851*7c478bd9Sstevel@tonic-gate (float)xx->csi.ufsdirblk / sec_diff); 852*7c478bd9Sstevel@tonic-gate } 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate static void 855*7c478bd9Sstevel@tonic-gate prt_q_opt(struct sa *xx) 856*7c478bd9Sstevel@tonic-gate { 857*7c478bd9Sstevel@tonic-gate if (xx->si.runocc == 0) 858*7c478bd9Sstevel@tonic-gate (void) printf(" %7.1f %7.0f", 0., 0.); 859*7c478bd9Sstevel@tonic-gate else { 860*7c478bd9Sstevel@tonic-gate (void) printf(" %7.1f %7.0f", 861*7c478bd9Sstevel@tonic-gate (float)xx->si.runque / (float)xx->si.runocc, 862*7c478bd9Sstevel@tonic-gate (float)xx->si.runocc / sec_diff * 100.0); 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate if (xx->si.swpocc == 0) 865*7c478bd9Sstevel@tonic-gate (void) printf(" %7.1f %7.0f\n", 0., 0.); 866*7c478bd9Sstevel@tonic-gate else { 867*7c478bd9Sstevel@tonic-gate (void) printf(" %7.1f %7.0f\n", 868*7c478bd9Sstevel@tonic-gate (float)xx->si.swpque / (float)xx->si.swpocc, 869*7c478bd9Sstevel@tonic-gate (float)xx->si.swpocc / sec_diff * 100.0); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate } 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate static void 874*7c478bd9Sstevel@tonic-gate prt_v_opt(struct sa *xx) 875*7c478bd9Sstevel@tonic-gate { 876*7c478bd9Sstevel@tonic-gate (void) printf(" %4lu/%-4lu %4u %4lu/%-4lu %4u %4lu/%-4lu " 877*7c478bd9Sstevel@tonic-gate "%4u %4lu/%-4lu\n", 878*7c478bd9Sstevel@tonic-gate nx.szproc, nx.mszproc, xx->csi.procovf, 879*7c478bd9Sstevel@tonic-gate nx.szinode, nx.mszinode, xx->csi.inodeovf, 880*7c478bd9Sstevel@tonic-gate nx.szfile, nx.mszfile, xx->csi.fileovf, 881*7c478bd9Sstevel@tonic-gate nx.szlckr, nx.mszlckr); 882*7c478bd9Sstevel@tonic-gate } 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate static void 885*7c478bd9Sstevel@tonic-gate prt_m_opt(struct sa *xx) 886*7c478bd9Sstevel@tonic-gate { 887*7c478bd9Sstevel@tonic-gate (void) printf(" %7.2f %7.2f\n", 888*7c478bd9Sstevel@tonic-gate (float)xx->csi.msg / sec_diff, 889*7c478bd9Sstevel@tonic-gate (float)xx->csi.sema / sec_diff); 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate static void 893*7c478bd9Sstevel@tonic-gate prt_p_opt(struct sa *xx) 894*7c478bd9Sstevel@tonic-gate { 895*7c478bd9Sstevel@tonic-gate (void) printf(" %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n", 896*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.pgfrec / sec_diff, 897*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.pgin / sec_diff, 898*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.pgpgin / sec_diff, 899*7c478bd9Sstevel@tonic-gate (float)(xx->cvmi.prot_fault + xx->cvmi.cow_fault) / sec_diff, 900*7c478bd9Sstevel@tonic-gate (float)(xx->cvmi.hat_fault + xx->cvmi.as_fault) / sec_diff, 901*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.softlock / sec_diff); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate static void 905*7c478bd9Sstevel@tonic-gate prt_g_opt(struct sa *xx) 906*7c478bd9Sstevel@tonic-gate { 907*7c478bd9Sstevel@tonic-gate (void) printf(" %8.2f %8.2f %8.2f %8.2f %8.2f\n", 908*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.pgout / sec_diff, 909*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.pgpgout / sec_diff, 910*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.dfree / sec_diff, 911*7c478bd9Sstevel@tonic-gate (float)xx->cvmi.scan / sec_diff, 912*7c478bd9Sstevel@tonic-gate (float)xx->csi.ufsipage * 100.0 / 913*7c478bd9Sstevel@tonic-gate denom((float)xx->csi.ufsipage + 914*7c478bd9Sstevel@tonic-gate (float)xx->csi.ufsinopage)); 915*7c478bd9Sstevel@tonic-gate } 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate static void 918*7c478bd9Sstevel@tonic-gate prt_r_opt(struct sa *xx) 919*7c478bd9Sstevel@tonic-gate { 920*7c478bd9Sstevel@tonic-gate (void) printf(" %7.0f %8.0f\n", 921*7c478bd9Sstevel@tonic-gate (double)xx->vmi.freemem / sec_diff, 922*7c478bd9Sstevel@tonic-gate (double)PGTOBLK(xx->vmi.swap_avail) / sec_diff); 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate static void 926*7c478bd9Sstevel@tonic-gate prt_k_opt(struct sa *xx, int n) 927*7c478bd9Sstevel@tonic-gate { 928*7c478bd9Sstevel@tonic-gate if (n != 1) { 929*7c478bd9Sstevel@tonic-gate (void) printf(" %7.0f %7.0f %5.0f %7.0f %7.0f %5.0f %11.0f" 930*7c478bd9Sstevel@tonic-gate " %5.0f\n", 931*7c478bd9Sstevel@tonic-gate (float)kmi.km_mem[KMEM_SMALL] / n, 932*7c478bd9Sstevel@tonic-gate (float)kmi.km_alloc[KMEM_SMALL] / n, 933*7c478bd9Sstevel@tonic-gate (float)kmi.km_fail[KMEM_SMALL] / n, 934*7c478bd9Sstevel@tonic-gate (float)kmi.km_mem[KMEM_LARGE] / n, 935*7c478bd9Sstevel@tonic-gate (float)kmi.km_alloc[KMEM_LARGE] / n, 936*7c478bd9Sstevel@tonic-gate (float)kmi.km_fail[KMEM_LARGE] / n, 937*7c478bd9Sstevel@tonic-gate (float)kmi.km_alloc[KMEM_OSIZE] / n, 938*7c478bd9Sstevel@tonic-gate (float)kmi.km_fail[KMEM_OSIZE] / n); 939*7c478bd9Sstevel@tonic-gate } else { 940*7c478bd9Sstevel@tonic-gate /* 941*7c478bd9Sstevel@tonic-gate * If we are not reporting averages, use the read values 942*7c478bd9Sstevel@tonic-gate * directly. 943*7c478bd9Sstevel@tonic-gate */ 944*7c478bd9Sstevel@tonic-gate (void) printf(" %7.0f %7.0f %5.0f %7.0f %7.0f %5.0f %11.0f" 945*7c478bd9Sstevel@tonic-gate " %5.0f\n", 946*7c478bd9Sstevel@tonic-gate (float)xx->kmi.km_mem[KMEM_SMALL], 947*7c478bd9Sstevel@tonic-gate (float)xx->kmi.km_alloc[KMEM_SMALL], 948*7c478bd9Sstevel@tonic-gate (float)xx->kmi.km_fail[KMEM_SMALL], 949*7c478bd9Sstevel@tonic-gate (float)xx->kmi.km_mem[KMEM_LARGE], 950*7c478bd9Sstevel@tonic-gate (float)xx->kmi.km_alloc[KMEM_LARGE], 951*7c478bd9Sstevel@tonic-gate (float)xx->kmi.km_fail[KMEM_LARGE], 952*7c478bd9Sstevel@tonic-gate (float)xx->kmi.km_alloc[KMEM_OSIZE], 953*7c478bd9Sstevel@tonic-gate (float)xx->kmi.km_fail[KMEM_OSIZE]); 954*7c478bd9Sstevel@tonic-gate } 955*7c478bd9Sstevel@tonic-gate } 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate /* 958*7c478bd9Sstevel@tonic-gate * Print options routine. 959*7c478bd9Sstevel@tonic-gate */ 960*7c478bd9Sstevel@tonic-gate static void 961*7c478bd9Sstevel@tonic-gate prtopt(void) 962*7c478bd9Sstevel@tonic-gate { 963*7c478bd9Sstevel@tonic-gate int ii, jj = 0; 964*7c478bd9Sstevel@tonic-gate char ccc; 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate prttim(); 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate while ((ccc = fopt[jj++]) != NULL) { 969*7c478bd9Sstevel@tonic-gate if (ccc != 'd') 970*7c478bd9Sstevel@tonic-gate tsttab(); 971*7c478bd9Sstevel@tonic-gate switch (ccc) { 972*7c478bd9Sstevel@tonic-gate case 'u': 973*7c478bd9Sstevel@tonic-gate prt_u_opt(&dx); 974*7c478bd9Sstevel@tonic-gate break; 975*7c478bd9Sstevel@tonic-gate case 'b': 976*7c478bd9Sstevel@tonic-gate prt_b_opt(&dx); 977*7c478bd9Sstevel@tonic-gate break; 978*7c478bd9Sstevel@tonic-gate case 'd': 979*7c478bd9Sstevel@tonic-gate for (ii = 0; ii < niodevs; ii++) 980*7c478bd9Sstevel@tonic-gate prt_d_opt(ii, dxio); 981*7c478bd9Sstevel@tonic-gate break; 982*7c478bd9Sstevel@tonic-gate case 'y': 983*7c478bd9Sstevel@tonic-gate prt_y_opt(&dx); 984*7c478bd9Sstevel@tonic-gate break; 985*7c478bd9Sstevel@tonic-gate case 'c': 986*7c478bd9Sstevel@tonic-gate prt_c_opt(&dx); 987*7c478bd9Sstevel@tonic-gate break; 988*7c478bd9Sstevel@tonic-gate case 'w': 989*7c478bd9Sstevel@tonic-gate prt_w_opt(&dx); 990*7c478bd9Sstevel@tonic-gate break; 991*7c478bd9Sstevel@tonic-gate case 'a': 992*7c478bd9Sstevel@tonic-gate prt_a_opt(&dx); 993*7c478bd9Sstevel@tonic-gate break; 994*7c478bd9Sstevel@tonic-gate case 'q': 995*7c478bd9Sstevel@tonic-gate prt_q_opt(&dx); 996*7c478bd9Sstevel@tonic-gate break; 997*7c478bd9Sstevel@tonic-gate case 'v': 998*7c478bd9Sstevel@tonic-gate prt_v_opt(&dx); 999*7c478bd9Sstevel@tonic-gate break; 1000*7c478bd9Sstevel@tonic-gate case 'm': 1001*7c478bd9Sstevel@tonic-gate prt_m_opt(&dx); 1002*7c478bd9Sstevel@tonic-gate break; 1003*7c478bd9Sstevel@tonic-gate case 'p': 1004*7c478bd9Sstevel@tonic-gate prt_p_opt(&dx); 1005*7c478bd9Sstevel@tonic-gate break; 1006*7c478bd9Sstevel@tonic-gate case 'g': 1007*7c478bd9Sstevel@tonic-gate prt_g_opt(&dx); 1008*7c478bd9Sstevel@tonic-gate break; 1009*7c478bd9Sstevel@tonic-gate case 'r': 1010*7c478bd9Sstevel@tonic-gate prt_r_opt(&dx); 1011*7c478bd9Sstevel@tonic-gate break; 1012*7c478bd9Sstevel@tonic-gate case 'k': 1013*7c478bd9Sstevel@tonic-gate prt_k_opt(&nx, 1); 1014*7c478bd9Sstevel@tonic-gate /* 1015*7c478bd9Sstevel@tonic-gate * To avoid overflow, copy the data from the sa record 1016*7c478bd9Sstevel@tonic-gate * into a struct kmeminfo_l which has members with 1017*7c478bd9Sstevel@tonic-gate * larger data types. 1018*7c478bd9Sstevel@tonic-gate */ 1019*7c478bd9Sstevel@tonic-gate kmi.km_mem[KMEM_SMALL] += nx.kmi.km_mem[KMEM_SMALL]; 1020*7c478bd9Sstevel@tonic-gate kmi.km_alloc[KMEM_SMALL] += nx.kmi.km_alloc[KMEM_SMALL]; 1021*7c478bd9Sstevel@tonic-gate kmi.km_fail[KMEM_SMALL] += nx.kmi.km_fail[KMEM_SMALL]; 1022*7c478bd9Sstevel@tonic-gate kmi.km_mem[KMEM_LARGE] += nx.kmi.km_mem[KMEM_LARGE]; 1023*7c478bd9Sstevel@tonic-gate kmi.km_alloc[KMEM_LARGE] += nx.kmi.km_alloc[KMEM_LARGE]; 1024*7c478bd9Sstevel@tonic-gate kmi.km_fail[KMEM_LARGE] += nx.kmi.km_fail[KMEM_LARGE]; 1025*7c478bd9Sstevel@tonic-gate kmi.km_alloc[KMEM_OSIZE] += nx.kmi.km_alloc[KMEM_OSIZE]; 1026*7c478bd9Sstevel@tonic-gate kmi.km_fail[KMEM_OSIZE] += nx.kmi.km_fail[KMEM_OSIZE]; 1027*7c478bd9Sstevel@tonic-gate break; 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate if (jj > 2 || do_disk) 1031*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1032*7c478bd9Sstevel@tonic-gate if (realtime) 1033*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1034*7c478bd9Sstevel@tonic-gate } 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate /* 1037*7c478bd9Sstevel@tonic-gate * Print average routine. 1038*7c478bd9Sstevel@tonic-gate */ 1039*7c478bd9Sstevel@tonic-gate static void 1040*7c478bd9Sstevel@tonic-gate prtavg(void) 1041*7c478bd9Sstevel@tonic-gate { 1042*7c478bd9Sstevel@tonic-gate int ii, jj = 0; 1043*7c478bd9Sstevel@tonic-gate char ccc; 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate tdiff = ax.csi.cpu[0] + ax.csi.cpu[1] + ax.csi.cpu[2] + ax.csi.cpu[3]; 1046*7c478bd9Sstevel@tonic-gate if (tdiff <= 0.0) 1047*7c478bd9Sstevel@tonic-gate return; 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate sec_diff = tdiff / hz; 1050*7c478bd9Sstevel@tonic-gate percent = 100.0 / tdiff; 1051*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1052*7c478bd9Sstevel@tonic-gate 1053*7c478bd9Sstevel@tonic-gate while ((ccc = fopt[jj++]) != NULL) { 1054*7c478bd9Sstevel@tonic-gate if (ccc != 'v') 1055*7c478bd9Sstevel@tonic-gate (void) printf("Average "); 1056*7c478bd9Sstevel@tonic-gate switch (ccc) { 1057*7c478bd9Sstevel@tonic-gate case 'u': 1058*7c478bd9Sstevel@tonic-gate prt_u_opt(&ax); 1059*7c478bd9Sstevel@tonic-gate break; 1060*7c478bd9Sstevel@tonic-gate case 'b': 1061*7c478bd9Sstevel@tonic-gate prt_b_opt(&ax); 1062*7c478bd9Sstevel@tonic-gate break; 1063*7c478bd9Sstevel@tonic-gate case 'd': 1064*7c478bd9Sstevel@tonic-gate tabflg = 1; 1065*7c478bd9Sstevel@tonic-gate for (ii = 0; ii < niodevs; ii++) 1066*7c478bd9Sstevel@tonic-gate prt_d_opt(ii, axio); 1067*7c478bd9Sstevel@tonic-gate break; 1068*7c478bd9Sstevel@tonic-gate case 'y': 1069*7c478bd9Sstevel@tonic-gate prt_y_opt(&ax); 1070*7c478bd9Sstevel@tonic-gate break; 1071*7c478bd9Sstevel@tonic-gate case 'c': 1072*7c478bd9Sstevel@tonic-gate prt_c_opt(&ax); 1073*7c478bd9Sstevel@tonic-gate break; 1074*7c478bd9Sstevel@tonic-gate case 'w': 1075*7c478bd9Sstevel@tonic-gate prt_w_opt(&ax); 1076*7c478bd9Sstevel@tonic-gate break; 1077*7c478bd9Sstevel@tonic-gate case 'a': 1078*7c478bd9Sstevel@tonic-gate prt_a_opt(&ax); 1079*7c478bd9Sstevel@tonic-gate break; 1080*7c478bd9Sstevel@tonic-gate case 'q': 1081*7c478bd9Sstevel@tonic-gate prt_q_opt(&ax); 1082*7c478bd9Sstevel@tonic-gate break; 1083*7c478bd9Sstevel@tonic-gate case 'v': 1084*7c478bd9Sstevel@tonic-gate break; 1085*7c478bd9Sstevel@tonic-gate case 'm': 1086*7c478bd9Sstevel@tonic-gate prt_m_opt(&ax); 1087*7c478bd9Sstevel@tonic-gate break; 1088*7c478bd9Sstevel@tonic-gate case 'p': 1089*7c478bd9Sstevel@tonic-gate prt_p_opt(&ax); 1090*7c478bd9Sstevel@tonic-gate break; 1091*7c478bd9Sstevel@tonic-gate case 'g': 1092*7c478bd9Sstevel@tonic-gate prt_g_opt(&ax); 1093*7c478bd9Sstevel@tonic-gate break; 1094*7c478bd9Sstevel@tonic-gate case 'r': 1095*7c478bd9Sstevel@tonic-gate prt_r_opt(&ax); 1096*7c478bd9Sstevel@tonic-gate break; 1097*7c478bd9Sstevel@tonic-gate case 'k': 1098*7c478bd9Sstevel@tonic-gate prt_k_opt(&ax, lines); 1099*7c478bd9Sstevel@tonic-gate break; 1100*7c478bd9Sstevel@tonic-gate } 1101*7c478bd9Sstevel@tonic-gate } 1102*7c478bd9Sstevel@tonic-gate } 1103*7c478bd9Sstevel@tonic-gate 1104*7c478bd9Sstevel@tonic-gate static void 1105*7c478bd9Sstevel@tonic-gate ulong_delta(ulong_t *new, ulong_t *old, ulong_t *delta, ulong_t *accum, 1106*7c478bd9Sstevel@tonic-gate int begin, int end) 1107*7c478bd9Sstevel@tonic-gate { 1108*7c478bd9Sstevel@tonic-gate int i; 1109*7c478bd9Sstevel@tonic-gate ulong_t *np, *op, *dp, *ap; 1110*7c478bd9Sstevel@tonic-gate 1111*7c478bd9Sstevel@tonic-gate np = new; 1112*7c478bd9Sstevel@tonic-gate op = old; 1113*7c478bd9Sstevel@tonic-gate dp = delta; 1114*7c478bd9Sstevel@tonic-gate ap = accum; 1115*7c478bd9Sstevel@tonic-gate for (i = begin; i < end; i += sizeof (ulong_t)) 1116*7c478bd9Sstevel@tonic-gate *ap++ += *dp++ = *np++ - *op++; 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate 1119*7c478bd9Sstevel@tonic-gate /* 1120*7c478bd9Sstevel@tonic-gate * used to prevent zero denominators 1121*7c478bd9Sstevel@tonic-gate */ 1122*7c478bd9Sstevel@tonic-gate static float 1123*7c478bd9Sstevel@tonic-gate denom(float x) 1124*7c478bd9Sstevel@tonic-gate { 1125*7c478bd9Sstevel@tonic-gate return ((x > 0.5) ? x : 1.0); 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate /* 1129*7c478bd9Sstevel@tonic-gate * a little calculation that comes up often when computing frequency 1130*7c478bd9Sstevel@tonic-gate * of one operation relative to another 1131*7c478bd9Sstevel@tonic-gate */ 1132*7c478bd9Sstevel@tonic-gate static float 1133*7c478bd9Sstevel@tonic-gate freq(float x, float y) 1134*7c478bd9Sstevel@tonic-gate { 1135*7c478bd9Sstevel@tonic-gate return ((x < 0.5) ? 100.0 : (x - y) / x * 100.0); 1136*7c478bd9Sstevel@tonic-gate } 1137*7c478bd9Sstevel@tonic-gate 1138*7c478bd9Sstevel@tonic-gate static void 1139*7c478bd9Sstevel@tonic-gate usage(void) 1140*7c478bd9Sstevel@tonic-gate { 1141*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1142*7c478bd9Sstevel@tonic-gate "usage: sar [-ubdycwaqvmpgrkA][-o file] t [n]\n" 1143*7c478bd9Sstevel@tonic-gate "\tsar [-ubdycwaqvmpgrkA] [-s hh:mm][-e hh:mm][-i ss][-f file]\n"); 1144*7c478bd9Sstevel@tonic-gate } 1145*7c478bd9Sstevel@tonic-gate 1146*7c478bd9Sstevel@tonic-gate static void 1147*7c478bd9Sstevel@tonic-gate fail(int do_perror, char *message, ...) 1148*7c478bd9Sstevel@tonic-gate { 1149*7c478bd9Sstevel@tonic-gate va_list args; 1150*7c478bd9Sstevel@tonic-gate 1151*7c478bd9Sstevel@tonic-gate va_start(args, message); 1152*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "sar: "); 1153*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, message, args); 1154*7c478bd9Sstevel@tonic-gate va_end(args); 1155*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 1156*7c478bd9Sstevel@tonic-gate switch (do_perror) { 1157*7c478bd9Sstevel@tonic-gate case 0: /* usage message */ 1158*7c478bd9Sstevel@tonic-gate usage(); 1159*7c478bd9Sstevel@tonic-gate break; 1160*7c478bd9Sstevel@tonic-gate case 1: /* perror output */ 1161*7c478bd9Sstevel@tonic-gate perror(""); 1162*7c478bd9Sstevel@tonic-gate break; 1163*7c478bd9Sstevel@tonic-gate case 2: /* no further output */ 1164*7c478bd9Sstevel@tonic-gate break; 1165*7c478bd9Sstevel@tonic-gate default: /* error */ 1166*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "unsupported failure mode\n"); 1167*7c478bd9Sstevel@tonic-gate break; 1168*7c478bd9Sstevel@tonic-gate } 1169*7c478bd9Sstevel@tonic-gate exit(2); 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate 1172*7c478bd9Sstevel@tonic-gate static int 1173*7c478bd9Sstevel@tonic-gate safe_strtoi(char const *val, char *errmsg) 1174*7c478bd9Sstevel@tonic-gate { 1175*7c478bd9Sstevel@tonic-gate char *end; 1176*7c478bd9Sstevel@tonic-gate long tmp; 1177*7c478bd9Sstevel@tonic-gate 1178*7c478bd9Sstevel@tonic-gate errno = 0; 1179*7c478bd9Sstevel@tonic-gate tmp = strtol(val, &end, 10); 1180*7c478bd9Sstevel@tonic-gate if (*end != '\0' || errno) 1181*7c478bd9Sstevel@tonic-gate fail(0, "%s %s", errmsg, val); 1182*7c478bd9Sstevel@tonic-gate return ((int)tmp); 1183*7c478bd9Sstevel@tonic-gate } 1184*7c478bd9Sstevel@tonic-gate 1185*7c478bd9Sstevel@tonic-gate static void 1186*7c478bd9Sstevel@tonic-gate safe_zalloc(void **ptr, int size, int free_first) 1187*7c478bd9Sstevel@tonic-gate { 1188*7c478bd9Sstevel@tonic-gate if (free_first && *ptr != NULL) 1189*7c478bd9Sstevel@tonic-gate free(*ptr); 1190*7c478bd9Sstevel@tonic-gate if ((*ptr = malloc(size)) == NULL) 1191*7c478bd9Sstevel@tonic-gate fail(1, "malloc failed"); 1192*7c478bd9Sstevel@tonic-gate (void) memset(*ptr, 0, size); 1193*7c478bd9Sstevel@tonic-gate } 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate static int 1196*7c478bd9Sstevel@tonic-gate safe_read(int fd, void *buf, size_t size) 1197*7c478bd9Sstevel@tonic-gate { 1198*7c478bd9Sstevel@tonic-gate size_t rsize = read(fd, buf, size); 1199*7c478bd9Sstevel@tonic-gate 1200*7c478bd9Sstevel@tonic-gate if (rsize == 0) 1201*7c478bd9Sstevel@tonic-gate return (0); 1202*7c478bd9Sstevel@tonic-gate 1203*7c478bd9Sstevel@tonic-gate if (rsize != size) 1204*7c478bd9Sstevel@tonic-gate fail(1, "read failed"); 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate return (1); 1207*7c478bd9Sstevel@tonic-gate } 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate static void 1210*7c478bd9Sstevel@tonic-gate safe_write(int fd, void *buf, size_t size) 1211*7c478bd9Sstevel@tonic-gate { 1212*7c478bd9Sstevel@tonic-gate if (write(fd, buf, size) != size) 1213*7c478bd9Sstevel@tonic-gate fail(1, "write failed"); 1214*7c478bd9Sstevel@tonic-gate } 1215