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