[BACK]Return to vmstat.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / systat

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>