Annotation of src/usr.bin/systat/iostat.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: iostat.c,v 1.3 1995/05/17 15:51:47 mycroft Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1980, 1992, 1993
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * 4. Neither the name of the University nor the names of its contributors
! 20: * may be used to endorse or promote products derived from this software
! 21: * without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: */
! 35:
! 36: #ifndef lint
! 37: #if 0
! 38: static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93";
! 39: #endif
! 40: static char rcsid[] = "$NetBSD: iostat.c,v 1.3 1995/05/17 15:51:47 mycroft Exp $";
! 41: #endif not lint
! 42:
! 43: #include <sys/param.h>
! 44: #include <sys/dkstat.h>
! 45: #include <sys/buf.h>
! 46:
! 47: #include <string.h>
! 48: #include <stdlib.h>
! 49: #include <nlist.h>
! 50: #include <paths.h>
! 51: #include "systat.h"
! 52: #include "extern.h"
! 53:
! 54: static struct nlist namelist[] = {
! 55: #define X_DK_BUSY 0
! 56: { "_dk_busy" },
! 57: #define X_DK_TIME 1
! 58: { "_dk_time" },
! 59: #define X_DK_XFER 2
! 60: { "_dk_xfer" },
! 61: #define X_DK_WDS 3
! 62: { "_dk_wds" },
! 63: #define X_DK_SEEK 4
! 64: { "_dk_seek" },
! 65: #define X_CP_TIME 5
! 66: { "_cp_time" },
! 67: #ifdef vax
! 68: #define X_MBDINIT (X_CP_TIME+1)
! 69: { "_mbdinit" },
! 70: #define X_UBDINIT (X_CP_TIME+2)
! 71: { "_ubdinit" },
! 72: #endif
! 73: #ifdef tahoe
! 74: #define X_VBDINIT (X_CP_TIME+1)
! 75: { "_vbdinit" },
! 76: #endif
! 77: { "" },
! 78: };
! 79:
! 80: static struct {
! 81: int dk_busy;
! 82: long cp_time[CPUSTATES];
! 83: long *dk_time;
! 84: long *dk_wds;
! 85: long *dk_seek;
! 86: long *dk_xfer;
! 87: } s, s1;
! 88:
! 89: static int linesperregion;
! 90: static double etime;
! 91: static int numbers = 0; /* default display bar graphs */
! 92: static int msps = 0; /* default ms/seek shown */
! 93:
! 94: static int barlabels __P((int));
! 95: static void histogram __P((double, int, double));
! 96: static int numlabels __P((int));
! 97: static int stats __P((int, int, int));
! 98: static void stat1 __P((int, int));
! 99:
! 100:
! 101: WINDOW *
! 102: openiostat()
! 103: {
! 104: return (subwin(stdscr, LINES-1-5, 0, 5, 0));
! 105: }
! 106:
! 107: void
! 108: closeiostat(w)
! 109: WINDOW *w;
! 110: {
! 111: if (w == NULL)
! 112: return;
! 113: wclear(w);
! 114: wrefresh(w);
! 115: delwin(w);
! 116: }
! 117:
! 118: int
! 119: initiostat()
! 120: {
! 121: if (namelist[X_DK_BUSY].n_type == 0) {
! 122: if (kvm_nlist(kd, namelist)) {
! 123: nlisterr(namelist);
! 124: return(0);
! 125: }
! 126: if (namelist[X_DK_BUSY].n_type == 0) {
! 127: error("Disk init information isn't in namelist");
! 128: return(0);
! 129: }
! 130: }
! 131: if (! dkinit())
! 132: return(0);
! 133: if (dk_ndrive) {
! 134: #define allocate(e, t) \
! 135: s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
! 136: s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
! 137: allocate(dk_time, long);
! 138: allocate(dk_wds, long);
! 139: allocate(dk_seek, long);
! 140: allocate(dk_xfer, long);
! 141: #undef allocate
! 142: }
! 143: return(1);
! 144: }
! 145:
! 146: void
! 147: fetchiostat()
! 148: {
! 149: if (namelist[X_DK_BUSY].n_type == 0)
! 150: return;
! 151: NREAD(X_DK_BUSY, &s.dk_busy, LONG);
! 152: NREAD(X_DK_TIME, s.dk_time, dk_ndrive * LONG);
! 153: NREAD(X_DK_XFER, s.dk_xfer, dk_ndrive * LONG);
! 154: NREAD(X_DK_WDS, s.dk_wds, dk_ndrive * LONG);
! 155: NREAD(X_DK_SEEK, s.dk_seek, dk_ndrive * LONG);
! 156: NREAD(X_CP_TIME, s.cp_time, sizeof s.cp_time);
! 157: }
! 158:
! 159: #define INSET 10
! 160:
! 161: void
! 162: labeliostat()
! 163: {
! 164: int row;
! 165:
! 166: if (namelist[X_DK_BUSY].n_type == 0) {
! 167: error("No dk_busy defined.");
! 168: return;
! 169: }
! 170: row = 0;
! 171: wmove(wnd, row, 0); wclrtobot(wnd);
! 172: mvwaddstr(wnd, row++, INSET,
! 173: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
! 174: mvwaddstr(wnd, row++, 0, "cpu user|");
! 175: mvwaddstr(wnd, row++, 0, " nice|");
! 176: mvwaddstr(wnd, row++, 0, " system|");
! 177: mvwaddstr(wnd, row++, 0, "interrupt|");
! 178: mvwaddstr(wnd, row++, 0, " idle|");
! 179: if (numbers)
! 180: row = numlabels(row + 1);
! 181: else
! 182: row = barlabels(row + 1);
! 183: }
! 184:
! 185: static int
! 186: numlabels(row)
! 187: int row;
! 188: {
! 189: int i, col, regions, ndrives;
! 190:
! 191: #define COLWIDTH 14
! 192: #define DRIVESPERLINE ((wnd->maxx - INSET) / COLWIDTH)
! 193: for (ndrives = 0, i = 0; i < dk_ndrive; i++)
! 194: if (dk_select[i])
! 195: ndrives++;
! 196: regions = howmany(ndrives, DRIVESPERLINE);
! 197: /*
! 198: * Deduct -regions for blank line after each scrolling region.
! 199: */
! 200: linesperregion = (wnd->maxy - row - regions) / regions;
! 201: /*
! 202: * Minimum region contains space for two
! 203: * label lines and one line of statistics.
! 204: */
! 205: if (linesperregion < 3)
! 206: linesperregion = 3;
! 207: col = 0;
! 208: for (i = 0; i < dk_ndrive; i++)
! 209: if (dk_select[i] && dk_mspw[i] != 0.0) {
! 210: if (col + COLWIDTH >= wnd->maxx - INSET) {
! 211: col = 0, row += linesperregion + 1;
! 212: if (row > wnd->maxy - (linesperregion + 1))
! 213: break;
! 214: }
! 215: mvwaddstr(wnd, row, col + 4, dr_name[i]);
! 216: mvwaddstr(wnd, row + 1, col, "bps tps msps");
! 217: col += COLWIDTH;
! 218: }
! 219: if (col)
! 220: row += linesperregion + 1;
! 221: return (row);
! 222: }
! 223:
! 224: static int
! 225: barlabels(row)
! 226: int row;
! 227: {
! 228: int i;
! 229:
! 230: mvwaddstr(wnd, row++, INSET,
! 231: "/0 /5 /10 /15 /20 /25 /30 /35 /40 /45 /50");
! 232: linesperregion = 2 + msps;
! 233: for (i = 0; i < dk_ndrive; i++)
! 234: if (dk_select[i] && dk_mspw[i] != 0.0) {
! 235: if (row > wnd->maxy - linesperregion)
! 236: break;
! 237: mvwprintw(wnd, row++, 0, "%3.3s bps|", dr_name[i]);
! 238: mvwaddstr(wnd, row++, 0, " tps|");
! 239: if (msps)
! 240: mvwaddstr(wnd, row++, 0, " msps|");
! 241: }
! 242: return (row);
! 243: }
! 244:
! 245:
! 246: void
! 247: showiostat()
! 248: {
! 249: register long t;
! 250: register int i, row, col;
! 251:
! 252: if (namelist[X_DK_BUSY].n_type == 0)
! 253: return;
! 254: for (i = 0; i < dk_ndrive; i++) {
! 255: #define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t
! 256: X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
! 257: }
! 258: etime = 0;
! 259: for(i = 0; i < CPUSTATES; i++) {
! 260: X(cp_time);
! 261: etime += s.cp_time[i];
! 262: }
! 263: if (etime == 0.0)
! 264: etime = 1.0;
! 265: etime /= (float) hz;
! 266: row = 1;
! 267:
! 268: /*
! 269: * Interrupt CPU state not calculated yet.
! 270: */
! 271: for (i = 0; i < CPUSTATES; i++)
! 272: stat1(row++, i);
! 273: if (!numbers) {
! 274: row += 2;
! 275: for (i = 0; i < dk_ndrive; i++)
! 276: if (dk_select[i] && dk_mspw[i] != 0.0) {
! 277: if (row > wnd->maxy - linesperregion)
! 278: break;
! 279: row = stats(row, INSET, i);
! 280: }
! 281: return;
! 282: }
! 283: col = 0;
! 284: wmove(wnd, row + linesperregion, 0);
! 285: wdeleteln(wnd);
! 286: wmove(wnd, row + 3, 0);
! 287: winsertln(wnd);
! 288: for (i = 0; i < dk_ndrive; i++)
! 289: if (dk_select[i] && dk_mspw[i] != 0.0) {
! 290: if (col + COLWIDTH >= wnd->maxx) {
! 291: col = 0, row += linesperregion + 1;
! 292: if (row > wnd->maxy - (linesperregion + 1))
! 293: break;
! 294: wmove(wnd, row + linesperregion, 0);
! 295: wdeleteln(wnd);
! 296: wmove(wnd, row + 3, 0);
! 297: winsertln(wnd);
! 298: }
! 299: (void) stats(row + 3, col, i);
! 300: col += COLWIDTH;
! 301: }
! 302: }
! 303:
! 304: static int
! 305: stats(row, col, dn)
! 306: int row, col, dn;
! 307: {
! 308: double atime, words, xtime, itime;
! 309:
! 310: atime = s.dk_time[dn];
! 311: atime /= (float) hz;
! 312: words = s.dk_wds[dn]*32.0; /* number of words transferred */
! 313: xtime = dk_mspw[dn]*words; /* transfer time */
! 314: itime = atime - xtime; /* time not transferring */
! 315: if (xtime < 0)
! 316: itime += xtime, xtime = 0;
! 317: if (itime < 0)
! 318: xtime += itime, itime = 0;
! 319: if (numbers) {
! 320: mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f",
! 321: words / 512 / etime, s.dk_xfer[dn] / etime,
! 322: s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0.0);
! 323: return (row);
! 324: }
! 325: wmove(wnd, row++, col);
! 326: histogram(words / 512 / etime, 50, 1.0);
! 327: wmove(wnd, row++, col);
! 328: histogram(s.dk_xfer[dn] / etime, 50, 1.0);
! 329: if (msps) {
! 330: wmove(wnd, row++, col);
! 331: histogram(s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0,
! 332: 50, 1.0);
! 333: }
! 334: return (row);
! 335: }
! 336:
! 337: static void
! 338: stat1(row, o)
! 339: int row, o;
! 340: {
! 341: register int i;
! 342: double time;
! 343:
! 344: time = 0;
! 345: for (i = 0; i < CPUSTATES; i++)
! 346: time += s.cp_time[i];
! 347: if (time == 0.0)
! 348: time = 1.0;
! 349: wmove(wnd, row, INSET);
! 350: #define CPUSCALE 0.5
! 351: histogram(100.0 * s.cp_time[o] / time, 50, CPUSCALE);
! 352: }
! 353:
! 354: static void
! 355: histogram(val, colwidth, scale)
! 356: double val;
! 357: int colwidth;
! 358: double scale;
! 359: {
! 360: char buf[10];
! 361: register int k;
! 362: register int v = (int)(val * scale) + 0.5;
! 363:
! 364: k = MIN(v, colwidth);
! 365: if (v > colwidth) {
! 366: sprintf(buf, "%4.1f", val);
! 367: k -= strlen(buf);
! 368: while (k--)
! 369: waddch(wnd, 'X');
! 370: waddstr(wnd, buf);
! 371: return;
! 372: }
! 373: while (k--)
! 374: waddch(wnd, 'X');
! 375: wclrtoeol(wnd);
! 376: }
! 377:
! 378: int
! 379: cmdiostat(cmd, args)
! 380: char *cmd, *args;
! 381: {
! 382:
! 383: if (prefix(cmd, "msps"))
! 384: msps = !msps;
! 385: else if (prefix(cmd, "numbers"))
! 386: numbers = 1;
! 387: else if (prefix(cmd, "bars"))
! 388: numbers = 0;
! 389: else if (!dkcmd(cmd, args))
! 390: return (0);
! 391: wclear(wnd);
! 392: labeliostat();
! 393: refresh();
! 394: return (1);
! 395: }