Annotation of src/usr.bin/systat/iostat.c, Revision 1.16
1.16 ! deraadt 1: /* $OpenBSD: iostat.c,v 1.14 2001/11/23 22:20:06 deraadt Exp $ */
1.3 deraadt 2: /* $NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $ */
1.1 deraadt 3:
4: /*
5: * Copyright (c) 1980, 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: #if 0
39: static char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93";
40: #endif
1.16 ! deraadt 41: static char rcsid[] = "$OpenBSD: iostat.c,v 1.14 2001/11/23 22:20:06 deraadt Exp $";
1.12 heko 42: #endif /* not lint */
1.1 deraadt 43:
44: #include <sys/param.h>
45: #include <sys/dkstat.h>
46: #include <sys/buf.h>
1.3 deraadt 47: #include <sys/time.h>
1.1 deraadt 48:
49: #include <string.h>
50: #include <stdlib.h>
51: #include <paths.h>
52: #include "systat.h"
53: #include "extern.h"
54:
1.3 deraadt 55: #include "dkstats.h"
56: extern struct _disk cur;
1.1 deraadt 57:
58: static int linesperregion;
59: static double etime;
60: static int numbers = 0; /* default display bar graphs */
1.3 deraadt 61: static int secs = 0; /* default seconds shown */
1.1 deraadt 62:
63: static int barlabels __P((int));
64: static void histogram __P((double, int, double));
65: static int numlabels __P((int));
66: static int stats __P((int, int, int));
67: static void stat1 __P((int, int));
68:
69:
70: WINDOW *
71: openiostat()
72: {
73: return (subwin(stdscr, LINES-1-5, 0, 5, 0));
74: }
75:
76: void
77: closeiostat(w)
78: WINDOW *w;
79: {
80: if (w == NULL)
81: return;
82: wclear(w);
83: wrefresh(w);
84: delwin(w);
85: }
86:
87: int
88: initiostat()
89: {
1.3 deraadt 90: dkinit(1);
91: dkreadstats();
1.9 kstailey 92: return (1);
1.1 deraadt 93: }
94:
95: void
96: fetchiostat()
97: {
1.3 deraadt 98: if (dk_ndrive == 0)
1.1 deraadt 99: return;
1.3 deraadt 100: dkreadstats();
1.1 deraadt 101: }
102:
103: #define INSET 10
104:
105: void
106: labeliostat()
107: {
108: int row;
109:
110: row = 0;
111: wmove(wnd, row, 0); wclrtobot(wnd);
112: mvwaddstr(wnd, row++, INSET,
113: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
114: mvwaddstr(wnd, row++, 0, "cpu user|");
115: mvwaddstr(wnd, row++, 0, " nice|");
116: mvwaddstr(wnd, row++, 0, " system|");
117: mvwaddstr(wnd, row++, 0, "interrupt|");
118: mvwaddstr(wnd, row++, 0, " idle|");
119: if (numbers)
120: row = numlabels(row + 1);
121: else
122: row = barlabels(row + 1);
123: }
124:
125: static int
126: numlabels(row)
127: int row;
128: {
129: int i, col, regions, ndrives;
130:
1.7 kstailey 131: if (dk_ndrive == 0) {
132: mvwaddstr(wnd, row++, INSET, "No drives attached.");
133: return (row);
134: }
1.11 deraadt 135: #define COLWIDTH 17
1.4 mickey 136: #define DRIVESPERLINE ((wnd->_maxx - INSET) / COLWIDTH)
1.1 deraadt 137: for (ndrives = 0, i = 0; i < dk_ndrive; i++)
1.3 deraadt 138: if (cur.dk_select[i])
1.1 deraadt 139: ndrives++;
140: regions = howmany(ndrives, DRIVESPERLINE);
141: /*
142: * Deduct -regions for blank line after each scrolling region.
143: */
1.4 mickey 144: linesperregion = (wnd->_maxy - row - regions) / regions;
1.1 deraadt 145: /*
146: * Minimum region contains space for two
147: * label lines and one line of statistics.
148: */
149: if (linesperregion < 3)
150: linesperregion = 3;
1.11 deraadt 151: col = INSET;
1.1 deraadt 152: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 153: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.11 deraadt 154: if (col + COLWIDTH >= wnd->_maxx) {
155: col = INSET, row += linesperregion + 1;
1.4 mickey 156: if (row > wnd->_maxy - (linesperregion + 1))
1.1 deraadt 157: break;
158: }
1.3 deraadt 159: mvwaddstr(wnd, row, col + 4, cur.dk_name[i]);
1.11 deraadt 160: mvwaddstr(wnd, row + 1, col, " KBps tps sec");
1.1 deraadt 161: col += COLWIDTH;
162: }
163: if (col)
164: row += linesperregion + 1;
165: return (row);
166: }
167:
168: static int
169: barlabels(row)
170: int row;
171: {
172: int i;
173:
1.7 kstailey 174: if (dk_ndrive == 0) {
175: mvwaddstr(wnd, row++, INSET, "No drives attached.");
176: return (row);
177: }
1.1 deraadt 178: mvwaddstr(wnd, row++, INSET,
1.3 deraadt 179: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
180: linesperregion = 2 + secs;
1.1 deraadt 181: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 182: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 183: if (row > wnd->_maxy - linesperregion)
1.1 deraadt 184: break;
1.6 maja 185: mvwprintw(wnd, row++, 0, "%4.4s Kps|", cur.dk_name[i]);
1.1 deraadt 186: mvwaddstr(wnd, row++, 0, " tps|");
1.3 deraadt 187: if (secs)
188: mvwaddstr(wnd, row++, 0, " msec|");
1.1 deraadt 189: }
190: return (row);
191: }
192:
193:
194: void
195: showiostat()
196: {
1.13 mpech 197: int i, row, col;
1.1 deraadt 198:
1.3 deraadt 199: dkswap();
200:
1.1 deraadt 201: etime = 0;
202: for(i = 0; i < CPUSTATES; i++) {
1.3 deraadt 203: etime += cur.cp_time[i];
1.1 deraadt 204: }
205: if (etime == 0.0)
206: etime = 1.0;
207: etime /= (float) hz;
208: row = 1;
209:
210: /*
211: * Interrupt CPU state not calculated yet.
1.16 ! deraadt 212: */
1.1 deraadt 213: for (i = 0; i < CPUSTATES; i++)
214: stat1(row++, i);
1.7 kstailey 215:
216: if (dk_ndrive == 0)
217: return;
218:
1.1 deraadt 219: if (!numbers) {
220: row += 2;
221: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 222: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 223: if (row > wnd->_maxy - linesperregion)
1.1 deraadt 224: break;
225: row = stats(row, INSET, i);
226: }
227: return;
228: }
1.11 deraadt 229: col = INSET;
1.1 deraadt 230: wmove(wnd, row + linesperregion, 0);
231: wdeleteln(wnd);
232: wmove(wnd, row + 3, 0);
233: winsertln(wnd);
234: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 235: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 236: if (col + COLWIDTH >= wnd->_maxx) {
1.11 deraadt 237: col = INSET, row += linesperregion + 1;
1.4 mickey 238: if (row > wnd->_maxy - (linesperregion + 1))
1.1 deraadt 239: break;
240: wmove(wnd, row + linesperregion, 0);
241: wdeleteln(wnd);
242: wmove(wnd, row + 3, 0);
243: winsertln(wnd);
244: }
245: (void) stats(row + 3, col, i);
246: col += COLWIDTH;
247: }
248: }
249:
250: static int
251: stats(row, col, dn)
252: int row, col, dn;
253: {
1.3 deraadt 254: double atime, words;
255:
256: /* time busy in disk activity */
257: atime = (double)cur.dk_time[dn].tv_sec +
258: ((double)cur.dk_time[dn].tv_usec / (double)1000000);
1.1 deraadt 259:
1.3 deraadt 260: words = cur.dk_bytes[dn] / 1024.0; /* # of K transferred */
1.1 deraadt 261: if (numbers) {
1.11 deraadt 262: mvwprintw(wnd, row, col, "%5.0f%4.0f%5.1f",
1.3 deraadt 263: words / etime, cur.dk_xfer[dn] / etime, atime / etime);
1.1 deraadt 264: return (row);
265: }
266: wmove(wnd, row++, col);
1.3 deraadt 267: histogram(words / etime, 50, 0.5);
1.1 deraadt 268: wmove(wnd, row++, col);
1.3 deraadt 269: histogram(cur.dk_xfer[dn] / etime, 50, 0.5);
270: if (secs) {
1.1 deraadt 271: wmove(wnd, row++, col);
1.3 deraadt 272: atime *= 1000; /* In milliseconds */
273: histogram(atime / etime, 50, 0.5);
1.1 deraadt 274: }
275: return (row);
276: }
277:
278: static void
279: stat1(row, o)
280: int row, o;
281: {
1.13 mpech 282: int i;
1.1 deraadt 283: double time;
284:
285: time = 0;
286: for (i = 0; i < CPUSTATES; i++)
1.3 deraadt 287: time += cur.cp_time[i];
1.1 deraadt 288: if (time == 0.0)
289: time = 1.0;
290: wmove(wnd, row, INSET);
291: #define CPUSCALE 0.5
1.3 deraadt 292: histogram(100.0 * cur.cp_time[o] / time, 50, CPUSCALE);
1.1 deraadt 293: }
294:
295: static void
296: histogram(val, colwidth, scale)
297: double val;
298: int colwidth;
299: double scale;
300: {
301: char buf[10];
1.13 mpech 302: int k;
303: int v = (int)(val * scale) + 0.5;
1.1 deraadt 304:
305: k = MIN(v, colwidth);
306: if (v > colwidth) {
1.10 deraadt 307: snprintf(buf, sizeof buf, "%4.1f", val);
1.1 deraadt 308: k -= strlen(buf);
309: while (k--)
310: waddch(wnd, 'X');
311: waddstr(wnd, buf);
1.3 deraadt 312: wclrtoeol(wnd);
1.1 deraadt 313: return;
314: }
315: while (k--)
316: waddch(wnd, 'X');
317: wclrtoeol(wnd);
318: }
319:
320: int
321: cmdiostat(cmd, args)
322: char *cmd, *args;
323: {
324:
1.3 deraadt 325: if (prefix(cmd, "secs"))
326: secs = !secs;
1.1 deraadt 327: else if (prefix(cmd, "numbers"))
328: numbers = 1;
329: else if (prefix(cmd, "bars"))
330: numbers = 0;
331: else if (!dkcmd(cmd, args))
332: return (0);
333: wclear(wnd);
334: labeliostat();
335: refresh();
336: return (1);
337: }