|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)iostat.c 5.5 (Berkeley) 5/29/89";
9: #endif not lint
10:
11: /*
12: * iostat
13: */
14: #include "systat.h"
15: #include <sys/buf.h>
16: #include <paths.h>
17:
18: WINDOW *
19: openiostat()
20: {
21: return (subwin(stdscr, LINES-1-5, 0, 5, 0));
22: }
23:
24: closeiostat(w)
25: WINDOW *w;
26: {
27: if (w == NULL)
28: return;
29: wclear(w);
30: wrefresh(w);
31: delwin(w);
32: }
33:
34: static struct nlist nlst[] = {
35: #define X_DK_BUSY 0
36: { "_dk_busy" },
37: #define X_DK_TIME 1
38: { "_dk_time" },
39: #define X_DK_XFER 2
40: { "_dk_xfer" },
41: #define X_DK_WDS 3
42: { "_dk_wds" },
43: #define X_DK_SEEK 4
44: { "_dk_seek" },
45: #define X_CP_TIME 5
46: { "_cp_time" },
47: #ifdef vax
48: #define X_MBDINIT (X_CP_TIME+1)
49: { "_mbdinit" },
50: #define X_UBDINIT (X_CP_TIME+2)
51: { "_ubdinit" },
52: #endif
53: #ifdef tahoe
54: #define X_VBDINIT (X_CP_TIME+1)
55: { "_vbdinit" },
56: #endif
57: { "" },
58: };
59:
60: static struct {
61: int dk_busy;
62: long cp_time[CPUSTATES];
63: long *dk_time;
64: long *dk_wds;
65: long *dk_seek;
66: long *dk_xfer;
67: } s, s1;
68:
69: static int linesperregion;
70: static double etime;
71: static int numbers = 0; /* default display bar graphs */
72: static int msps = 0; /* default ms/seek shown */
73:
74: initiostat()
75: {
76: if (nlst[X_DK_BUSY].n_type == 0) {
77: nlist(_PATH_UNIX, nlst);
78: if (nlst[X_DK_BUSY].n_type == 0) {
79: error("Disk init information isn't in namelist");
80: return(0);
81: }
82: }
83: if (! dkinit())
84: return(0);
85: if (dk_ndrive) {
86: #define allocate(e, t) \
87: s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
88: s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
89: allocate(dk_time, long);
90: allocate(dk_wds, long);
91: allocate(dk_seek, long);
92: allocate(dk_xfer, long);
93: #undef allocate
94: }
95: return(1);
96: }
97:
98: fetchiostat()
99: {
100: if (nlst[X_DK_BUSY].n_type == 0)
101: return;
102: s.dk_busy = getw(nlst[X_DK_BUSY].n_value);
103: lseek(kmem, (long)nlst[X_DK_TIME].n_value, L_SET);
104: read(kmem, s.dk_time, dk_ndrive * sizeof (long));
105: lseek(kmem, (long)nlst[X_DK_XFER].n_value, L_SET);
106: read(kmem, s.dk_xfer, dk_ndrive * sizeof (long));
107: lseek(kmem, (long)nlst[X_DK_WDS].n_value, L_SET);
108: read(kmem, s.dk_wds, dk_ndrive * sizeof (long));
109: lseek(kmem, (long)nlst[X_DK_SEEK].n_value, L_SET);
110: read(kmem, s.dk_seek, dk_ndrive * sizeof (long));
111: lseek(kmem, (long)nlst[X_CP_TIME].n_value, L_SET);
112: read(kmem, s.cp_time, sizeof s.cp_time);
113: }
114:
115: #define INSET 10
116:
117: labeliostat()
118: {
119: int row;
120:
121: if (nlst[X_DK_BUSY].n_type == 0) {
122: error("No dk_busy defined.");
123: return;
124: }
125: row = 0;
126: wmove(wnd, row, 0); wclrtobot(wnd);
127: mvwaddstr(wnd, row++, INSET,
128: "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100");
129: mvwaddstr(wnd, row++, 0, "cpu user|");
130: mvwaddstr(wnd, row++, 0, " nice|");
131: mvwaddstr(wnd, row++, 0, " system|");
132: mvwaddstr(wnd, row++, 0, " idle|");
133: if (numbers)
134: row = numlabels(row + 1);
135: else
136: row = barlabels(row + 1);
137: }
138:
139: static
140: numlabels(row)
141: {
142: int i, col, regions, ndrives;
143:
144: #define COLWIDTH 14
145: #define DRIVESPERLINE ((wnd->_maxx - INSET) / COLWIDTH)
146: for (ndrives = 0, i = 0; i < dk_ndrive; i++)
147: if (dk_select[i])
148: ndrives++;
149: regions = howmany(ndrives, DRIVESPERLINE);
150: /*
151: * Deduct -regions for blank line after each scrolling region.
152: */
153: linesperregion = (wnd->_maxy - row - regions) / regions;
154: /*
155: * Minimum region contains space for two
156: * label lines and one line of statistics.
157: */
158: if (linesperregion < 3)
159: linesperregion = 3;
160: col = 0;
161: for (i = 0; i < dk_ndrive; i++)
162: if (dk_select[i] && dk_mspw[i] != 0.0) {
163: if (col + COLWIDTH >= wnd->_maxx - INSET) {
164: col = 0, row += linesperregion + 1;
165: if (row > wnd->_maxy - (linesperregion + 1))
166: break;
167: }
168: mvwaddstr(wnd, row, col + 4, dr_name[i]);
169: mvwaddstr(wnd, row + 1, col, "bps tps msps");
170: col += COLWIDTH;
171: }
172: if (col)
173: row += linesperregion + 1;
174: return (row);
175: }
176:
177: static
178: barlabels(row)
179: int row;
180: {
181: int i;
182:
183: mvwaddstr(wnd, row++, INSET,
184: "/0 /5 /10 /15 /20 /25 /30 /35 /40 /45 /50");
185: linesperregion = 2 + msps;
186: for (i = 0; i < dk_ndrive; i++)
187: if (dk_select[i] && dk_mspw[i] != 0.0) {
188: if (row > wnd->_maxy - linesperregion)
189: break;
190: mvwprintw(wnd, row++, 0, "%3.3s bps|", dr_name[i]);
191: mvwaddstr(wnd, row++, 0, " tps|");
192: if (msps)
193: mvwaddstr(wnd, row++, 0, " msps|");
194: }
195: return (row);
196: }
197:
198: showiostat()
199: {
200: register int i, row, col;
201: register long t;
202:
203: if (nlst[X_DK_BUSY].n_type == 0)
204: return;
205: for (i = 0; i < dk_ndrive; i++) {
206: #define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t
207: X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
208: }
209: etime = 0;
210: for(i = 0; i < CPUSTATES; i++) {
211: X(cp_time);
212: etime += s.cp_time[i];
213: }
214: if (etime == 0.0)
215: etime = 1.0;
216: etime /= (float) hz;
217: row = 1;
218: for (i = 0; i < CPUSTATES; i++)
219: stat1(row++, i);
220: if (!numbers) {
221: row += 2;
222: for (i = 0; i < dk_ndrive; i++)
223: if (dk_select[i] && dk_mspw[i] != 0.0) {
224: if (row > wnd->_maxy - linesperregion)
225: break;
226: row = stats(row, INSET, i);
227: }
228: return;
229: }
230: col = 0;
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++)
236: if (dk_select[i] && dk_mspw[i] != 0.0) {
237: if (col + COLWIDTH >= wnd->_maxx) {
238: col = 0, row += linesperregion + 1;
239: if (row > wnd->_maxy - (linesperregion + 1))
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
252: stats(row, col, dn)
253: int row, dn;
254: {
255: double atime, words, xtime, itime;
256:
257: atime = s.dk_time[dn];
258: atime /= (float) hz;
259: words = s.dk_wds[dn]*32.0; /* number of words transferred */
260: xtime = dk_mspw[dn]*words; /* transfer time */
261: itime = atime - xtime; /* time not transferring */
262: if (xtime < 0)
263: itime += xtime, xtime = 0;
264: if (itime < 0)
265: xtime += itime, itime = 0;
266: if (numbers) {
267: mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f",
268: words / 512 / etime, s.dk_xfer[dn] / etime,
269: s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0.0);
270: return (row);
271: }
272: wmove(wnd, row++, col);
273: histogram(words / 512 / etime, 50, 1.0);
274: wmove(wnd, row++, col);
275: histogram(s.dk_xfer[dn] / etime, 50, 1.0);
276: if (msps) {
277: wmove(wnd, row++, col);
278: histogram(s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0,
279: 50, 1.0);
280: }
281: return (row);
282: }
283:
284: static
285: stat1(row, o)
286: int row, o;
287: {
288: register i;
289: double time;
290:
291: time = 0;
292: for (i = 0; i < CPUSTATES; i++)
293: time += s.cp_time[i];
294: if (time == 0.0)
295: time = 1.0;
296: wmove(wnd, row, INSET);
297: #define CPUSCALE 0.5
298: histogram(100.0 * s.cp_time[o] / time, 50, CPUSCALE);
299: }
300:
301: histogram(val, colwidth, scale)
302: double val;
303: int colwidth;
304: double scale;
305: {
306: char buf[10];
307: register int k;
308: register int v = (int)(val * scale) + 0.5;
309:
310: k = MIN(v, colwidth);
311: if (v > colwidth) {
312: sprintf(buf, "%4.1f", val);
313: k -= strlen(buf);
314: while (k--)
315: waddch(wnd, 'X');
316: waddstr(wnd, buf);
317: return;
318: }
319: while (k--)
320: waddch(wnd, 'X');
321: wclrtoeol(wnd);
322: }
323:
324: cmdiostat(cmd, args)
325: char *cmd, *args;
326: {
327:
328: if (prefix(cmd, "msps"))
329: msps = !msps;
330: else if (prefix(cmd, "numbers"))
331: numbers = 1;
332: else if (prefix(cmd, "bars"))
333: numbers = 0;
334: else if (!dkcmd(cmd, args))
335: return (0);
336: wclear(wnd);
337: labeliostat();
338: refresh();
339: return (1);
340: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.