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