Annotation of src/usr.bin/systat/vmstat.c, Revision 1.77.12.1
1.77.12.1! tls 1: /* $NetBSD$ */
1.2 jtc 2:
1.1 jtc 3: /*-
4: * Copyright (c) 1983, 1989, 1992, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.53 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 jtc 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
1.8 mrg 32: #include <sys/cdefs.h>
1.1 jtc 33: #ifndef lint
1.2 jtc 34: #if 0
1.1 jtc 35: static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94";
1.2 jtc 36: #endif
1.77.12.1! tls 37: __RCSID("$NetBSD$");
1.1 jtc 38: #endif /* not lint */
39:
40: /*
41: * Cursed vmstat -- from Robert Elz.
42: */
43:
44: #include <sys/param.h>
1.67 christos 45: #include <sys/uio.h>
1.1 jtc 46: #include <sys/namei.h>
47: #include <sys/sysctl.h>
1.70 dyoung 48: #include <sys/evcnt.h>
1.1 jtc 49:
1.11 mrg 50: #include <uvm/uvm_extern.h>
51:
1.66 yamt 52: #include <errno.h>
1.3 mycroft 53: #include <stdlib.h>
1.1 jtc 54: #include <string.h>
1.41 abs 55: #include <util.h>
1.3 mycroft 56:
1.1 jtc 57: #include "systat.h"
58: #include "extern.h"
1.65 blymn 59: #include "drvstats.h"
1.40 christos 60: #include "utmpentry.h"
1.63 dsl 61: #include "vmstat.h"
1.1 jtc 62:
63: static struct Info {
1.34 simonb 64: struct uvmexp_sysctl uvmexp;
1.1 jtc 65: struct vmtotal Total;
1.77.12.1! tls 66: struct nchstats_sysctl nchstats;
1.1 jtc 67: long nchcount;
68: long *intrcnt;
1.44 dsl 69: u_int64_t *evcnt;
1.1 jtc 70: } s, s1, s2, z;
71:
1.63 dsl 72: enum display_mode display_mode = TIME;
1.1 jtc 73:
1.33 ad 74: static void allocinfo(struct Info *);
75: static void copyinfo(struct Info *, struct Info *);
76: static float cputime(int);
1.49 dsl 77: static void dinfo(int, int, int);
1.63 dsl 78: static void getinfo(struct Info *);
1.33 ad 79: static int ucount(void);
1.1 jtc 80:
81: static char buf[26];
1.59 dsl 82: static u_int64_t temp;
1.63 dsl 83: double etime;
1.1 jtc 84: static float hertz;
85: static int nintr;
86: static long *intrloc;
87: static char **intrname;
88: static int nextintsrow;
1.49 dsl 89: static int disk_horiz = 1;
1.1 jtc 90:
91: WINDOW *
1.33 ad 92: openvmstat(void)
1.1 jtc 93: {
94: return (stdscr);
95: }
96:
97: void
1.33 ad 98: closevmstat(WINDOW *w)
1.1 jtc 99: {
100:
101: if (w == NULL)
102: return;
103: wclear(w);
104: wrefresh(w);
105: }
106:
107:
108: static struct nlist namelist[] = {
1.77.12.1! tls 109: #define X_INTRNAMES 0
1.69 christos 110: { .n_name = "_intrnames" },
1.77.12.1! tls 111: #define X_EINTRNAMES 1
1.69 christos 112: { .n_name = "_eintrnames" },
1.77.12.1! tls 113: #define X_INTRCNT 2
1.69 christos 114: { .n_name = "_intrcnt" },
1.77.12.1! tls 115: #define X_EINTRCNT 3
1.69 christos 116: { .n_name = "_eintrcnt" },
1.77.12.1! tls 117: #define X_ALLEVENTS 4
1.69 christos 118: { .n_name = "_allevents" },
119: { .n_name = NULL }
1.1 jtc 120: };
121:
122: /*
123: * These constants define where the major pieces are laid out
124: */
125: #define STATROW 0 /* uses 1 row and 68 cols */
126: #define STATCOL 2
1.48 dsl 127: #define MEMROW 9 /* uses 4 rows and 31 cols */
1.1 jtc 128: #define MEMCOL 0
129: #define PAGEROW 2 /* uses 4 rows and 26 cols */
1.48 dsl 130: #define PAGECOL 54
131: #define INTSROW 9 /* uses all rows to bottom and 17 cols */
132: #define INTSCOL 40
133: #define INTSCOLEND (VMSTATCOL - 0)
134: #define PROCSROW 2 /* uses 2 rows and 20 cols */
1.1 jtc 135: #define PROCSCOL 0
1.48 dsl 136: #define GENSTATROW 2 /* uses 2 rows and 30 cols */
1.58 christos 137: #define GENSTATCOL 17
1.48 dsl 138: #define VMSTATROW 7 /* uses 17 rows and 15 cols */
139: #define VMSTATCOL 64
140: #define GRAPHROW 5 /* uses 3 rows and 51 cols */
1.1 jtc 141: #define GRAPHCOL 0
142: #define NAMEIROW 14 /* uses 3 rows and 38 cols */
143: #define NAMEICOL 0
144: #define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */
145: #define DISKCOL 0
1.49 dsl 146: #define DISKCOLWIDTH 6
147: #define DISKCOLEND INTSCOL
1.1 jtc 148:
1.44 dsl 149: typedef struct intr_evcnt intr_evcnt_t;
150: struct intr_evcnt {
151: char *ie_group;
152: char *ie_name;
153: u_int64_t *ie_count; /* kernel address... */
154: int ie_loc; /* screen row */
155: } *ie_head;
156: int nevcnt;
157:
158: static void
159: get_interrupt_events(void)
160: {
161: struct evcntlist allevents;
162: struct evcnt evcnt, *evptr;
163: intr_evcnt_t *ie;
1.55 itojun 164: intr_evcnt_t *n;
1.44 dsl 165:
166: if (!NREAD(X_ALLEVENTS, &allevents, sizeof allevents))
167: return;
1.60 chs 168: evptr = TAILQ_FIRST(&allevents);
169: for (; evptr != NULL; evptr = TAILQ_NEXT(&evcnt, ev_list)) {
1.44 dsl 170: if (!KREAD(evptr, &evcnt, sizeof evcnt))
171: return;
172: if (evcnt.ev_type != EVCNT_TYPE_INTR)
173: continue;
1.55 itojun 174: n = realloc(ie_head, sizeof *ie * (nevcnt + 1));
175: if (n == NULL) {
1.44 dsl 176: error("realloc failed");
177: die(0);
178: }
1.55 itojun 179: ie_head = n;
1.44 dsl 180: ie = ie_head + nevcnt;
181: ie->ie_group = malloc(evcnt.ev_grouplen + 1);
182: ie->ie_name = malloc(evcnt.ev_namelen + 1);
183: if (ie->ie_group == NULL || ie->ie_name == NULL)
184: return;
1.46 dsl 185: if (!KREAD(evcnt.ev_group, ie->ie_group, evcnt.ev_grouplen + 1))
1.44 dsl 186: return;
1.46 dsl 187: if (!KREAD(evcnt.ev_name, ie->ie_name, evcnt.ev_namelen + 1))
1.44 dsl 188: return;
189: ie->ie_count = &evptr->ev_count;
190: ie->ie_loc = 0;
191: nevcnt++;
192: }
193: }
194:
1.1 jtc 195: int
1.33 ad 196: initvmstat(void)
1.1 jtc 197: {
1.64 dsl 198: static char *intrnamebuf;
199: char *cp;
1.1 jtc 200: int i;
201:
1.64 dsl 202: if (intrnamebuf)
203: free(intrnamebuf);
204: if (intrname)
205: free(intrname);
206: if (intrloc)
207: free(intrloc);
208:
1.1 jtc 209: if (namelist[0].n_type == 0) {
1.60 chs 210: if (kvm_nlist(kd, namelist) &&
1.77.12.1! tls 211: namelist[X_ALLEVENTS].n_type == 0) {
1.1 jtc 212: nlisterr(namelist);
213: return(0);
214: }
215: }
216: hertz = stathz ? stathz : hz;
1.65 blymn 217: if (!drvinit(1))
1.61 blymn 218: return(0);
1.44 dsl 219:
220: /* Old style interrupt counts - deprecated */
221: nintr = (namelist[X_EINTRCNT].n_value -
222: namelist[X_INTRCNT].n_value) / sizeof (long);
1.60 chs 223: if (nintr) {
224: intrloc = calloc(nintr, sizeof (long));
225: intrname = calloc(nintr, sizeof (long));
226: intrnamebuf = malloc(namelist[X_EINTRNAMES].n_value -
227: namelist[X_INTRNAMES].n_value);
228: if (intrnamebuf == NULL || intrname == 0 || intrloc == 0) {
229: error("Out of memory\n");
230: nintr = 0;
231: return(0);
232: }
233: NREAD(X_INTRNAMES, intrnamebuf, NVAL(X_EINTRNAMES) -
234: NVAL(X_INTRNAMES));
235: for (cp = intrnamebuf, i = 0; i < nintr; i++) {
236: intrname[i] = cp;
237: cp += strlen(cp) + 1;
238: }
1.44 dsl 239: }
240:
241: /* event counter interrupt counts */
242: get_interrupt_events();
243:
1.48 dsl 244: nextintsrow = INTSROW + 1;
1.44 dsl 245: allocinfo(&s);
246: allocinfo(&s1);
247: allocinfo(&s2);
248: allocinfo(&z);
249:
1.63 dsl 250: getinfo(&s2);
1.1 jtc 251: copyinfo(&s2, &s1);
252: return(1);
253: }
254:
255: void
1.33 ad 256: fetchvmstat(void)
1.1 jtc 257: {
258: time_t now;
259:
260: time(&now);
1.50 itojun 261: strlcpy(buf, ctime(&now), sizeof(buf));
1.18 marc 262: buf[19] = '\0';
1.63 dsl 263: getinfo(&s);
1.1 jtc 264: }
265:
1.44 dsl 266: static void
267: print_ie_title(int i)
268: {
269: int width, name_width, group_width;
270:
1.48 dsl 271: width = INTSCOLEND - (INTSCOL + 9);
1.44 dsl 272: if (width <= 0)
273: return;
274:
275: move(ie_head[i].ie_loc, INTSCOL + 9);
276: group_width = strlen(ie_head[i].ie_group);
277: name_width = strlen(ie_head[i].ie_name);
278: width -= group_width + 1 + name_width;
279: if (width < 0) {
1.47 dsl 280: /*
281: * Screen to narrow for full strings
282: * This is all rather horrid, in some cases there are a lot
283: * of events in the same group, and in others the event
284: * name is "intr". There are also names which need 7 or 8
285: * columns before they become meaningful.
286: * This is a bad compromise.
287: */
1.44 dsl 288: width = -width;
289: group_width -= (width + 1) / 2;
290: name_width -= width / 2;
1.47 dsl 291: /* some have the 'useful' name "intr", display their group */
292: if (strcasecmp(ie_head[i].ie_name, "intr") == 0) {
293: group_width += name_width + 1;
294: name_width = 0;
295: } else {
296: if (group_width <= 3 || name_width < 0) {
297: /* don't display group */
298: name_width += group_width + 1;
299: group_width = 0;
300: }
1.44 dsl 301: }
302: }
303:
1.47 dsl 304: if (group_width != 0) {
305: printw("%-.*s", group_width, ie_head[i].ie_group);
306: if (name_width != 0)
307: printw(" ");
308: }
309: if (name_width != 0)
310: printw("%-.*s", name_width, ie_head[i].ie_name);
1.44 dsl 311: }
312:
1.1 jtc 313: void
1.63 dsl 314: labelvmstat_top(void)
1.1 jtc 315: {
316:
317: clear();
1.63 dsl 318:
1.1 jtc 319: mvprintw(STATROW, STATCOL + 4, "users Load");
1.13 mrg 320:
1.72 njoly 321: mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt");
1.63 dsl 322:
323: mvprintw(GRAPHROW, GRAPHCOL,
324: " . %% Sy . %% Us . %% Ni . %% In . %% Id");
1.75 rmind 325: mvprintw(PROCSROW, PROCSCOL, "Proc:r d s");
1.63 dsl 326: mvprintw(GRAPHROW + 1, GRAPHCOL,
327: "| | | | | | | | | | |");
328:
329: mvprintw(PAGEROW, PAGECOL + 8, "PAGING SWAPPING ");
1.13 mrg 330: mvprintw(PAGEROW + 1, PAGECOL, " in out in out ");
1.63 dsl 331: mvprintw(PAGEROW + 2, PAGECOL + 2, "ops");
1.13 mrg 332: mvprintw(PAGEROW + 3, PAGECOL, "pages");
1.63 dsl 333: }
334:
335: void
336: labelvmstat(void)
337: {
338: int i;
1.1 jtc 339:
1.63 dsl 340: /* Top few lines first */
1.1 jtc 341:
1.63 dsl 342: labelvmstat_top();
1.1 jtc 343:
1.63 dsl 344: /* Left hand column */
1.1 jtc 345:
1.76 njoly 346: mvprintw(MEMROW, MEMCOL, " memory totals (in kB)");
347: mvprintw(MEMROW + 1, MEMCOL, " real virtual free");
1.63 dsl 348: mvprintw(MEMROW + 2, MEMCOL, "Active");
349: mvprintw(MEMROW + 3, MEMCOL, "All");
1.1 jtc 350:
351: mvprintw(NAMEIROW, NAMEICOL, "Namei Sys-cache Proc-cache");
352: mvprintw(NAMEIROW + 1, NAMEICOL,
353: " Calls hits %% hits %%");
1.63 dsl 354:
1.52 grant 355: mvprintw(DISKROW, DISKCOL, "Disks:");
1.49 dsl 356: if (disk_horiz) {
357: mvprintw(DISKROW + 1, DISKCOL + 1, "seeks");
358: mvprintw(DISKROW + 2, DISKCOL + 1, "xfers");
359: mvprintw(DISKROW + 3, DISKCOL + 1, "bytes");
360: mvprintw(DISKROW + 4, DISKCOL + 1, "%%busy");
361: } else {
362: mvprintw(DISKROW, DISKCOL + 1 + 1 * DISKCOLWIDTH, "seeks");
363: mvprintw(DISKROW, DISKCOL + 1 + 2 * DISKCOLWIDTH, "xfers");
364: mvprintw(DISKROW, DISKCOL + 1 + 3 * DISKCOLWIDTH, "bytes");
365: mvprintw(DISKROW, DISKCOL + 1 + 4 * DISKCOLWIDTH, "%%busy");
366: }
1.63 dsl 367:
368: /* Middle column */
369:
370: mvprintw(INTSROW, INTSCOL + 9, "Interrupts");
1.1 jtc 371: for (i = 0; i < nintr; i++) {
372: if (intrloc[i] == 0)
373: continue;
1.47 dsl 374: mvprintw(intrloc[i], INTSCOL + 9, "%-.*s",
1.48 dsl 375: INTSCOLEND - (INTSCOL + 9), intrname[i]);
1.1 jtc 376: }
1.44 dsl 377: for (i = 0; i < nevcnt; i++) {
378: if (ie_head[i].ie_loc == 0)
379: continue;
380: print_ie_title(i);
381: }
1.63 dsl 382:
383: /* Right hand column */
384:
385: mvprintw(VMSTATROW + 0, VMSTATCOL + 10, "forks");
386: mvprintw(VMSTATROW + 1, VMSTATCOL + 10, "fkppw");
387: mvprintw(VMSTATROW + 2, VMSTATCOL + 10, "fksvm");
388: mvprintw(VMSTATROW + 3, VMSTATCOL + 10, "pwait");
389: mvprintw(VMSTATROW + 4, VMSTATCOL + 10, "relck");
390: mvprintw(VMSTATROW + 5, VMSTATCOL + 10, "rlkok");
391: mvprintw(VMSTATROW + 6, VMSTATCOL + 10, "noram");
392: mvprintw(VMSTATROW + 7, VMSTATCOL + 10, "ndcpy");
393: mvprintw(VMSTATROW + 8, VMSTATCOL + 10, "fltcp");
394: mvprintw(VMSTATROW + 9, VMSTATCOL + 10, "zfod");
395: mvprintw(VMSTATROW + 10, VMSTATCOL + 10, "cow");
396: mvprintw(VMSTATROW + 11, VMSTATCOL + 10, "fmin");
397: mvprintw(VMSTATROW + 12, VMSTATCOL + 10, "ftarg");
398: mvprintw(VMSTATROW + 13, VMSTATCOL + 10, "itarg");
399: mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "wired");
400: mvprintw(VMSTATROW + 15, VMSTATCOL + 10, "pdfre");
401:
402: if (LINES - 1 > VMSTATROW + 16)
403: mvprintw(VMSTATROW + 16, VMSTATCOL + 10, "pdscn");
1.1 jtc 404: }
405:
1.63 dsl 406: #define X(s, s1, fld) {temp = (s).fld[i]; (s).fld[i] -= (s1).fld[i]; \
407: if (display_mode == TIME) (s1).fld[i] = temp;}
408: #define Z(s, s1, fld) {temp = (s).nchstats.fld; \
409: (s).nchstats.fld -= (s1).nchstats.fld; \
410: if (display_mode == TIME) (s1).nchstats.fld = temp;}
411: #define PUTRATE(s, s1, fld, l, c, w) \
412: {temp = (s).fld; (s).fld -= (s1).fld; \
413: if (display_mode == TIME) (s1).fld = temp; \
414: putint((int)((float)(s).fld/etime + 0.5), l, c, w);}
1.1 jtc 415: #define MAXFAIL 5
416:
1.25 simonb 417: static char cpuchar[CPUSTATES] = { '=' , '>', '-', '%', ' ' };
418: static char cpuorder[CPUSTATES] = { CP_SYS, CP_USER, CP_NICE, CP_INTR, CP_IDLE };
1.1 jtc 419:
420: void
1.63 dsl 421: show_vmstat_top(vmtotal_t *Total, uvmexp_sysctl_t *uvm, uvmexp_sysctl_t *uvm1)
422: {
423: float f1, f2;
424: int psiz;
425: int i, l, c;
426: struct {
427: struct uvmexp_sysctl *uvmexp;
428: } us, us1;
429:
430: us.uvmexp = uvm;
431: us1.uvmexp = uvm1;
432:
433: putint(ucount(), STATROW, STATCOL, 3);
434: putfloat(avenrun[0], STATROW, STATCOL + 17, 6, 2, 0);
435: putfloat(avenrun[1], STATROW, STATCOL + 23, 6, 2, 0);
436: putfloat(avenrun[2], STATROW, STATCOL + 29, 6, 2, 0);
437: mvaddstr(STATROW, STATCOL + 53, buf);
438:
439: putint(Total->t_rq - 1, PROCSROW + 1, PROCSCOL + 3, 3);
440: putint(Total->t_dw, PROCSROW + 1, PROCSCOL + 6, 3);
441: putint(Total->t_sl, PROCSROW + 1, PROCSCOL + 9, 3);
442:
443: PUTRATE(us, us1, uvmexp->swtch, GENSTATROW + 1, GENSTATCOL - 1, 7);
1.68 dsl 444: PUTRATE(us, us1, uvmexp->traps, GENSTATROW + 1, GENSTATCOL + 7, 6);
445: PUTRATE(us, us1, uvmexp->syscalls, GENSTATROW + 1, GENSTATCOL + 14, 6);
446: PUTRATE(us, us1, uvmexp->intrs, GENSTATROW + 1, GENSTATCOL + 21, 5);
1.72 njoly 447: PUTRATE(us, us1, uvmexp->softs, GENSTATROW + 1, GENSTATCOL + 27, 6);
448: PUTRATE(us, us1, uvmexp->faults, GENSTATROW + 1, GENSTATCOL + 34, 6);
1.63 dsl 449:
450: /* Last CPU state not calculated yet. */
451: for (f2 = 0.0, psiz = 0, c = 0; c < CPUSTATES; c++) {
452: i = cpuorder[c];
453: f1 = cputime(i);
454: f2 += f1;
455: l = (int) ((f2 + 1.0) / 2.0) - psiz;
456: if (c == 0)
457: putfloat(f1, GRAPHROW, GRAPHCOL + 1, 5, 1, 0);
458: else
459: putfloat(f1, GRAPHROW, GRAPHCOL + 10 * c + 1, 5, 1, 0);
460: mvhline(GRAPHROW + 2, psiz, cpuchar[c], l);
461: psiz += l;
462: }
463:
464: PUTRATE(us, us1, uvmexp->pageins, PAGEROW + 2, PAGECOL + 5, 5);
465: PUTRATE(us, us1, uvmexp->pdpageouts, PAGEROW + 2, PAGECOL + 10, 5);
466: PUTRATE(us, us1, uvmexp->pgswapin, PAGEROW + 3, PAGECOL + 5, 5);
467: PUTRATE(us, us1, uvmexp->pgswapout, PAGEROW + 3, PAGECOL + 10, 5);
468: }
469:
470: void
1.33 ad 471: showvmstat(void)
1.1 jtc 472: {
1.63 dsl 473: int inttotal;
1.49 dsl 474: int i, l, r, c;
1.1 jtc 475: static int failcnt = 0;
1.49 dsl 476: static int relabel = 0;
477: static int last_disks = 0;
1.59 dsl 478: static char pigs[] = "pigs";
1.49 dsl 479:
480: if (relabel) {
481: labelvmstat();
482: relabel = 0;
483: }
1.39 sommerfe 484:
1.62 dsl 485: cpuswap();
1.63 dsl 486: if (display_mode == TIME) {
1.65 blymn 487: drvswap();
1.44 dsl 488: etime = cur.cp_etime;
489: /* < 5 ticks - ignore this trash */
490: if ((etime * hertz) < 1.0) {
1.74 wiz 491: if (failcnt++ <= MAXFAIL)
1.44 dsl 492: return;
1.1 jtc 493: clear();
494: mvprintw(2, 10, "The alternate system clock has died!");
495: mvprintw(3, 10, "Reverting to ``pigs'' display.");
496: move(CMDLINE, 0);
497: refresh();
498: failcnt = 0;
499: sleep(5);
1.59 dsl 500: command(pigs);
1.44 dsl 501: return;
1.1 jtc 502: }
1.44 dsl 503: } else
504: etime = 1.0;
505:
1.63 dsl 506: show_vmstat_top(&s.Total, &s.uvmexp, &s1.uvmexp);
1.1 jtc 507:
1.63 dsl 508: /* Memory totals */
1.17 drochner 509: #define pgtokb(pg) ((pg) * (s.uvmexp.pagesize / 1024))
1.76 njoly 510: putint(pgtokb(s.uvmexp.active), MEMROW + 2, MEMCOL + 6, 9);
1.12 mrg 511: putint(pgtokb(s.uvmexp.active + s.uvmexp.swpginuse), /* XXX */
1.76 njoly 512: MEMROW + 2, MEMCOL + 16, 9);
513: putint(pgtokb(s.uvmexp.npages - s.uvmexp.free),
514: MEMROW + 3, MEMCOL + 6, 9);
1.12 mrg 515: putint(pgtokb(s.uvmexp.npages - s.uvmexp.free + s.uvmexp.swpginuse),
1.76 njoly 516: MEMROW + 3, MEMCOL + 16, 9);
517: putint(pgtokb(s.uvmexp.free), MEMROW + 2, MEMCOL + 26, 9);
1.12 mrg 518: putint(pgtokb(s.uvmexp.free + s.uvmexp.swpages - s.uvmexp.swpginuse),
1.76 njoly 519: MEMROW + 3, MEMCOL + 26, 9);
1.63 dsl 520: #undef pgtokb
521:
522: /* Namei cache */
523: Z(s, s1, ncs_goodhits); Z(s, s1, ncs_badhits); Z(s, s1, ncs_miss);
524: Z(s, s1, ncs_long); Z(s, s1, ncs_pass2); Z(s, s1, ncs_2passes);
525: s.nchcount = s.nchstats.ncs_goodhits + s.nchstats.ncs_badhits +
1.77 njoly 526: s.nchstats.ncs_miss + s.nchstats.ncs_long +
527: s.nchstats.ncs_pass2 + s.nchstats.ncs_2passes;
1.63 dsl 528: if (display_mode == TIME)
529: s1.nchcount = s.nchcount;
530:
531: putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 9);
532: putint(s.nchstats.ncs_goodhits, NAMEIROW + 2, NAMEICOL + 9, 9);
533: #define nz(x) ((x) ? (x) : 1)
534: putfloat(s.nchstats.ncs_goodhits * 100.0 / nz(s.nchcount),
535: NAMEIROW + 2, NAMEICOL + 19, 4, 0, 1);
536: putint(s.nchstats.ncs_pass2, NAMEIROW + 2, NAMEICOL + 23, 9);
537: putfloat(s.nchstats.ncs_pass2 * 100.0 / nz(s.nchcount),
538: NAMEIROW + 2, NAMEICOL + 34, 4, 0, 1);
539: #undef nz
1.12 mrg 540:
1.63 dsl 541: /* Disks */
1.61 blymn 542: for (l = 0, i = 0, r = DISKROW, c = DISKCOL;
1.73 lukem 543: i < (int)ndrive; i++) {
1.65 blymn 544: if (!drv_select[i])
545: continue;
1.61 blymn 546:
1.49 dsl 547: if (disk_horiz)
548: c += DISKCOLWIDTH;
549: else
550: r++;
551: if (c + DISKCOLWIDTH > DISKCOLEND) {
552: if (disk_horiz && LINES - 1 - DISKROW >
1.61 blymn 553: (DISKCOLEND - DISKCOL) / DISKCOLWIDTH) {
1.49 dsl 554: disk_horiz = 0;
555: relabel = 1;
556: }
557: break;
1.1 jtc 558: }
1.49 dsl 559: if (r >= LINES - 1) {
560: if (!disk_horiz && LINES - 1 - DISKROW <
1.61 blymn 561: (DISKCOLEND - DISKCOL) / DISKCOLWIDTH) {
1.49 dsl 562: disk_horiz = 1;
563: relabel = 1;
564: }
565: break;
566: }
567: l++;
568:
1.65 blymn 569: dinfo(i, r, c);
1.49 dsl 570: }
571: /* blank out if we lost any disks */
572: for (i = l; i < last_disks; i++) {
573: int j;
574: if (disk_horiz)
575: c += DISKCOLWIDTH;
576: else
577: r++;
578: for (j = 0; j < 5; j++) {
579: if (disk_horiz)
1.56 mycroft 580: mvprintw(r+j, c, "%*s", DISKCOLWIDTH, "");
1.49 dsl 581: else
1.56 mycroft 582: mvprintw(r, c+j*DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "");
1.49 dsl 583: }
584: }
585: last_disks = l;
1.63 dsl 586:
587: /* Interrupts */
588: failcnt = 0;
589: inttotal = 0;
590: for (i = 0; i < nintr; i++) {
591: if (s.intrcnt[i] == 0)
592: continue;
593: if (intrloc[i] == 0) {
594: if (nextintsrow == LINES)
595: continue;
596: intrloc[i] = nextintsrow++;
597: mvprintw(intrloc[i], INTSCOL + 9, "%-.*s",
598: INTSCOLEND - (INTSCOL + 9), intrname[i]);
599: }
600: X(s, s1, intrcnt);
601: l = (int)((float)s.intrcnt[i]/etime + 0.5);
602: inttotal += l;
603: putint(l, intrloc[i], INTSCOL, 8);
604: }
605:
606: for (i = 0; i < nevcnt; i++) {
607: if (s.evcnt[i] == 0)
608: continue;
609: if (ie_head[i].ie_loc == 0) {
610: if (nextintsrow == LINES)
611: continue;
612: ie_head[i].ie_loc = nextintsrow++;
613: print_ie_title(i);
614: }
615: X(s, s1, evcnt);
616: l = (int)((float)s.evcnt[i]/etime + 0.5);
617: inttotal += l;
618: putint(l, ie_head[i].ie_loc, INTSCOL, 8);
619: }
620: putint(inttotal, INTSROW, INTSCOL, 8);
621:
622: PUTRATE(s, s1, uvmexp.forks, VMSTATROW + 0, VMSTATCOL + 3, 6);
623: PUTRATE(s, s1, uvmexp.forks_ppwait, VMSTATROW + 1, VMSTATCOL + 3, 6);
624: PUTRATE(s, s1, uvmexp.forks_sharevm, VMSTATROW + 2, VMSTATCOL + 3, 6);
625: PUTRATE(s, s1, uvmexp.fltpgwait, VMSTATROW + 3, VMSTATCOL + 4, 5);
626: PUTRATE(s, s1, uvmexp.fltrelck, VMSTATROW + 4, VMSTATCOL + 3, 6);
627: PUTRATE(s, s1, uvmexp.fltrelckok, VMSTATROW + 5, VMSTATCOL + 3, 6);
628: PUTRATE(s, s1, uvmexp.fltnoram, VMSTATROW + 6, VMSTATCOL + 3, 6);
629: PUTRATE(s, s1, uvmexp.fltamcopy, VMSTATROW + 7, VMSTATCOL + 3, 6);
630: PUTRATE(s, s1, uvmexp.flt_prcopy, VMSTATROW + 8, VMSTATCOL + 3, 6);
631: PUTRATE(s, s1, uvmexp.flt_przero, VMSTATROW + 9, VMSTATCOL + 3, 6);
632: PUTRATE(s, s1, uvmexp.flt_acow, VMSTATROW + 10, VMSTATCOL, 9);
633: putint(s.uvmexp.freemin, VMSTATROW + 11, VMSTATCOL, 9);
634: putint(s.uvmexp.freetarg, VMSTATROW + 12, VMSTATCOL, 9);
635: putint(s.uvmexp.inactarg, VMSTATROW + 13, VMSTATCOL, 9);
636: putint(s.uvmexp.wired, VMSTATROW + 14, VMSTATCOL, 9);
637: PUTRATE(s, s1, uvmexp.pdfreed, VMSTATROW + 15, VMSTATCOL, 9);
638: if (LINES - 1 > VMSTATROW + 16)
639: PUTRATE(s, s1, uvmexp.pdscans, VMSTATROW + 16, VMSTATCOL, 9);
640:
1.1 jtc 641: }
642:
1.22 jwise 643: void
1.33 ad 644: vmstat_boot(char *args)
1.22 jwise 645: {
646: copyinfo(&z, &s1);
1.63 dsl 647: display_mode = BOOT;
1.22 jwise 648: }
649:
650: void
1.33 ad 651: vmstat_run(char *args)
1.22 jwise 652: {
653: copyinfo(&s1, &s2);
1.63 dsl 654: display_mode = RUN;
1.22 jwise 655: }
656:
657: void
1.44 dsl 658: vmstat_time(char *args)
1.1 jtc 659: {
1.63 dsl 660: display_mode = TIME;
1.22 jwise 661: }
1.1 jtc 662:
1.22 jwise 663: void
1.33 ad 664: vmstat_zero(char *args)
1.22 jwise 665: {
1.63 dsl 666: if (display_mode == RUN)
667: getinfo(&s1);
1.1 jtc 668: }
669:
670: /* calculate number of users on the system */
671: static int
1.33 ad 672: ucount(void)
1.1 jtc 673: {
1.40 christos 674: static int onusers = -1;
675: int nusers = 0;
676: struct utmpentry *ehead;
677:
678: nusers = getutentries(NULL, &ehead);
1.1 jtc 679:
1.21 mrg 680: if (nusers != onusers) {
681: if (nusers == 1)
682: mvprintw(STATROW, STATCOL + 8, " ");
683: else
684: mvprintw(STATROW, STATCOL + 8, "s");
685: }
686: onusers = nusers;
1.1 jtc 687: return (nusers);
688: }
689:
690: static float
1.33 ad 691: cputime(int indx)
1.1 jtc 692: {
693: double t;
1.10 lukem 694: int i;
1.1 jtc 695:
696: t = 0;
697: for (i = 0; i < CPUSTATES; i++)
1.39 sommerfe 698: t += cur.cp_time[i];
1.1 jtc 699: if (t == 0.0)
700: t = 1.0;
1.39 sommerfe 701: return (cur.cp_time[indx] * 100.0 / t);
1.1 jtc 702: }
703:
1.63 dsl 704: void
1.44 dsl 705: puthumanint(u_int64_t n, int l, int c, int w)
1.41 abs 706: {
707: char b[128];
708:
1.48 dsl 709: if (move(l, c) != OK)
710: return;
1.41 abs 711: if (n == 0) {
712: hline(' ', w);
713: return;
714: }
1.44 dsl 715: if (humanize_number(b, w, n, "", HN_AUTOSCALE, HN_NOSPACE) == -1 ) {
1.41 abs 716: hline('*', w);
717: return;
718: }
1.63 dsl 719: printw("%*s", w, b);
1.41 abs 720: }
721:
1.63 dsl 722: void
1.33 ad 723: putint(int n, int l, int c, int w)
1.1 jtc 724: {
725: char b[128];
726:
1.48 dsl 727: if (move(l, c) != OK)
728: return;
1.1 jtc 729: if (n == 0) {
1.30 mycroft 730: hline(' ', w);
1.1 jtc 731: return;
732: }
1.14 mrg 733: (void)snprintf(b, sizeof b, "%*d", w, n);
1.73 lukem 734: if ((int)strlen(b) > w) {
1.63 dsl 735: if (display_mode == TIME)
736: hline('*', w);
737: else
738: puthumanint(n, l, c, w);
1.1 jtc 739: return;
740: }
741: addstr(b);
742: }
743:
1.63 dsl 744: void
1.33 ad 745: putfloat(double f, int l, int c, int w, int d, int nz)
1.1 jtc 746: {
747: char b[128];
748:
1.48 dsl 749: if (move(l, c) != OK)
750: return;
1.1 jtc 751: if (nz && f == 0.0) {
1.30 mycroft 752: hline(' ', w);
1.1 jtc 753: return;
754: }
1.14 mrg 755: (void)snprintf(b, sizeof b, "%*.*f", w, d, f);
1.73 lukem 756: if ((int)strlen(b) > w) {
1.30 mycroft 757: hline('*', w);
1.1 jtc 758: return;
759: }
760: addstr(b);
761: }
762:
763: static void
1.63 dsl 764: getinfo(struct Info *stats)
1.1 jtc 765: {
1.4 cgd 766: int mib[2];
767: size_t size;
1.44 dsl 768: int i;
1.1 jtc 769:
1.62 dsl 770: cpureadstats();
1.65 blymn 771: drvreadstats();
1.77.12.1! tls 772: size = sizeof(stats->nchstats);
! 773: if (sysctlbyname("vfs.namecache_stats", &stats->nchstats, &size,
! 774: NULL, 0) < 0) {
! 775: error("can't get namecache statistics: %s\n", strerror(errno));
! 776: memset(&stats->nchstats, 0, sizeof(stats->nchstats));
! 777: }
1.60 chs 778: if (nintr)
779: NREAD(X_INTRCNT, stats->intrcnt, nintr * LONG);
1.44 dsl 780: for (i = 0; i < nevcnt; i++)
1.60 chs 781: KREAD(ie_head[i].ie_count, &stats->evcnt[i],
782: sizeof stats->evcnt[i]);
1.59 dsl 783: size = sizeof(stats->uvmexp);
1.11 mrg 784: mib[0] = CTL_VM;
1.34 simonb 785: mib[1] = VM_UVMEXP2;
1.59 dsl 786: if (sysctl(mib, 2, &stats->uvmexp, &size, NULL, 0) < 0) {
1.11 mrg 787: error("can't get uvmexp: %s\n", strerror(errno));
1.59 dsl 788: memset(&stats->uvmexp, 0, sizeof(stats->uvmexp));
1.11 mrg 789: }
1.59 dsl 790: size = sizeof(stats->Total);
1.1 jtc 791: mib[0] = CTL_VM;
792: mib[1] = VM_METER;
1.59 dsl 793: if (sysctl(mib, 2, &stats->Total, &size, NULL, 0) < 0) {
1.1 jtc 794: error("Can't get kernel info: %s\n", strerror(errno));
1.59 dsl 795: memset(&stats->Total, 0, sizeof(stats->Total));
1.1 jtc 796: }
797: }
798:
799: static void
1.59 dsl 800: allocinfo(struct Info *stats)
1.1 jtc 801: {
802:
1.60 chs 803: if (nintr &&
804: (stats->intrcnt = calloc(nintr, sizeof(long))) == NULL) {
1.44 dsl 805: error("calloc failed");
806: die(0);
807: }
1.59 dsl 808: if ((stats->evcnt = calloc(nevcnt, sizeof(u_int64_t))) == NULL) {
1.44 dsl 809: error("calloc failed");
1.23 jwise 810: die(0);
811: }
1.1 jtc 812: }
813:
814: static void
1.33 ad 815: copyinfo(struct Info *from, struct Info *to)
1.1 jtc 816: {
817: long *intrcnt;
1.44 dsl 818: u_int64_t *evcnt;
1.1 jtc 819:
1.5 thorpej 820: intrcnt = to->intrcnt;
1.44 dsl 821: evcnt = to->evcnt;
1.1 jtc 822: *to = *from;
1.54 dsl 823: memmove(to->intrcnt = intrcnt, from->intrcnt, nintr * sizeof *intrcnt);
1.44 dsl 824: memmove(to->evcnt = evcnt, from->evcnt, nevcnt * sizeof *evcnt);
1.1 jtc 825: }
826:
827: static void
1.49 dsl 828: dinfo(int dn, int r, int c)
1.1 jtc 829: {
1.44 dsl 830: double atime;
1.49 dsl 831: #define ADV if (disk_horiz) r++; else c += DISKCOLWIDTH
832:
833: mvprintw(r, c, "%*.*s", DISKCOLWIDTH, DISKCOLWIDTH, dr_name[dn]);
834: ADV;
1.1 jtc 835:
1.65 blymn 836: putint((int)(cur.seek[dn]/etime+0.5), r, c, DISKCOLWIDTH);
1.61 blymn 837: ADV;
1.65 blymn 838: putint((int)((cur.rxfer[dn]+cur.wxfer[dn])/etime+0.5),
1.61 blymn 839: r, c, DISKCOLWIDTH);
840: ADV;
1.65 blymn 841: puthumanint((cur.rbytes[dn] + cur.wbytes[dn]) / etime + 0.5,
1.61 blymn 842: r, c, DISKCOLWIDTH);
843: ADV;
844:
845: /* time busy in disk activity */
1.65 blymn 846: atime = cur.time[dn].tv_sec + cur.time[dn].tv_usec / 1000000.0;
1.61 blymn 847: atime = atime * 100.0 / etime;
848: if (atime >= 100)
849: putint(100, r, c, DISKCOLWIDTH);
850: else
851: putfloat(atime, r, c, DISKCOLWIDTH, 1, 1);
1.1 jtc 852: }
CVSweb <webmaster@jp.NetBSD.org>