Annotation of src/usr.bin/systat/iostat.c, Revision 1.4
1.3 deraadt 1: /* $NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $ */
1.1 deraadt 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
1.3 deraadt 40: static char rcsid[] = "$NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $";
1.1 deraadt 41: #endif not lint
42:
43: #include <sys/param.h>
44: #include <sys/dkstat.h>
45: #include <sys/buf.h>
1.3 deraadt 46: #include <sys/time.h>
1.1 deraadt 47:
48: #include <string.h>
49: #include <stdlib.h>
50: #include <nlist.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.1 deraadt 92: }
93:
94: void
95: fetchiostat()
96: {
1.3 deraadt 97: if (dk_ndrive == 0)
1.1 deraadt 98: return;
1.3 deraadt 99: dkreadstats();
1.1 deraadt 100: }
101:
102: #define INSET 10
103:
104: void
105: labeliostat()
106: {
107: int row;
108:
1.3 deraadt 109: if (dk_ndrive == 0) {
110: error("No drives defined.");
1.1 deraadt 111: return;
112: }
113: row = 0;
114: wmove(wnd, row, 0); wclrtobot(wnd);
115: mvwaddstr(wnd, row++, INSET,
116: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
117: mvwaddstr(wnd, row++, 0, "cpu user|");
118: mvwaddstr(wnd, row++, 0, " nice|");
119: mvwaddstr(wnd, row++, 0, " system|");
120: mvwaddstr(wnd, row++, 0, "interrupt|");
121: mvwaddstr(wnd, row++, 0, " idle|");
122: if (numbers)
123: row = numlabels(row + 1);
124: else
125: row = barlabels(row + 1);
126: }
127:
128: static int
129: numlabels(row)
130: int row;
131: {
132: int i, col, regions, ndrives;
133:
134: #define COLWIDTH 14
1.4 ! mickey 135: #define DRIVESPERLINE ((wnd->_maxx - INSET) / COLWIDTH)
1.1 deraadt 136: for (ndrives = 0, i = 0; i < dk_ndrive; i++)
1.3 deraadt 137: if (cur.dk_select[i])
1.1 deraadt 138: ndrives++;
139: regions = howmany(ndrives, DRIVESPERLINE);
140: /*
141: * Deduct -regions for blank line after each scrolling region.
142: */
1.4 ! mickey 143: linesperregion = (wnd->_maxy - row - regions) / regions;
1.1 deraadt 144: /*
145: * Minimum region contains space for two
146: * label lines and one line of statistics.
147: */
148: if (linesperregion < 3)
149: linesperregion = 3;
150: col = 0;
151: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 152: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 ! mickey 153: if (col + COLWIDTH >= wnd->_maxx - INSET) {
1.1 deraadt 154: col = 0, row += linesperregion + 1;
1.4 ! mickey 155: if (row > wnd->_maxy - (linesperregion + 1))
1.1 deraadt 156: break;
157: }
1.3 deraadt 158: mvwaddstr(wnd, row, col + 4, cur.dk_name[i]);
159: mvwaddstr(wnd, row + 1, col, "Kps tps sec");
1.1 deraadt 160: col += COLWIDTH;
161: }
162: if (col)
163: row += linesperregion + 1;
164: return (row);
165: }
166:
167: static int
168: barlabels(row)
169: int row;
170: {
171: int i;
172:
173: mvwaddstr(wnd, row++, INSET,
1.3 deraadt 174: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
175: linesperregion = 2 + secs;
1.1 deraadt 176: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 177: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 ! mickey 178: if (row > wnd->_maxy - linesperregion)
1.1 deraadt 179: break;
1.3 deraadt 180: mvwprintw(wnd, row++, 0, "%3.3s Kps|", cur.dk_name[i]);
1.1 deraadt 181: mvwaddstr(wnd, row++, 0, " tps|");
1.3 deraadt 182: if (secs)
183: mvwaddstr(wnd, row++, 0, " msec|");
1.1 deraadt 184: }
185: return (row);
186: }
187:
188:
189: void
190: showiostat()
191: {
1.3 deraadt 192: register u_int64_t t;
1.1 deraadt 193: register int i, row, col;
194:
1.3 deraadt 195: if (dk_ndrive == 0)
1.1 deraadt 196: return;
1.3 deraadt 197: dkswap();
198:
1.1 deraadt 199: etime = 0;
200: for(i = 0; i < CPUSTATES; i++) {
1.3 deraadt 201: etime += cur.cp_time[i];
1.1 deraadt 202: }
203: if (etime == 0.0)
204: etime = 1.0;
205: etime /= (float) hz;
206: row = 1;
207:
208: /*
209: * Interrupt CPU state not calculated yet.
210: */
211: for (i = 0; i < CPUSTATES; i++)
212: stat1(row++, i);
213: if (!numbers) {
214: row += 2;
215: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 216: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 ! mickey 217: if (row > wnd->_maxy - linesperregion)
1.1 deraadt 218: break;
219: row = stats(row, INSET, i);
220: }
221: return;
222: }
223: col = 0;
224: wmove(wnd, row + linesperregion, 0);
225: wdeleteln(wnd);
226: wmove(wnd, row + 3, 0);
227: winsertln(wnd);
228: for (i = 0; i < dk_ndrive; i++)
1.3 deraadt 229: if (cur.dk_select[i] /*&& cur.dk_bytes[i] != 0.0*/) {
1.4 ! mickey 230: if (col + COLWIDTH >= wnd->_maxx) {
1.1 deraadt 231: col = 0, row += linesperregion + 1;
1.4 ! mickey 232: if (row > wnd->_maxy - (linesperregion + 1))
1.1 deraadt 233: break;
234: wmove(wnd, row + linesperregion, 0);
235: wdeleteln(wnd);
236: wmove(wnd, row + 3, 0);
237: winsertln(wnd);
238: }
239: (void) stats(row + 3, col, i);
240: col += COLWIDTH;
241: }
242: }
243:
244: static int
245: stats(row, col, dn)
246: int row, col, dn;
247: {
1.3 deraadt 248: double atime, words;
249:
250: /* time busy in disk activity */
251: atime = (double)cur.dk_time[dn].tv_sec +
252: ((double)cur.dk_time[dn].tv_usec / (double)1000000);
1.1 deraadt 253:
1.3 deraadt 254: words = cur.dk_bytes[dn] / 1024.0; /* # of K transferred */
1.1 deraadt 255: if (numbers) {
256: mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f",
1.3 deraadt 257: words / etime, cur.dk_xfer[dn] / etime, atime / etime);
1.1 deraadt 258: return (row);
259: }
260: wmove(wnd, row++, col);
1.3 deraadt 261: histogram(words / etime, 50, 0.5);
1.1 deraadt 262: wmove(wnd, row++, col);
1.3 deraadt 263: histogram(cur.dk_xfer[dn] / etime, 50, 0.5);
264: if (secs) {
1.1 deraadt 265: wmove(wnd, row++, col);
1.3 deraadt 266: atime *= 1000; /* In milliseconds */
267: histogram(atime / etime, 50, 0.5);
1.1 deraadt 268: }
269: return (row);
270: }
271:
272: static void
273: stat1(row, o)
274: int row, o;
275: {
276: register int i;
277: double time;
278:
279: time = 0;
280: for (i = 0; i < CPUSTATES; i++)
1.3 deraadt 281: time += cur.cp_time[i];
1.1 deraadt 282: if (time == 0.0)
283: time = 1.0;
284: wmove(wnd, row, INSET);
285: #define CPUSCALE 0.5
1.3 deraadt 286: histogram(100.0 * cur.cp_time[o] / time, 50, CPUSCALE);
1.1 deraadt 287: }
288:
289: static void
290: histogram(val, colwidth, scale)
291: double val;
292: int colwidth;
293: double scale;
294: {
295: char buf[10];
296: register int k;
297: register int v = (int)(val * scale) + 0.5;
298:
299: k = MIN(v, colwidth);
300: if (v > colwidth) {
301: sprintf(buf, "%4.1f", val);
302: k -= strlen(buf);
303: while (k--)
304: waddch(wnd, 'X');
305: waddstr(wnd, buf);
1.3 deraadt 306: wclrtoeol(wnd);
1.1 deraadt 307: return;
308: }
309: while (k--)
310: waddch(wnd, 'X');
311: wclrtoeol(wnd);
312: }
313:
314: int
315: cmdiostat(cmd, args)
316: char *cmd, *args;
317: {
318:
1.3 deraadt 319: if (prefix(cmd, "secs"))
320: secs = !secs;
1.1 deraadt 321: else if (prefix(cmd, "numbers"))
322: numbers = 1;
323: else if (prefix(cmd, "bars"))
324: numbers = 0;
325: else if (!dkcmd(cmd, args))
326: return (0);
327: wclear(wnd);
328: labeliostat();
329: refresh();
330: return (1);
331: }