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