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