msps defaults to off
[unix-history] / usr / src / usr.bin / systat / iostat.c
CommitLineData
8b38f7fc 1#ifndef lint
2a68a21a 2static 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
17WINDOW *
18openiostat()
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
27closeiostat(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
39static 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
65static 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
74static int linesperregion;
75static double etime;
76static int numbers = 0; /* default display bar graphs */
2a68a21a 77static int msps = 0; /* default ms/seek shown */
855ff304 78static int dk_select[DK_NDRIVE];
8b38f7fc
SL
79
80initiostat()
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
109fetchiostat()
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
128labeliostat()
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
150static
151numlabels(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
185static
186barlabels(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
206showiostat()
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
260static
261stats(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 294static
8b38f7fc 295stat1(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
311histogram(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
334cmdiostat(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);
367fixdisplay:
368 wclear(wnd);
369 wrefresh(wnd);
370 labeliostat();
371 refresh();
372 return (1);
8b38f7fc 373}
8b38f7fc 374
855ff304
KM
375prefix(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}