Annotation of src/usr.bin/systat/vmstat.c, Revision 1.49
1.49 ! deraadt 1: /* $OpenBSD: vmstat.c,v 1.48 2004/06/11 05:55:43 deraadt Exp $ */
1.2 deraadt 2: /* $NetBSD: vmstat.c,v 1.5 1996/05/10 23:16:40 thorpej Exp $ */
1.1 deraadt 3:
4: /*-
5: * Copyright (c) 1983, 1989, 1992, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.41 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: #if 0
35: static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94";
36: #endif
1.49 ! deraadt 37: static char rcsid[] = "$OpenBSD: vmstat.c,v 1.48 2004/06/11 05:55:43 deraadt Exp $";
1.1 deraadt 38: #endif /* not lint */
39:
40: /*
41: * Cursed vmstat -- from Robert Elz.
42: */
43:
44: #include <sys/param.h>
45: #include <sys/dkstat.h>
46: #include <sys/buf.h>
47: #include <sys/stat.h>
48: #include <sys/time.h>
49: #include <sys/user.h>
50: #include <sys/proc.h>
51: #include <sys/namei.h>
52: #include <sys/sysctl.h>
53:
1.19 art 54: #include <uvm/uvm_extern.h>
55:
1.1 deraadt 56: #include <ctype.h>
57: #include <err.h>
58: #include <nlist.h>
59: #include <paths.h>
60: #include <signal.h>
61: #include <stdlib.h>
62: #include <string.h>
63: #include <utmp.h>
64: #include <unistd.h>
65:
1.18 espie 66: #if defined(__i386__)
1.3 tholo 67: #define _KERNEL
68: #include <machine/psl.h>
69: #undef _KERNEL
70: #endif
71:
1.1 deraadt 72: #include "systat.h"
73: #include "extern.h"
74:
75: static struct Info {
76: long time[CPUSTATES];
1.19 art 77: struct uvmexp uvmexp;
1.1 deraadt 78: struct vmtotal Total;
79: struct nchstats nchstats;
80: long nchcount;
1.38 jason 81: int *intrcnt;
1.1 deraadt 82: } s, s1, s2, z;
83:
1.2 deraadt 84: #include "dkstats.h"
85: extern struct _disk cur;
86:
1.1 deraadt 87: #define cnt s.Cnt
88: #define oldcnt s1.Cnt
89: #define total s.Total
90: #define nchtotal s.nchstats
91: #define oldnchtotal s1.nchstats
92:
93: static enum state { BOOT, TIME, RUN } state = TIME;
94:
1.33 millert 95: static void allocinfo(struct Info *);
96: static void copyinfo(struct Info *, struct Info *);
97: static float cputime(int);
98: static void dinfo(int, int);
99: static void getinfo(struct Info *, enum state);
100: static void putint(int, int, int, int);
101: static void putfloat(double, int, int, int, int, int);
102: static int ucount(void);
1.1 deraadt 103:
104: static int ut;
105: static char buf[26];
106: static time_t t;
107: static double etime;
108: static float hertz;
109: static int nintr;
110: static long *intrloc;
111: static char **intrname;
112: static int nextintsrow;
113:
114: struct utmp utmp;
115:
116: WINDOW *
1.35 deraadt 117: openkre(void)
1.1 deraadt 118: {
119:
120: ut = open(_PATH_UTMP, O_RDONLY);
121: if (ut < 0)
122: error("No utmp");
123: return (stdscr);
124: }
125:
126: void
1.35 deraadt 127: closekre(WINDOW *w)
1.1 deraadt 128: {
129:
130: (void) close(ut);
131: if (w == NULL)
132: return;
133: wclear(w);
134: wrefresh(w);
135: }
136:
137:
138: static struct nlist namelist[] = {
1.36 deraadt 139: #define X_INTRNAMES 0 /* no sysctl */
1.1 deraadt 140: { "_intrnames" },
1.36 deraadt 141: #define X_EINTRNAMES 1 /* no sysctl */
1.1 deraadt 142: { "_eintrnames" },
1.36 deraadt 143: #define X_INTRCNT 2 /* no sysctl */
1.1 deraadt 144: { "_intrcnt" },
1.36 deraadt 145: #define X_EINTRCNT 3 /* no sysctl */
1.1 deraadt 146: { "_eintrcnt" },
1.18 espie 147: #if defined(__i386__)
1.36 deraadt 148: #define X_INTRHAND 4 /* no sysctl */
1.3 tholo 149: { "_intrhand" },
1.48 deraadt 150: #define X_APICINTRHAND 5 /* no sysctl */
151: { "_apic_intrhand" },
1.3 tholo 152: #endif
1.1 deraadt 153: { "" },
154: };
155:
156: /*
157: * These constants define where the major pieces are laid out
158: */
159: #define STATROW 0 /* uses 1 row and 68 cols */
160: #define STATCOL 2
161: #define MEMROW 2 /* uses 4 rows and 31 cols */
162: #define MEMCOL 0
163: #define PAGEROW 2 /* uses 4 rows and 26 cols */
1.17 deraadt 164: #define PAGECOL 37
1.1 deraadt 165: #define INTSROW 2 /* uses all rows to bottom and 17 cols */
166: #define INTSCOL 63
167: #define PROCSROW 7 /* uses 2 rows and 20 cols */
168: #define PROCSCOL 0
1.27 deraadt 169: #define GENSTATROW 7 /* uses 2 rows and 35 cols */
170: #define GENSTATCOL 16
1.9 kstailey 171: #define VMSTATROW 7 /* uses 17 rows and 12 cols */
1.1 deraadt 172: #define VMSTATCOL 48
173: #define GRAPHROW 10 /* uses 3 rows and 51 cols */
174: #define GRAPHCOL 0
1.25 weingart 175: #define NAMEIROW 14 /* uses 3 rows and 49 cols */
1.1 deraadt 176: #define NAMEICOL 0
177: #define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */
178: #define DISKCOL 0
179:
1.32 tdeval 180: #define DRIVESPACE 45 /* max space for drives */
1.1 deraadt 181:
182: int
1.35 deraadt 183: initkre(void)
1.1 deraadt 184: {
185: char *intrnamebuf, *cp;
1.22 ericj 186: int i, ret;
1.1 deraadt 187:
188: if (namelist[0].n_type == 0) {
1.22 ericj 189: if ((ret = kvm_nlist(kd, namelist)) == -1)
190: errx(1, "%s", kvm_geterr(kd));
1.48 deraadt 191: #if defined(__i386__)
1.49 ! deraadt 192: else if (ret == 1 && namelist[X_APICINTRHAND].n_value != 0)
1.48 deraadt 193: nlisterr(namelist);
194: #endif
1.49 ! deraadt 195: else if (ret > 1)
1.1 deraadt 196: nlisterr(namelist);
197: if (namelist[0].n_type == 0) {
198: error("No namelist");
199: return(0);
200: }
201: }
202: hertz = stathz ? stathz : hz;
1.31 deraadt 203: if (!dkinit(1))
1.1 deraadt 204: return(0);
205: if (nintr == 0) {
1.18 espie 206: #if defined(__i386__)
1.3 tholo 207: struct intrhand *intrhand[16], *ihp, ih;
1.48 deraadt 208: struct intrhand *apicintrhand[256];
1.3 tholo 209: char iname[16];
210: int namelen, n;
211:
212: NREAD(X_INTRHAND, intrhand, sizeof(intrhand));
213: for (namelen = 0, i = 0; i < 16; i++) {
214: ihp = intrhand[i];
215: while (ihp) {
216: nintr++;
217: KREAD(ihp, &ih, sizeof(ih));
218: KREAD(ih.ih_what, iname, 16);
1.39 deraadt 219: namelen += strlen(iname) + 1;
1.3 tholo 220: ihp = ih.ih_next;
221: }
222: }
1.48 deraadt 223: if (namelist[X_APICINTRHAND].n_value) {
224: NREAD(X_APICINTRHAND, apicintrhand, sizeof(apicintrhand));
225: for (namelen = 0, i = 0; i < 256; i++) {
226: ihp = apicintrhand[i];
227: while (ihp) {
228: nintr++;
229: KREAD(ihp, &ih, sizeof(ih));
230: KREAD(ih.ih_what, iname, 16);
231: namelen += strlen(iname) + 1;
232: printf("apic handler %x %s\n", i, iname);
233: ihp = ih.ih_next;
234: }
235: }
236: }
1.3 tholo 237: intrloc = calloc(nintr, sizeof (long));
238: intrname = calloc(nintr, sizeof (char *));
239: cp = intrnamebuf = malloc(namelen);
1.39 deraadt 240: for (i = 0, n = 0; i < 16; i++) {
1.3 tholo 241: ihp = intrhand[i];
242: while (ihp) {
243: KREAD(ihp, &ih, sizeof(ih));
244: KREAD(ih.ih_what, iname, 16);
1.39 deraadt 245: intrname[n++] = cp;
246: strlcpy(cp, iname, intrnamebuf + namelen - cp);
247: cp += strlen(iname) + 1;
1.3 tholo 248: ihp = ih.ih_next;
249: }
250: }
1.48 deraadt 251: if (namelist[X_APICINTRHAND].n_value) {
252: for (i = 0, n = 0; i < 256; i++) {
253: ihp = apicintrhand[i];
254: while (ihp) {
255: KREAD(ihp, &ih, sizeof(ih));
256: KREAD(ih.ih_what, iname, 16);
257: intrname[n++] = cp;
258: strlcpy(cp, iname, intrnamebuf + namelen - cp);
259: cp += strlen(iname) + 1;
260: ihp = ih.ih_next;
261: }
262: }
263: }
1.3 tholo 264: #else
1.1 deraadt 265: nintr = (namelist[X_EINTRCNT].n_value -
1.38 jason 266: namelist[X_INTRCNT].n_value) / sizeof (int);
1.1 deraadt 267: intrloc = calloc(nintr, sizeof (long));
268: intrname = calloc(nintr, sizeof (long));
269: intrnamebuf = malloc(namelist[X_EINTRNAMES].n_value -
1.31 deraadt 270: namelist[X_INTRNAMES].n_value);
1.1 deraadt 271: if (intrnamebuf == 0 || intrname == 0 || intrloc == 0) {
272: error("Out of memory\n");
273: if (intrnamebuf)
274: free(intrnamebuf);
275: if (intrname)
276: free(intrname);
277: if (intrloc)
278: free(intrloc);
279: nintr = 0;
280: return(0);
281: }
282: NREAD(X_INTRNAMES, intrnamebuf, NVAL(X_EINTRNAMES) -
1.31 deraadt 283: NVAL(X_INTRNAMES));
1.1 deraadt 284: for (cp = intrnamebuf, i = 0; i < nintr; i++) {
285: intrname[i] = cp;
286: cp += strlen(cp) + 1;
287: }
1.3 tholo 288: #endif
1.1 deraadt 289: nextintsrow = INTSROW + 2;
290: allocinfo(&s);
291: allocinfo(&s1);
292: allocinfo(&s2);
293: allocinfo(&z);
294: }
295: getinfo(&s2, RUN);
296: copyinfo(&s2, &s1);
297: return(1);
298: }
299:
300: void
1.35 deraadt 301: fetchkre(void)
1.1 deraadt 302: {
303: time_t now;
304:
305: time(&now);
1.23 lebel 306: strlcpy(buf, ctime(&now), sizeof buf);
1.1 deraadt 307: getinfo(&s, state);
308: }
309:
310: void
1.35 deraadt 311: labelkre(void)
1.1 deraadt 312: {
1.32 tdeval 313: int i, j, l;
1.1 deraadt 314:
315: clear();
316: mvprintw(STATROW, STATCOL + 4, "users Load");
1.19 art 317: mvprintw(MEMROW, MEMCOL, " memory totals (in KB)");
318: mvprintw(MEMROW + 1, MEMCOL, " real virtual free");
319: mvprintw(MEMROW + 2, MEMCOL, "Active");
320: mvprintw(MEMROW + 3, MEMCOL, "All");
321:
322: mvprintw(PAGEROW, PAGECOL, " PAGING SWAPPING ");
323: mvprintw(PAGEROW + 1, PAGECOL, " in out in out ");
324: mvprintw(PAGEROW + 2, PAGECOL, "ops");
325: mvprintw(PAGEROW + 3, PAGECOL, "pages");
1.1 deraadt 326:
1.20 art 327: mvprintw(INTSROW, INTSCOL + 3, " Interrupts");
328: mvprintw(INTSROW + 1, INTSCOL + 9, "total");
329:
1.19 art 330: mvprintw(VMSTATROW + 0, VMSTATCOL + 10, "forks");
331: mvprintw(VMSTATROW + 1, VMSTATCOL + 10, "fkppw");
332: mvprintw(VMSTATROW + 2, VMSTATCOL + 10, "fksvm");
333: mvprintw(VMSTATROW + 3, VMSTATCOL + 10, "pwait");
334: mvprintw(VMSTATROW + 4, VMSTATCOL + 10, "relck");
335: mvprintw(VMSTATROW + 5, VMSTATCOL + 10, "rlkok");
336: mvprintw(VMSTATROW + 6, VMSTATCOL + 10, "noram");
337: mvprintw(VMSTATROW + 7, VMSTATCOL + 10, "ndcpy");
338: mvprintw(VMSTATROW + 8, VMSTATCOL + 10, "fltcp");
339: mvprintw(VMSTATROW + 9, VMSTATCOL + 10, "zfod");
340: mvprintw(VMSTATROW + 10, VMSTATCOL + 10, "cow");
341: mvprintw(VMSTATROW + 11, VMSTATCOL + 10, "fmin");
342: mvprintw(VMSTATROW + 12, VMSTATCOL + 10, "ftarg");
343: mvprintw(VMSTATROW + 13, VMSTATCOL + 10, "itarg");
344: mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "wired");
345: mvprintw(VMSTATROW + 15, VMSTATCOL + 10, "pdfre");
346: if (LINES - 1 > VMSTATROW + 16)
347: mvprintw(VMSTATROW + 16, VMSTATCOL + 10, "pdscn");
1.42 mickey 348: if (LINES - 1 > VMSTATROW + 17)
349: mvprintw(VMSTATROW + 17, VMSTATCOL + 10, "pzidle");
1.1 deraadt 350:
1.27 deraadt 351: mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt");
1.1 deraadt 352:
353: mvprintw(GRAPHROW, GRAPHCOL,
1.31 deraadt 354: " . %% Sys . %% User . %% Nice . %% Idle");
1.19 art 355: mvprintw(PROCSROW, PROCSCOL, "Proc:r d s w");
1.1 deraadt 356: mvprintw(GRAPHROW + 1, GRAPHCOL,
1.31 deraadt 357: "| | | | | | | | | | |");
1.1 deraadt 358:
1.25 weingart 359: mvprintw(NAMEIROW, NAMEICOL,
1.31 deraadt 360: "Namei Sys-cache Proc-cache No-cache");
1.1 deraadt 361: mvprintw(NAMEIROW + 1, NAMEICOL,
1.31 deraadt 362: " Calls hits %% hits %% miss %%");
1.45 tedu 363: mvprintw(DISKROW, DISKCOL, "Disks");
1.1 deraadt 364: mvprintw(DISKROW + 1, DISKCOL, "seeks");
365: mvprintw(DISKROW + 2, DISKCOL, "xfers");
1.2 deraadt 366: mvprintw(DISKROW + 3, DISKCOL, "Kbyte");
367: mvprintw(DISKROW + 4, DISKCOL, " sec");
1.37 tdeval 368: for (i = 0, j = 0; i < cur.dk_ndrive && j < DRIVESPACE; i++)
369: if (cur.dk_select[i] && (j + strlen(dr_name[i])) < DRIVESPACE) {
1.47 henning 370: l = MAX(5, strlen(dr_name[i]));
1.32 tdeval 371: mvprintw(DISKROW, DISKCOL + 5 + j,
372: " %*s", l, dr_name[i]);
373: j += 1 + l;
1.1 deraadt 374: }
375: for (i = 0; i < nintr; i++) {
376: if (intrloc[i] == 0)
377: continue;
378: mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", intrname[i]);
379: }
380: }
381:
1.35 deraadt 382: #define X(fld) {t=s.fld[i]; s.fld[i]-=s1.fld[i]; if (state==TIME) s1.fld[i]=t;}
383: #define Y(fld) {t = s.fld; s.fld -= s1.fld; if (state == TIME) s1.fld = t;}
1.1 deraadt 384: #define Z(fld) {t = s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld; \
1.35 deraadt 385: if (state == TIME) s1.nchstats.fld = t;}
1.1 deraadt 386: #define PUTRATE(fld, l, c, w) \
387: Y(fld); \
388: putint((int)((float)s.fld/etime + 0.5), l, c, w)
389: #define MAXFAIL 5
390:
391: static char cpuchar[CPUSTATES] = { '=' , '>', '-', ' ' };
392: static char cpuorder[CPUSTATES] = { CP_SYS, CP_USER, CP_NICE, CP_IDLE };
393:
394: void
1.35 deraadt 395: showkre(void)
1.1 deraadt 396: {
397: float f1, f2;
398: int psiz, inttotal;
399: int i, l, c;
1.46 tedu 400: static int failcnt = 0, first_run = 0;
1.1 deraadt 401:
1.46 tedu 402: if (state == TIME) {
1.2 deraadt 403: dkswap();
1.46 tedu 404: if (!first_run) {
405: first_run = 1;
406: return;
407: }
408: }
1.1 deraadt 409: etime = 0;
1.35 deraadt 410: for (i = 0; i < CPUSTATES; i++) {
1.1 deraadt 411: X(time);
412: etime += s.time[i];
413: }
414: if (etime < 5.0) { /* < 5 ticks - ignore this trash */
415: if (failcnt++ >= MAXFAIL) {
416: clear();
417: mvprintw(2, 10, "The alternate system clock has died!");
418: mvprintw(3, 10, "Reverting to ``pigs'' display.");
419: move(CMDLINE, 0);
420: refresh();
421: failcnt = 0;
422: sleep(5);
423: command("pigs");
424: }
425: return;
426: }
427: failcnt = 0;
428: etime /= hertz;
429: inttotal = 0;
430: for (i = 0; i < nintr; i++) {
431: if (s.intrcnt[i] == 0)
432: continue;
433: if (intrloc[i] == 0) {
434: if (nextintsrow == LINES)
435: continue;
436: intrloc[i] = nextintsrow++;
437: mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s",
1.31 deraadt 438: intrname[i]);
1.1 deraadt 439: }
440: X(intrcnt);
441: l = (int)((float)s.intrcnt[i]/etime + 0.5);
442: inttotal += l;
443: putint(l, intrloc[i], INTSCOL, 8);
444: }
445: putint(inttotal, INTSROW + 1, INTSCOL, 8);
446: Z(ncs_goodhits); Z(ncs_badhits); Z(ncs_miss);
447: Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes);
448: s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits +
449: nchtotal.ncs_miss + nchtotal.ncs_long;
450: if (state == TIME)
451: s1.nchcount = s.nchcount;
452:
453: psiz = 0;
454: f2 = 0.0;
455:
1.31 deraadt 456: /*
1.1 deraadt 457: * Last CPU state not calculated yet.
458: */
459: for (c = 0; c < CPUSTATES - 1; c++) {
460: i = cpuorder[c];
461: f1 = cputime(i);
462: f2 += f1;
463: l = (int) ((f2 + 1.0) / 2.0) - psiz;
464: if (c == 0)
465: putfloat(f1, GRAPHROW, GRAPHCOL + 1, 5, 1, 0);
466: else
467: putfloat(f1, GRAPHROW, GRAPHCOL + 12 * c,
1.31 deraadt 468: 5, 1, 0);
1.1 deraadt 469: move(GRAPHROW + 2, psiz);
470: psiz += l;
471: while (l-- > 0)
472: addch(cpuchar[c]);
473: }
1.15 marc 474:
475: /*
476: * The above code does not account for time in the CP_INTR state.
477: * Thus the total may be less than 100%. If the total is less than
478: * the previous total old data may be left on the graph. The graph
479: * assumes one character position for every 2 percentage points for
480: * a total of 50 positions. Ensure all positions have been filled.
481: */
482: while ( psiz++ <= 50 )
483: addch(' ');
1.1 deraadt 484:
485: putint(ucount(), STATROW, STATCOL, 3);
486: putfloat(avenrun[0], STATROW, STATCOL + 17, 6, 2, 0);
487: putfloat(avenrun[1], STATROW, STATCOL + 23, 6, 2, 0);
488: putfloat(avenrun[2], STATROW, STATCOL + 29, 6, 2, 0);
489: mvaddstr(STATROW, STATCOL + 53, buf);
1.34 millert 490: #define pgtokb(pg) ((pg) * (s.uvmexp.pagesize / 1024))
1.19 art 491:
492: putint(pgtokb(s.uvmexp.active), MEMROW + 2, MEMCOL + 6, 7);
493: putint(pgtokb(s.uvmexp.active + s.uvmexp.swpginuse), /* XXX */
494: MEMROW + 2, MEMCOL + 16, 7);
495: putint(pgtokb(s.uvmexp.npages - s.uvmexp.free), MEMROW + 3, MEMCOL + 6, 7);
496: putint(pgtokb(s.uvmexp.npages - s.uvmexp.free + s.uvmexp.swpginuse),
497: MEMROW + 3, MEMCOL + 16, 7);
498: putint(pgtokb(s.uvmexp.free), MEMROW + 2, MEMCOL + 24, 7);
499: putint(pgtokb(s.uvmexp.free + s.uvmexp.swpages - s.uvmexp.swpginuse),
500: MEMROW + 3, MEMCOL + 24, 7);
1.1 deraadt 501: putint(total.t_rq - 1, PROCSROW + 1, PROCSCOL + 3, 3);
1.19 art 502:
503: putint(total.t_dw, PROCSROW + 1, PROCSCOL + 6, 3);
504: putint(total.t_sl, PROCSROW + 1, PROCSCOL + 9, 3);
505: putint(total.t_sw, PROCSROW + 1, PROCSCOL + 12, 3);
506: PUTRATE(uvmexp.forks, VMSTATROW + 0, VMSTATCOL + 3, 6);
507: PUTRATE(uvmexp.forks_ppwait, VMSTATROW + 1, VMSTATCOL + 3, 6);
508: PUTRATE(uvmexp.forks_sharevm, VMSTATROW + 2, VMSTATCOL + 3, 6);
509: PUTRATE(uvmexp.fltpgwait, VMSTATROW + 3, VMSTATCOL + 4, 5);
510: PUTRATE(uvmexp.fltrelck, VMSTATROW + 4, VMSTATCOL + 3, 6);
511: PUTRATE(uvmexp.fltrelckok, VMSTATROW + 5, VMSTATCOL + 3, 6);
512: PUTRATE(uvmexp.fltnoram, VMSTATROW + 6, VMSTATCOL + 3, 6);
513: PUTRATE(uvmexp.fltamcopy, VMSTATROW + 7, VMSTATCOL + 3, 6);
514: PUTRATE(uvmexp.flt_prcopy, VMSTATROW + 8, VMSTATCOL + 3, 6);
515: PUTRATE(uvmexp.flt_przero, VMSTATROW + 9, VMSTATCOL + 3, 6);
516: PUTRATE(uvmexp.flt_acow, VMSTATROW + 10, VMSTATCOL, 9);
517: putint(s.uvmexp.freemin, VMSTATROW + 11, VMSTATCOL, 9);
518: putint(s.uvmexp.freetarg, VMSTATROW + 12, VMSTATCOL, 9);
519: putint(s.uvmexp.inactarg, VMSTATROW + 13, VMSTATCOL, 9);
520: putint(s.uvmexp.wired, VMSTATROW + 14, VMSTATCOL, 9);
521: PUTRATE(uvmexp.pdfreed, VMSTATROW + 15, VMSTATCOL, 9);
522: if (LINES - 1 > VMSTATROW + 16)
523: PUTRATE(uvmexp.pdscans, VMSTATROW + 16, VMSTATCOL, 9);
1.42 mickey 524: if (LINES - 1 > VMSTATROW + 17)
1.43 mickey 525: PUTRATE(uvmexp.zeropages, VMSTATROW + 17, VMSTATCOL, 9);
1.19 art 526:
527: PUTRATE(uvmexp.pageins, PAGEROW + 2, PAGECOL + 5, 5);
528: PUTRATE(uvmexp.pdpageouts, PAGEROW + 2, PAGECOL + 10, 5);
529: PUTRATE(uvmexp.swapins, PAGEROW + 2, PAGECOL + 15, 5);
530: PUTRATE(uvmexp.swapouts, PAGEROW + 2, PAGECOL + 20, 5);
531: PUTRATE(uvmexp.pgswapin, PAGEROW + 3, PAGECOL + 5, 5);
532: PUTRATE(uvmexp.pgswapout, PAGEROW + 3, PAGECOL + 10, 5);
533:
1.27 deraadt 534: PUTRATE(uvmexp.swtch, GENSTATROW + 1, GENSTATCOL, 6);
535: PUTRATE(uvmexp.traps, GENSTATROW + 1, GENSTATCOL + 6, 6);
536: PUTRATE(uvmexp.syscalls, GENSTATROW + 1, GENSTATCOL + 12, 6);
537: PUTRATE(uvmexp.intrs, GENSTATROW + 1, GENSTATCOL + 18, 6);
538: PUTRATE(uvmexp.softs, GENSTATROW + 1, GENSTATCOL + 24, 6);
539: PUTRATE(uvmexp.faults, GENSTATROW + 1, GENSTATCOL + 30, 5);
1.1 deraadt 540: mvprintw(DISKROW, DISKCOL + 5, " ");
1.37 tdeval 541: for (i = 0, c = 0; i < cur.dk_ndrive && c < DRIVESPACE; i++)
542: if (cur.dk_select[i] && (c + strlen(dr_name[i])) < DRIVESPACE) {
1.47 henning 543: l = MAX(5, strlen(dr_name[i]));
1.32 tdeval 544: mvprintw(DISKROW, DISKCOL + 5 + c,
545: " %*s", l, dr_name[i]);
546: c += 1 + l;
547: dinfo(i, c);
1.1 deraadt 548: }
1.35 deraadt 549: /* and pad the DRIVESPACE */
1.32 tdeval 550: l = DRIVESPACE - c;
551: for (i = 0; i < 5; i++)
552: mvprintw(DISKROW + i, DISKCOL + 5 + c, "%*s", l, "");
553:
1.1 deraadt 554: putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 9);
1.25 weingart 555: putint(nchtotal.ncs_goodhits, NAMEIROW + 2, NAMEICOL + 10, 8);
1.1 deraadt 556: #define nz(x) ((x) ? (x) : 1)
557: putfloat(nchtotal.ncs_goodhits * 100.0 / nz(s.nchcount),
1.31 deraadt 558: NAMEIROW + 2, NAMEICOL + 19, 4, 0, 1);
1.25 weingart 559: putint(nchtotal.ncs_pass2, NAMEIROW + 2, NAMEICOL + 24, 7);
1.1 deraadt 560: putfloat(nchtotal.ncs_pass2 * 100.0 / nz(s.nchcount),
1.31 deraadt 561: NAMEIROW + 2, NAMEICOL + 33, 4, 0, 1);
1.25 weingart 562: putint(nchtotal.ncs_miss - nchtotal.ncs_pass2,
563: NAMEIROW + 2, NAMEICOL + 38, 7);
564: putfloat((nchtotal.ncs_miss - nchtotal.ncs_pass2) *
1.31 deraadt 565: 100.0 / nz(s.nchcount), NAMEIROW + 2, NAMEICOL + 45, 4, 0, 1);
1.1 deraadt 566: #undef nz
567: }
568:
569: int
1.35 deraadt 570: cmdkre(char *cmd, char *args)
1.1 deraadt 571: {
572:
573: if (prefix(cmd, "run")) {
574: copyinfo(&s2, &s1);
575: state = RUN;
576: return (1);
577: }
578: if (prefix(cmd, "boot")) {
579: state = BOOT;
580: copyinfo(&z, &s1);
581: return (1);
582: }
583: if (prefix(cmd, "time")) {
584: state = TIME;
585: return (1);
586: }
587: if (prefix(cmd, "zero")) {
588: if (state == RUN)
589: getinfo(&s1, RUN);
590: return (1);
591: }
592: return (dkcmd(cmd, args));
593: }
594:
595: /* calculate number of users on the system */
596: static int
1.35 deraadt 597: ucount(void)
1.1 deraadt 598: {
1.28 mpech 599: int nusers = 0;
1.1 deraadt 600:
601: if (ut < 0)
602: return (0);
603: while (read(ut, &utmp, sizeof(utmp)))
604: if (utmp.ut_name[0] != '\0')
605: nusers++;
606:
1.16 millert 607: lseek(ut, 0, SEEK_SET);
1.1 deraadt 608: return (nusers);
609: }
610:
611: static float
1.35 deraadt 612: cputime(int indx)
1.1 deraadt 613: {
614: double t;
1.28 mpech 615: int i;
1.1 deraadt 616:
617: t = 0;
618: for (i = 0; i < CPUSTATES; i++)
619: t += s.time[i];
620: if (t == 0.0)
621: t = 1.0;
622: return (s.time[indx] * 100.0 / t);
623: }
624:
625: static void
1.35 deraadt 626: putint(int n, int l, int c, int w)
1.1 deraadt 627: {
628: char b[128];
629:
630: move(l, c);
631: if (n == 0) {
632: while (w-- > 0)
633: addch(' ');
634: return;
635: }
1.12 deraadt 636: snprintf(b, sizeof b, "%*d", w, n);
1.1 deraadt 637: if (strlen(b) > w) {
638: while (w-- > 0)
639: addch('*');
640: return;
641: }
642: addstr(b);
643: }
644:
645: static void
1.35 deraadt 646: putfloat(double f, int l, int c, int w, int d, int nz)
1.1 deraadt 647: {
648: char b[128];
649:
650: move(l, c);
651: if (nz && f == 0.0) {
652: while (--w >= 0)
653: addch(' ');
654: return;
655: }
1.12 deraadt 656: snprintf(b, sizeof b, "%*.*f", w, d, f);
1.1 deraadt 657: if (strlen(b) > w) {
658: while (--w >= 0)
659: addch('*');
660: return;
661: }
662: addstr(b);
663: }
664:
665: static void
1.35 deraadt 666: getinfo(struct Info *s, enum state st)
1.1 deraadt 667: {
1.31 deraadt 668: static int cp_time_mib[] = { CTL_KERN, KERN_CPTIME };
669: static int nchstats_mib[2] = { CTL_KERN, KERN_NCHSTATS };
670: static int uvmexp_mib[2] = { CTL_VM, VM_UVMEXP };
671: static int vmtotal_mib[2] = { CTL_VM, VM_METER };
1.1 deraadt 672: size_t size;
1.18 espie 673: #if defined(__i386__)
1.3 tholo 674: struct intrhand *intrhand[16], *ihp, ih;
1.48 deraadt 675: struct intrhand *apicintrhand[256];
1.3 tholo 676: int i, n;
677: #endif
1.1 deraadt 678:
1.2 deraadt 679: dkreadstats();
1.18 espie 680: #if defined(__i386__)
1.3 tholo 681: NREAD(X_INTRHAND, intrhand, sizeof(intrhand));
682: for (i = 0, n = 0; i < 16; i++) {
683: ihp = intrhand[i];
684: while (ihp) {
685: KREAD(ihp, &ih, sizeof(ih));
686: s->intrcnt[n++] = ih.ih_count;
687: ihp = ih.ih_next;
1.48 deraadt 688: }
689: }
690: if (namelist[X_APICINTRHAND].n_value) {
691: NREAD(X_APICINTRHAND, apicintrhand, sizeof(apicintrhand));
692: for (i = 0, n = 0; i < 256; i++) {
693: ihp = apicintrhand[i];
694: while (ihp) {
695: KREAD(ihp, &ih, sizeof(ih));
696: s->intrcnt[n++] = ih.ih_count;
697: ihp = ih.ih_next;
698: }
1.3 tholo 699: }
700: }
701: #else
1.38 jason 702: NREAD(X_INTRCNT, s->intrcnt, nintr * sizeof(int));
1.3 tholo 703: #endif
1.31 deraadt 704: size = sizeof(s->time);
705: if (sysctl(cp_time_mib, 2, &s->time, &size, NULL, 0) < 0) {
706: error("Can't get KERN_CPTIME: %s\n", strerror(errno));
707: bzero(&s->time, sizeof(s->time));
708: }
709:
710: size = sizeof(s->nchstats);
711: if (sysctl(nchstats_mib, 2, &s->nchstats, &size, NULL, 0) < 0) {
712: error("Can't get KERN_NCHSTATS: %s\n", strerror(errno));
713: bzero(&s->nchstats, sizeof(s->nchstats));
714: }
715:
716: size = sizeof(s->uvmexp);
717: if (sysctl(uvmexp_mib, 2, &s->uvmexp, &size, NULL, 0) < 0) {
718: error("Can't get VM_UVMEXP: %s\n", strerror(errno));
719: bzero(&s->uvmexp, sizeof(s->uvmexp));
720: }
721:
1.1 deraadt 722: size = sizeof(s->Total);
1.31 deraadt 723: if (sysctl(vmtotal_mib, 2, &s->Total, &size, NULL, 0) < 0) {
724: error("Can't get VM_METER: %s\n", strerror(errno));
1.1 deraadt 725: bzero(&s->Total, sizeof(s->Total));
726: }
727: }
728:
729: static void
1.35 deraadt 730: allocinfo(struct Info *s)
1.1 deraadt 731: {
732:
1.38 jason 733: s->intrcnt = (int *) malloc(nintr * sizeof(int));
1.1 deraadt 734: if (s->intrcnt == NULL)
735: errx(2, "out of memory");
736: }
737:
738: static void
1.35 deraadt 739: copyinfo(struct Info *from, struct Info *to)
1.1 deraadt 740: {
1.38 jason 741: int *intrcnt;
1.1 deraadt 742:
1.2 deraadt 743: intrcnt = to->intrcnt;
1.1 deraadt 744: *to = *from;
745: bcopy(from->intrcnt, to->intrcnt = intrcnt, nintr * sizeof (int));
746: }
747:
748: static void
1.35 deraadt 749: dinfo(int dn, int c)
1.1 deraadt 750: {
1.2 deraadt 751: double words, atime;
1.1 deraadt 752:
1.32 tdeval 753: c += DISKCOL;
1.2 deraadt 754:
755: /* time busy in disk activity */
756: atime = (double)cur.dk_time[dn].tv_sec +
1.31 deraadt 757: ((double)cur.dk_time[dn].tv_usec / (double)1000000);
1.2 deraadt 758:
1.44 tedu 759: /* # of K transferred */
760: words = (cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) / 1024.0;
1.2 deraadt 761:
762: putint((int)((float)cur.dk_seek[dn]/etime+0.5), DISKROW + 1, c, 5);
1.44 tedu 763: putint((int)((float)(cur.dk_rxfer[dn] + cur.dk_wxfer[dn])/etime+0.5),
764: DISKROW + 2, c, 5);
1.2 deraadt 765: putint((int)(words/etime + 0.5), DISKROW + 3, c, 5);
766: putfloat(atime/etime, DISKROW + 4, c, 5, 1, 1);
1.1 deraadt 767: }