Annotation of src/usr.bin/systat/iostat.c, Revision 1.5
1.5 ! deraadt 1: /* $OpenBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej 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.5 ! deraadt 41: static char rcsid[] = "$OpenBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $";
1.1 deraadt 42: #endif not lint
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 <nlist.h>
52: #include <paths.h>
53: #include "systat.h"
54: #include "extern.h"
55:
1.3 deraadt 56: #include "dkstats.h"
57: extern struct _disk cur;
1.1 deraadt 58:
59: static int linesperregion;
60: static double etime;
61: static int numbers = 0; /* default display bar graphs */
1.3 deraadt 62: static int secs = 0; /* default seconds shown */
1.1 deraadt 63:
64: static int barlabels __P((int));
65: static void histogram __P((double, int, double));
66: static int numlabels __P((int));
67: static int stats __P((int, int, int));
68: static void stat1 __P((int, int));
69:
70:
71: WINDOW *
72: openiostat()
73: {
74: return (subwin(stdscr, LINES-1-5, 0, 5, 0));
75: }
76:
77: void
78: closeiostat(w)
79: WINDOW *w;
80: {
81: if (w == NULL)
82: return;
83: wclear(w);
84: wrefresh(w);
85: delwin(w);
86: }
87:
88: int
89: initiostat()
90: {
1.3 deraadt 91: dkinit(1);
92: dkreadstats();
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:
1.3 deraadt 110: if (dk_ndrive == 0) {
111: error("No drives defined.");
1.1 deraadt 112: return;
113: }
114: row = 0;
115: wmove(wnd, row, 0); wclrtobot(wnd);
116: mvwaddstr(wnd, row++, INSET,
117: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
118: mvwaddstr(wnd, row++, 0, "cpu user|");
119: mvwaddstr(wnd, row++, 0, " nice|");
120: mvwaddstr(wnd, row++, 0, " system|");
121: mvwaddstr(wnd, row++, 0, "interrupt|");
122: mvwaddstr(wnd, row++, 0, " idle|");
123: if (numbers)
124: row = numlabels(row + 1);
125: else
126: row = barlabels(row + 1);
127: }
128:
129: static int
130: numlabels(row)
131: int row;
132: {
133: int i, col, regions, ndrives;
134:
135: #define COLWIDTH 14
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;
151: col = 0;
152: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 153: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 154: if (col + COLWIDTH >= wnd->_maxx - INSET) {
1.1 deraadt 155: col = 0, 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]);
160: mvwaddstr(wnd, row + 1, col, "Kps 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:
174: mvwaddstr(wnd, row++, INSET,
1.3 deraadt 175: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
176: linesperregion = 2 + secs;
1.1 deraadt 177: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 178: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 179: if (row > wnd->_maxy - linesperregion)
1.1 deraadt 180: break;
1.3 deraadt 181: mvwprintw(wnd, row++, 0, "%3.3s Kps|", cur.dk_name[i]);
1.1 deraadt 182: mvwaddstr(wnd, row++, 0, " tps|");
1.3 deraadt 183: if (secs)
184: mvwaddstr(wnd, row++, 0, " msec|");
1.1 deraadt 185: }
186: return (row);
187: }
188:
189:
190: void
191: showiostat()
192: {
1.3 deraadt 193: register u_int64_t t;
1.1 deraadt 194: register int i, row, col;
195:
1.3 deraadt 196: if (dk_ndrive == 0)
1.1 deraadt 197: return;
1.3 deraadt 198: dkswap();
199:
1.1 deraadt 200: etime = 0;
201: for(i = 0; i < CPUSTATES; i++) {
1.3 deraadt 202: etime += cur.cp_time[i];
1.1 deraadt 203: }
204: if (etime == 0.0)
205: etime = 1.0;
206: etime /= (float) hz;
207: row = 1;
208:
209: /*
210: * Interrupt CPU state not calculated yet.
211: */
212: for (i = 0; i < CPUSTATES; i++)
213: stat1(row++, i);
214: if (!numbers) {
215: row += 2;
216: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 217: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 218: if (row > wnd->_maxy - linesperregion)
1.1 deraadt 219: break;
220: row = stats(row, INSET, i);
221: }
222: return;
223: }
224: col = 0;
225: wmove(wnd, row + linesperregion, 0);
226: wdeleteln(wnd);
227: wmove(wnd, row + 3, 0);
228: winsertln(wnd);
229: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 230: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 mickey 231: if (col + COLWIDTH >= wnd->_maxx) {
1.1 deraadt 232: col = 0, row += linesperregion + 1;
1.4 mickey 233: if (row > wnd->_maxy - (linesperregion + 1))
1.1 deraadt 234: break;
235: wmove(wnd, row + linesperregion, 0);
236: wdeleteln(wnd);
237: wmove(wnd, row + 3, 0);
238: winsertln(wnd);
239: }
240: (void) stats(row + 3, col, i);
241: col += COLWIDTH;
242: }
243: }
244:
245: static int
246: stats(row, col, dn)
247: int row, col, dn;
248: {
1.3 deraadt 249: double atime, words;
250:
251: /* time busy in disk activity */
252: atime = (double)cur.dk_time[dn].tv_sec +
253: ((double)cur.dk_time[dn].tv_usec / (double)1000000);
1.1 deraadt 254:
1.3 deraadt 255: words = cur.dk_bytes[dn] / 1024.0; /* # of K transferred */
1.1 deraadt 256: if (numbers) {
257: mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f",
1.3 deraadt 258: words / etime, cur.dk_xfer[dn] / etime, atime / etime);
1.1 deraadt 259: return (row);
260: }
261: wmove(wnd, row++, col);
1.3 deraadt 262: histogram(words / etime, 50, 0.5);
1.1 deraadt 263: wmove(wnd, row++, col);
1.3 deraadt 264: histogram(cur.dk_xfer[dn] / etime, 50, 0.5);
265: if (secs) {
1.1 deraadt 266: wmove(wnd, row++, col);
1.3 deraadt 267: atime *= 1000; /* In milliseconds */
268: histogram(atime / etime, 50, 0.5);
1.1 deraadt 269: }
270: return (row);
271: }
272:
273: static void
274: stat1(row, o)
275: int row, o;
276: {
277: register int i;
278: double time;
279:
280: time = 0;
281: for (i = 0; i < CPUSTATES; i++)
1.3 deraadt 282: time += cur.cp_time[i];
1.1 deraadt 283: if (time == 0.0)
284: time = 1.0;
285: wmove(wnd, row, INSET);
286: #define CPUSCALE 0.5
1.3 deraadt 287: histogram(100.0 * cur.cp_time[o] / time, 50, CPUSCALE);
1.1 deraadt 288: }
289:
290: static void
291: histogram(val, colwidth, scale)
292: double val;
293: int colwidth;
294: double scale;
295: {
296: char buf[10];
297: register int k;
298: register int v = (int)(val * scale) + 0.5;
299:
300: k = MIN(v, colwidth);
301: if (v > colwidth) {
302: sprintf(buf, "%4.1f", val);
303: k -= strlen(buf);
304: while (k--)
305: waddch(wnd, 'X');
306: waddstr(wnd, buf);
1.3 deraadt 307: wclrtoeol(wnd);
1.1 deraadt 308: return;
309: }
310: while (k--)
311: waddch(wnd, 'X');
312: wclrtoeol(wnd);
313: }
314:
315: int
316: cmdiostat(cmd, args)
317: char *cmd, *args;
318: {
319:
1.3 deraadt 320: if (prefix(cmd, "secs"))
321: secs = !secs;
1.1 deraadt 322: else if (prefix(cmd, "numbers"))
323: numbers = 1;
324: else if (prefix(cmd, "bars"))
325: numbers = 0;
326: else if (!dkcmd(cmd, args))
327: return (0);
328: wclear(wnd);
329: labeliostat();
330: refresh();
331: return (1);
332: }