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