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 |
eef33ea7 | 8 | static char sccsid[] = "@(#)iostat.c 5.4 (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 SL |
73 | |
74 | initiostat() | |
75 | { | |
eef33ea7 KB |
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 | } | |
c0b7e584 JB |
83 | if (! dkinit()) |
84 | return(0); | |
833d578b SL |
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 | } | |
c0b7e584 | 95 | return(1); |
8b38f7fc SL |
96 | } |
97 | ||
98 | fetchiostat() | |
99 | { | |
eef33ea7 KB |
100 | if (nlst[X_DK_BUSY].n_type == 0) |
101 | return; | |
833d578b | 102 | s.dk_busy = getw(nlst[X_DK_BUSY].n_value); |
eef33ea7 KB |
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); | |
8b38f7fc SL |
113 | } |
114 | ||
b5eefd1e SL |
115 | #define INSET 10 |
116 | ||
8b38f7fc SL |
117 | labeliostat() |
118 | { | |
eef33ea7 | 119 | int row; |
8b38f7fc | 120 | |
eef33ea7 KB |
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); | |
855ff304 KM |
137 | } |
138 | ||
139 | static | |
140 | numlabels(row) | |
141 | { | |
eef33ea7 | 142 | int i, col, regions, ndrives; |
855ff304 | 143 | |
eef33ea7 KB |
144 | #define COLWIDTH 14 |
145 | #define DRIVESPERLINE ((wnd->_maxx - INSET) / COLWIDTH) | |
833d578b SL |
146 | for (ndrives = 0, i = 0; i < dk_ndrive; i++) |
147 | if (dk_select[i]) | |
148 | ndrives++; | |
eef33ea7 KB |
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); | |
855ff304 KM |
175 | } |
176 | ||
177 | static | |
178 | barlabels(row) | |
eef33ea7 | 179 | int row; |
855ff304 | 180 | { |
eef33ea7 | 181 | int i; |
855ff304 | 182 | |
eef33ea7 KB |
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); | |
8b38f7fc SL |
196 | } |
197 | ||
198 | showiostat() | |
199 | { | |
eef33ea7 KB |
200 | register int i, row, col; |
201 | register long t; | |
8b38f7fc | 202 | |
eef33ea7 KB |
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 | } | |
8b38f7fc SL |
249 | } |
250 | ||
855ff304 KM |
251 | static |
252 | stats(row, col, dn) | |
eef33ea7 | 253 | int row, dn; |
8b38f7fc | 254 | { |
eef33ea7 | 255 | double atime, words, xtime, itime; |
8b38f7fc | 256 | |
eef33ea7 KB |
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); | |
8b38f7fc SL |
282 | } |
283 | ||
855ff304 | 284 | static |
8b38f7fc | 285 | stat1(row, o) |
eef33ea7 | 286 | int row, o; |
8b38f7fc | 287 | { |
eef33ea7 KB |
288 | register i; |
289 | double time; | |
8b38f7fc | 290 | |
eef33ea7 KB |
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 * s.cp_time[o] / time, 50, CPUSCALE); | |
8b38f7fc SL |
299 | } |
300 | ||
855ff304 | 301 | histogram(val, colwidth, scale) |
eef33ea7 KB |
302 | double val; |
303 | int colwidth; | |
304 | double scale; | |
8b38f7fc | 305 | { |
eef33ea7 KB |
306 | char buf[10]; |
307 | register int k; | |
308 | register int v = (int)(val * scale) + 0.5; | |
8b38f7fc | 309 | |
eef33ea7 KB |
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); | |
8b38f7fc SL |
322 | } |
323 | ||
855ff304 | 324 | cmdiostat(cmd, args) |
eef33ea7 | 325 | char *cmd, *args; |
8b38f7fc | 326 | { |
8b38f7fc | 327 | |
eef33ea7 KB |
328 | if (prefix(cmd, "msps")) |
329 | msps = !msps; | |
833d578b | 330 | else if (prefix(cmd, "numbers")) |
eef33ea7 | 331 | numbers = 1; |
833d578b | 332 | else if (prefix(cmd, "bars")) |
eef33ea7 | 333 | numbers = 0; |
833d578b SL |
334 | else if (!dkcmd(cmd, args)) |
335 | return (0); | |
eef33ea7 KB |
336 | wclear(wnd); |
337 | labeliostat(); | |
338 | refresh(); | |
339 | return (1); | |
8b38f7fc | 340 | } |