use standard headers to get declarations; strdup is now in libc
[unix-history] / usr / src / usr.bin / systat / iostat.c
CommitLineData
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 8static 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
18WINDOW *
19openiostat()
20{
b5eefd1e 21 return (subwin(stdscr, LINES-1-5, 0, 5, 0));
8b38f7fc
SL
22}
23
24closeiostat(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
34static 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 60static 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
69static int linesperregion;
70static double etime;
eef33ea7
KB
71static int numbers = 0; /* default display bar graphs */
72static int msps = 0; /* default ms/seek shown */
8b38f7fc 73
2202cfef
CT
74static int numlabels(), barlabels(), stats();
75static void stat1();
76
8b38f7fc
SL
77initiostat()
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
101fetchiostat()
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
120labeliostat()
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 142static int
855ff304 143numlabels(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 181static int
855ff304 182barlabels(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
202showiostat()
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 255static int
855ff304 256stats(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 288static void
8b38f7fc 289stat1(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 305histogram(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 328cmdiostat(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}