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

Annotation of src/usr.bin/vmstat/vmstat.c, Revision 1.130

1.130   ! he          1: /* $NetBSD: vmstat.c,v 1.129 2005/02/26 21:19:18 dsl Exp $ */
1.45      thorpej     2:
                      3: /*-
1.87      lukem       4:  * Copyright (c) 1998, 2000, 2001 The NetBSD Foundation, Inc.
1.45      thorpej     5:  * All rights reserved.
                      6:  *
1.87      lukem       7:  * This code is derived from software contributed to The NetBSD Foundation by:
                      8:  *     - Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
                      9:  *       NASA Ames Research Center.
                     10:  *     - Simon Burge and Luke Mewburn of Wasabi Systems, Inc.
1.45      thorpej    11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the NetBSD
                     23:  *     Foundation, Inc. and its contributors.
                     24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     25:  *    contributors may be used to endorse or promote products derived
                     26:  *    from this software without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     38:  * POSSIBILITY OF SUCH DAMAGE.
                     39:  */
1.21      cgd        40:
1.1       cgd        41: /*
1.13      cgd        42:  * Copyright (c) 1980, 1986, 1991, 1993
                     43:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd        44:  *
                     45:  * Redistribution and use in source and binary forms, with or without
                     46:  * modification, are permitted provided that the following conditions
                     47:  * are met:
                     48:  * 1. Redistributions of source code must retain the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer.
                     50:  * 2. Redistributions in binary form must reproduce the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer in the
                     52:  *    documentation and/or other materials provided with the distribution.
1.117     agc        53:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        54:  *    may be used to endorse or promote products derived from this software
                     55:  *    without specific prior written permission.
                     56:  *
                     57:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     58:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     59:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     60:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     61:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     62:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     63:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     64:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     65:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     66:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     67:  * SUCH DAMAGE.
                     68:  */
                     69:
1.38      mrg        70: #include <sys/cdefs.h>
1.1       cgd        71: #ifndef lint
1.38      mrg        72: __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
                     73:        The Regents of the University of California.  All rights reserved.\n");
1.1       cgd        74: #endif /* not lint */
                     75:
                     76: #ifndef lint
1.21      cgd        77: #if 0
1.37      mrg        78: static char sccsid[] = "@(#)vmstat.c   8.2 (Berkeley) 3/1/95";
1.21      cgd        79: #else
1.130   ! he         80: __RCSID("$NetBSD: vmstat.c,v 1.129 2005/02/26 21:19:18 dsl Exp $");
1.21      cgd        81: #endif
1.1       cgd        82: #endif /* not lint */
1.57      thorpej    83:
                     84: #define        __POOL_EXPOSE
1.1       cgd        85:
                     86: #include <sys/param.h>
1.87      lukem      87: #include <sys/mount.h>
                     88: #include <sys/uio.h>
                     89:
                     90: #include <sys/buf.h>
                     91: #include <sys/device.h>
                     92: #include <sys/ioctl.h>
                     93: #include <sys/malloc.h>
1.109     thorpej    94: #include <sys/mallocvar.h>
1.1       cgd        95: #include <sys/namei.h>
1.87      lukem      96: #include <sys/pool.h>
                     97: #include <sys/proc.h>
1.64      perry      98: #include <sys/sched.h>
1.87      lukem      99: #include <sys/socket.h>
1.13      cgd       100: #include <sys/sysctl.h>
1.87      lukem     101: #include <sys/time.h>
                    102: #include <sys/user.h>
1.67      mrg       103:
                    104: #include <uvm/uvm_extern.h>
                    105: #include <uvm/uvm_stat.h>
                    106:
1.87      lukem     107: #include <net/if.h>
                    108: #include <netinet/in.h>
                    109: #include <netinet/in_var.h>
                    110:
                    111: #include <ufs/ufs/inode.h>
                    112:
                    113: #include <nfs/rpcv2.h>
                    114: #include <nfs/nfsproto.h>
                    115: #include <nfs/nfsnode.h>
                    116:
                    117: #include <ctype.h>
1.45      thorpej   118: #include <err.h>
1.87      lukem     119: #include <errno.h>
1.55      kleink    120: #include <fcntl.h>
1.87      lukem     121: #include <kvm.h>
                    122: #include <limits.h>
1.1       cgd       123: #include <nlist.h>
1.87      lukem     124: #undef n_hash
                    125: #include <paths.h>
1.22      jtc       126: #include <signal.h>
1.1       cgd       127: #include <stdio.h>
1.87      lukem     128: #include <stddef.h>
1.1       cgd       129: #include <stdlib.h>
                    130: #include <string.h>
1.87      lukem     131: #include <time.h>
                    132: #include <unistd.h>
1.104     mrg       133: #include <util.h>
1.87      lukem     134:
1.29      thorpej   135: #include "dkstats.h"
1.45      thorpej   136:
1.90      lukem     137: /*
                    138:  * General namelist
                    139:  */
1.87      lukem     140: struct nlist namelist[] =
                    141: {
1.65      itojun    142: #define        X_BOOTTIME      0
1.1       cgd       143:        { "_boottime" },
1.75      enami     144: #define        X_HZ            1
1.1       cgd       145:        { "_hz" },
1.75      enami     146: #define        X_STATHZ        2
1.13      cgd       147:        { "_stathz" },
1.75      enami     148: #define        X_NCHSTATS      3
1.1       cgd       149:        { "_nchstats" },
1.65      itojun    150: #define        X_INTRNAMES     4
1.1       cgd       151:        { "_intrnames" },
1.65      itojun    152: #define        X_EINTRNAMES    5
1.1       cgd       153:        { "_eintrnames" },
1.65      itojun    154: #define        X_INTRCNT       6
1.1       cgd       155:        { "_intrcnt" },
1.65      itojun    156: #define        X_EINTRCNT      7
1.1       cgd       157:        { "_eintrcnt" },
1.65      itojun    158: #define        X_KMEMSTAT      8
1.109     thorpej   159:        { "_kmemstatistics" },
1.65      itojun    160: #define        X_KMEMBUCKETS   9
1.1       cgd       161:        { "_bucket" },
1.75      enami     162: #define        X_ALLEVENTS     10
1.18      pk        163:        { "_allevents" },
1.75      enami     164: #define        X_POOLHEAD      11
1.51      pk        165:        { "_pool_head" },
1.65      itojun    166: #define        X_UVMEXP        12
1.58      thorpej   167:        { "_uvmexp" },
1.105     nathanw   168: #define        X_TIME          13
                    169:        { "_time" },
                    170: #define        X_END           14
1.90      lukem     171:        { NULL },
                    172: };
                    173:
                    174: /*
                    175:  * Namelist for hash statistics
                    176:  */
                    177: struct nlist hashnl[] =
                    178: {
                    179: #define        X_NFSNODE       0
1.87      lukem     180:        { "_nfsnodehash" },
1.90      lukem     181: #define        X_NFSNODETBL    1
1.87      lukem     182:        { "_nfsnodehashtbl" },
1.90      lukem     183: #define        X_IHASH         2
1.87      lukem     184:        { "_ihash" },
1.90      lukem     185: #define        X_IHASHTBL      3
1.87      lukem     186:        { "_ihashtbl" },
1.90      lukem     187: #define        X_BUFHASH       4
1.87      lukem     188:        { "_bufhash" },
1.90      lukem     189: #define        X_BUFHASHTBL    5
1.87      lukem     190:        { "_bufhashtbl" },
1.122     junyoung  191: #define        X_UIHASH        6
1.87      lukem     192:        { "_uihash" },
1.122     junyoung  193: #define        X_UIHASHTBL     7
1.87      lukem     194:        { "_uihashtbl" },
1.122     junyoung  195: #define        X_IFADDRHASH    8
1.87      lukem     196:        { "_in_ifaddrhash" },
1.122     junyoung  197: #define        X_IFADDRHASHTBL 9
1.87      lukem     198:        { "_in_ifaddrhashtbl" },
1.122     junyoung  199: #define        X_NCHASH        10
1.89      lukem     200:        { "_nchash" },
1.122     junyoung  201: #define        X_NCHASHTBL     11
1.89      lukem     202:        { "_nchashtbl" },
1.122     junyoung  203: #define        X_NCVHASH       12
1.89      lukem     204:        { "_ncvhash" },
1.122     junyoung  205: #define        X_NCVHASHTBL    13
1.89      lukem     206:        { "_ncvhashtbl" },
1.122     junyoung  207: #define X_HASHNL_SIZE  14      /* must be last */
1.90      lukem     208:        { NULL },
                    209: };
1.87      lukem     210:
1.90      lukem     211: /*
                    212:  * Namelist for UVM histories
                    213:  */
                    214: struct nlist histnl[] =
                    215: {
                    216:        { "_uvm_histories" },
                    217: #define        X_UVM_HISTORIES         0
                    218:        { NULL },
1.1       cgd       219: };
                    220:
1.87      lukem     221:
1.90      lukem     222:
1.41      mrg       223: struct uvmexp uvmexp, ouvmexp;
1.73      simonb    224: int    ndrives;
1.1       cgd       225:
                    226: int    winlines = 20;
                    227:
1.13      cgd       228: kvm_t *kd;
                    229:
1.87      lukem     230: #define        FORKSTAT        1<<0
                    231: #define        INTRSTAT        1<<1
                    232: #define        MEMSTAT         1<<2
                    233: #define        SUMSTAT         1<<3
                    234: #define        EVCNTSTAT       1<<4
                    235: #define        VMSTAT          1<<5
                    236: #define        HISTLIST        1<<6
                    237: #define        HISTDUMP        1<<7
                    238: #define        HASHSTAT        1<<8
1.88      lukem     239: #define        HASHLIST        1<<9
1.130   ! he        240: #define        VMTOTAL         1<<10
1.1       cgd       241:
1.73      simonb    242: void   cpustats(void);
1.87      lukem     243: void   deref_kptr(const void *, void *, size_t, const char *);
1.73      simonb    244: void   dkstats(void);
                    245: void   doevcnt(int verbose);
1.88      lukem     246: void   dohashstat(int, int, const char *);
1.73      simonb    247: void   dointr(int verbose);
                    248: void   domem(void);
1.126     simonb    249: void   dopool(int, int);
1.96      enami     250: void   dopoolcache(struct pool *, int);
1.73      simonb    251: void   dosum(void);
1.103     mycroft   252: void   dovmstat(struct timespec *, int);
1.130   ! he        253: void   print_total_hdr(void);
        !           254: void   dovmtotal(struct timespec *, int);
1.73      simonb    255: void   kread(int, void *, size_t);
                    256: void   needhdr(int);
                    257: long   getuptime(void);
                    258: void   printhdr(void);
                    259: long   pct(long, long);
                    260: void   usage(void);
                    261: void   doforkst(void);
                    262:
                    263: void   hist_traverse(int, const char *);
                    264: void   hist_dodump(struct uvm_history *);
                    265:
                    266: int    main(int, char **);
                    267: char   **choosedrives(char **);
1.38      mrg       268:
1.29      thorpej   269: /* Namelist and memory file names. */
                    270: char   *nlistf, *memf;
                    271:
1.47      mrg       272: /* allow old usage [vmstat 1] */
                    273: #define        BACKWARD_COMPATIBILITY
                    274:
1.38      mrg       275: int
1.75      enami     276: main(int argc, char *argv[])
1.1       cgd       277: {
1.126     simonb    278:        int c, todo, verbose, wide;
1.103     mycroft   279:        struct timespec interval;
1.1       cgd       280:        int reps;
1.75      enami     281:        char errbuf[_POSIX2_LINE_MAX];
                    282:        gid_t egid = getegid();
1.88      lukem     283:        const char *histname, *hashname;
1.1       cgd       284:
1.88      lukem     285:        histname = hashname = NULL;
1.48      mrg       286:        (void)setegid(getgid());
1.13      cgd       287:        memf = nlistf = NULL;
1.126     simonb    288:        reps = todo = verbose = wide = 0;
1.103     mycroft   289:        interval.tv_sec = 0;
                    290:        interval.tv_nsec = 0;
1.130   ! he        291:        while ((c = getopt(argc, argv, "c:efh:HilLM:mN:stu:UvWw:")) != -1) {
1.1       cgd       292:                switch (c) {
                    293:                case 'c':
                    294:                        reps = atoi(optarg);
                    295:                        break;
1.66      cgd       296:                case 'e':
                    297:                        todo |= EVCNTSTAT;
                    298:                        break;
1.1       cgd       299:                case 'f':
                    300:                        todo |= FORKSTAT;
                    301:                        break;
1.45      thorpej   302:                case 'h':
1.88      lukem     303:                        hashname = optarg;
                    304:                        /* FALLTHROUGH */
                    305:                case 'H':
1.87      lukem     306:                        todo |= HASHSTAT;
1.45      thorpej   307:                        break;
1.1       cgd       308:                case 'i':
                    309:                        todo |= INTRSTAT;
                    310:                        break;
1.45      thorpej   311:                case 'l':
                    312:                        todo |= HISTLIST;
                    313:                        break;
1.88      lukem     314:                case 'L':
                    315:                        todo |= HASHLIST;
                    316:                        break;
1.1       cgd       317:                case 'M':
1.13      cgd       318:                        memf = optarg;
1.1       cgd       319:                        break;
                    320:                case 'm':
                    321:                        todo |= MEMSTAT;
                    322:                        break;
                    323:                case 'N':
1.13      cgd       324:                        nlistf = optarg;
1.1       cgd       325:                        break;
                    326:                case 's':
                    327:                        todo |= SUMSTAT;
                    328:                        break;
1.130   ! he        329:                case 't':
        !           330:                        todo |= VMTOTAL;
        !           331:                        break;
1.87      lukem     332:                case 'u':
                    333:                        histname = optarg;
                    334:                        /* FALLTHROUGH */
                    335:                case 'U':
                    336:                        todo |= HISTDUMP;
                    337:                        break;
1.66      cgd       338:                case 'v':
1.87      lukem     339:                        verbose++;
1.66      cgd       340:                        break;
1.126     simonb    341:                case 'W':
                    342:                        wide++;
                    343:                        break;
1.1       cgd       344:                case 'w':
1.103     mycroft   345:                        interval.tv_sec = atol(optarg);
1.1       cgd       346:                        break;
                    347:                case '?':
                    348:                default:
                    349:                        usage();
                    350:                }
                    351:        }
                    352:        argc -= optind;
                    353:        argv += optind;
                    354:
                    355:        if (todo == 0)
                    356:                todo = VMSTAT;
                    357:
1.13      cgd       358:        /*
1.48      mrg       359:         * Discard setgid privileges.  If not the running kernel, we toss
                    360:         * them away totally so that bad guys can't print interesting stuff
                    361:         * from kernel memory, otherwise switch back to kmem for the
                    362:         * duration of the kvm_openfiles() call.
1.13      cgd       363:         */
                    364:        if (nlistf != NULL || memf != NULL)
1.48      mrg       365:                (void)setgid(getgid());
                    366:        else
                    367:                (void)setegid(egid);
1.13      cgd       368:
1.75      enami     369:        kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
                    370:        if (kd == NULL)
1.87      lukem     371:                errx(1, "kvm_openfiles: %s", errbuf);
1.48      mrg       372:
1.95      simonb    373:        if (nlistf == NULL && memf == NULL)
                    374:                (void)setgid(getgid());
1.1       cgd       375:
1.13      cgd       376:        if ((c = kvm_nlist(kd, namelist)) != 0) {
1.90      lukem     377:                if (c == -1)
                    378:                        errx(1, "kvm_nlist: %s %s", "namelist", kvm_geterr(kd));
                    379:                (void)fprintf(stderr, "vmstat: undefined symbols:");
1.110     matt      380:                for (c = 0; c < sizeof(namelist) / sizeof(namelist[0])-1; c++)
1.90      lukem     381:                        if (namelist[c].n_type == 0)
                    382:                                fprintf(stderr, " %s", namelist[c].n_name);
                    383:                (void)fputc('\n', stderr);
1.1       cgd       384:                exit(1);
                    385:        }
1.90      lukem     386:        if ((c = kvm_nlist(kd, hashnl)) == -1 || c == X_HASHNL_SIZE)
                    387:                errx(1, "kvm_nlist: %s %s", "hashnl", kvm_geterr(kd));
                    388:        if (kvm_nlist(kd, histnl) == -1)
                    389:                errx(1, "kvm_nlist: %s %s", "histnl", kvm_geterr(kd));
1.1       cgd       390:
                    391:        if (todo & VMSTAT) {
                    392:                struct winsize winsize;
                    393:
1.95      simonb    394:                dkinit(0);      /* Initialize disk stats, no disks selected. */
1.49      drochner  395:
                    396:                (void)setgid(getgid()); /* don't need privs anymore */
                    397:
1.29      thorpej   398:                argv = choosedrives(argv);      /* Select disks. */
1.1       cgd       399:                winsize.ws_row = 0;
1.115     simonb    400:                (void)ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
1.1       cgd       401:                if (winsize.ws_row > 0)
                    402:                        winlines = winsize.ws_row;
                    403:
                    404:        }
                    405:
                    406: #ifdef BACKWARD_COMPATIBILITY
                    407:        if (*argv) {
1.103     mycroft   408:                interval.tv_sec = atol(*argv);
1.1       cgd       409:                if (*++argv)
                    410:                        reps = atoi(*argv);
                    411:        }
                    412: #endif
                    413:
1.103     mycroft   414:        if (interval.tv_sec) {
1.1       cgd       415:                if (!reps)
                    416:                        reps = -1;
                    417:        } else if (reps)
1.103     mycroft   418:                interval.tv_sec = 1;
1.1       cgd       419:
1.78      jhawk     420:
                    421:        /*
                    422:         * Statistics dumping is incompatible with the default
                    423:         * VMSTAT/dovmstat() output. So perform the interval/reps handling
                    424:         * for it here.
                    425:         */
1.130   ! he        426:        if ((todo & (VMSTAT|VMTOTAL)) == 0) {
1.99      enami     427:                for (;;) {
                    428:                        if (todo & (HISTLIST|HISTDUMP)) {
                    429:                                if ((todo & (HISTLIST|HISTDUMP)) ==
                    430:                                    (HISTLIST|HISTDUMP))
                    431:                                        errx(1, "you may list or dump,"
                    432:                                            " but not both!");
                    433:                                hist_traverse(todo, histname);
                    434:                                putchar('\n');
                    435:                        }
                    436:                        if (todo & FORKSTAT) {
                    437:                                doforkst();
                    438:                                putchar('\n');
                    439:                        }
                    440:                        if (todo & MEMSTAT) {
                    441:                                domem();
1.126     simonb    442:                                dopool(verbose, wide);
1.99      enami     443:                                putchar('\n');
                    444:                        }
                    445:                        if (todo & SUMSTAT) {
                    446:                                dosum();
                    447:                                putchar('\n');
                    448:                        }
                    449:                        if (todo & INTRSTAT) {
                    450:                                dointr(verbose);
                    451:                                putchar('\n');
                    452:                        }
                    453:                        if (todo & EVCNTSTAT) {
                    454:                                doevcnt(verbose);
                    455:                                putchar('\n');
                    456:                        }
                    457:                        if (todo & (HASHLIST|HASHSTAT)) {
                    458:                                if ((todo & (HASHLIST|HASHSTAT)) ==
                    459:                                    (HASHLIST|HASHSTAT))
                    460:                                        errx(1, "you may list or display,"
                    461:                                            " but not both!");
                    462:                                dohashstat(verbose, todo, hashname);
                    463:                                putchar('\n');
                    464:                        }
1.101     sommerfe  465:
                    466:                        if (reps >= 0 && --reps <=0)
1.99      enami     467:                                break;
1.103     mycroft   468:                        nanosleep(&interval, NULL);
1.87      lukem     469:                }
1.130   ! he        470:        } else {
        !           471:                if ((todo & (VMSTAT|VMTOTAL)) == (VMSTAT|VMTOTAL)) {
        !           472:                        errx(1, "you may not both do vmstat and vmtotal");
        !           473:                }
        !           474:                if (todo & VMSTAT)
        !           475:                        dovmstat(&interval, reps);
        !           476:                if (todo & VMTOTAL)
        !           477:                        dovmtotal(&interval, reps);
        !           478:        }
1.1       cgd       479:        exit(0);
                    480: }
                    481:
                    482: char **
1.73      simonb    483: choosedrives(char **argv)
1.1       cgd       484: {
1.38      mrg       485:        int i;
1.1       cgd       486:
                    487:        /*
                    488:         * Choose drives to be displayed.  Priority goes to (in order) drives
                    489:         * supplied as arguments, default drives.  If everything isn't filled
                    490:         * in and there are drives not taken care of, display the first few
                    491:         * that fit.
                    492:         */
1.75      enami     493: #define        BACKWARD_COMPATIBILITY
1.1       cgd       494:        for (ndrives = 0; *argv; ++argv) {
                    495: #ifdef BACKWARD_COMPATIBILITY
1.124     dsl       496:                if (isdigit((unsigned char)**argv))
1.1       cgd       497:                        break;
                    498: #endif
                    499:                for (i = 0; i < dk_ndrive; i++) {
                    500:                        if (strcmp(dr_name[i], *argv))
                    501:                                continue;
1.29      thorpej   502:                        dk_select[i] = 1;
1.1       cgd       503:                        ++ndrives;
                    504:                        break;
                    505:                }
                    506:        }
1.120     dbj       507:        for (i = 0; i < dk_ndrive && ndrives < 3; i++) {
1.29      thorpej   508:                if (dk_select[i])
1.1       cgd       509:                        continue;
1.29      thorpej   510:                dk_select[i] = 1;
1.1       cgd       511:                ++ndrives;
                    512:        }
1.75      enami     513:        return (argv);
1.1       cgd       514: }
                    515:
                    516: long
1.73      simonb    517: getuptime(void)
1.1       cgd       518: {
1.30      cgd       519:        static struct timeval boottime;
1.105     nathanw   520:        struct timeval now, diff;
1.1       cgd       521:        time_t uptime;
                    522:
1.30      cgd       523:        if (boottime.tv_sec == 0)
1.1       cgd       524:                kread(X_BOOTTIME, &boottime, sizeof(boottime));
1.105     nathanw   525:        kread(X_TIME, &now, sizeof(now));
                    526:        timersub(&now, &boottime, &diff);
                    527:        uptime = diff.tv_sec;
1.87      lukem     528:        if (uptime <= 0 || uptime > 60*60*24*365*10)
                    529:                errx(1, "time makes no sense; namelist must be wrong.");
1.75      enami     530:        return (uptime);
1.1       cgd       531: }
                    532:
                    533: int    hz, hdrcnt;
                    534:
                    535: void
1.130   ! he        536: print_total_hdr()
        !           537: {
        !           538:
        !           539:        (void)printf("procs            memory\n");
        !           540:        (void)printf("ru dw pw sl sw");
        !           541:        (void)printf("   total-v  active-v  active-r");
        !           542:        (void)printf(" vm-sh avm-sh rm-sh arm-sh free\n");
        !           543:        hdrcnt = winlines - 2;
        !           544: }
        !           545:
        !           546: void
        !           547: dovmtotal(struct timespec *interval, int reps)
        !           548: {
        !           549:        struct vmtotal total;
        !           550:        int mib[2];
        !           551:        size_t size;
        !           552:
        !           553:        (void)signal(SIGCONT, needhdr);
        !           554:
        !           555:        for (hdrcnt = 1;;) {
        !           556:                if (!--hdrcnt)
        !           557:                        print_total_hdr();
        !           558:                if (memf != NULL) {
        !           559:                        printf("Unable to get vmtotals from crash dump.\n");
        !           560:                        memset(&total, 0, sizeof(total));
        !           561:                } else {
        !           562:                        size = sizeof(total);
        !           563:                        mib[0] = CTL_VM;
        !           564:                        mib[1] = VM_METER;
        !           565:                        if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
        !           566:                                printf("Can't get vmtotals: %s\n",
        !           567:                                    strerror(errno));
        !           568:                                memset(&total, 0, sizeof(total));
        !           569:                        }
        !           570:                }
        !           571:                printf("%2d ", total.t_rq);
        !           572:                printf("%2d ", total.t_dw);
        !           573:                printf("%2d ", total.t_pw);
        !           574:                printf("%2d ", total.t_sl);
        !           575:                printf("%2d ", total.t_sw);
        !           576:
        !           577:                printf("%9d ", total.t_vm);
        !           578:                printf("%9d ", total.t_avm);
        !           579:                printf("%9d ", total.t_arm);
        !           580:                printf("%5d ", total.t_vmshr);
        !           581:                printf("%6d ", total.t_avmshr);
        !           582:                printf("%5d ", total.t_rmshr);
        !           583:                printf("%6d ", total.t_armshr);
        !           584:                printf("%5d",  total.t_free);
        !           585:
        !           586:                putchar('\n');
        !           587:
        !           588:                (void)fflush(stdout);
        !           589:                if (reps >= 0 && --reps <= 0)
        !           590:                        break;
        !           591:
        !           592:                nanosleep(interval, NULL);
        !           593:        }
        !           594: }
        !           595:
        !           596: void
1.103     mycroft   597: dovmstat(struct timespec *interval, int reps)
1.1       cgd       598: {
                    599:        struct vmtotal total;
                    600:        time_t uptime, halfuptime;
1.17      cgd       601:        int mib[2];
                    602:        size_t size;
1.41      mrg       603:        int pagesize = getpagesize();
1.1       cgd       604:
                    605:        uptime = getuptime();
                    606:        halfuptime = uptime / 2;
                    607:        (void)signal(SIGCONT, needhdr);
                    608:
1.13      cgd       609:        if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
                    610:                kread(X_STATHZ, &hz, sizeof(hz));
1.1       cgd       611:        if (!hz)
                    612:                kread(X_HZ, &hz, sizeof(hz));
                    613:
                    614:        for (hdrcnt = 1;;) {
                    615:                if (!--hdrcnt)
                    616:                        printhdr();
1.29      thorpej   617:                /* Read new disk statistics */
                    618:                dkreadstats();
1.58      thorpej   619:                kread(X_UVMEXP, &uvmexp, sizeof(uvmexp));
                    620:                if (memf != NULL) {
                    621:                        /*
                    622:                         * XXX Can't do this if we're reading a crash
                    623:                         * XXX dump because they're lazily-calculated.
                    624:                         */
                    625:                        printf("Unable to get vmtotals from crash dump.\n");
1.53      perry     626:                        memset(&total, 0, sizeof(total));
1.58      thorpej   627:                } else {
                    628:                        size = sizeof(total);
                    629:                        mib[0] = CTL_VM;
                    630:                        mib[1] = VM_METER;
                    631:                        if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
                    632:                                printf("Can't get vmtotals: %s\n",
                    633:                                    strerror(errno));
                    634:                                memset(&total, 0, sizeof(total));
                    635:                        }
1.13      cgd       636:                }
1.120     dbj       637:                (void)printf("%2d %d %d",
1.13      cgd       638:                    total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
1.75      enami     639: #define        pgtok(a) (long)((a) * (pagesize >> 10))
1.38      mrg       640: #define        rate(x) (u_long)(((x) + halfuptime) / uptime)   /* round */
1.104     mrg       641:                (void)printf(" %6ld %6ld ",
1.1       cgd       642:                    pgtok(total.t_avm), pgtok(total.t_free));
1.42      mrg       643:                (void)printf("%4lu ", rate(uvmexp.faults - ouvmexp.faults));
                    644:                (void)printf("%3lu ", rate(uvmexp.pdreact - ouvmexp.pdreact));
1.46      mrg       645:                (void)printf("%3lu ", rate(uvmexp.pageins - ouvmexp.pageins));
1.44      mrg       646:                (void)printf("%4lu ",
                    647:                    rate(uvmexp.pgswapout - ouvmexp.pgswapout));
                    648:                (void)printf("%4lu ", rate(uvmexp.pdfreed - ouvmexp.pdfreed));
                    649:                (void)printf("%4lu ", rate(uvmexp.pdscans - ouvmexp.pdscans));
1.42      mrg       650:                dkstats();
                    651:                (void)printf("%4lu %4lu %3lu ",
                    652:                    rate(uvmexp.intrs - ouvmexp.intrs),
                    653:                    rate(uvmexp.syscalls - ouvmexp.syscalls),
                    654:                    rate(uvmexp.swtch - ouvmexp.swtch));
                    655:                cpustats();
1.87      lukem     656:                putchar('\n');
1.42      mrg       657:                (void)fflush(stdout);
                    658:                if (reps >= 0 && --reps <= 0)
                    659:                        break;
                    660:                ouvmexp = uvmexp;
1.103     mycroft   661:                uptime = interval->tv_sec;
1.1       cgd       662:                /*
                    663:                 * We round upward to avoid losing low-frequency events
                    664:                 * (i.e., >= 1 per interval but < 1 per second).
                    665:                 */
1.33      thorpej   666:                halfuptime = uptime == 1 ? 0 : (uptime + 1) / 2;
1.103     mycroft   667:                nanosleep(interval, NULL);
1.1       cgd       668:        }
                    669: }
                    670:
1.38      mrg       671: void
1.73      simonb    672: printhdr(void)
1.1       cgd       673: {
1.38      mrg       674:        int i;
1.1       cgd       675:
1.104     mrg       676:        (void)printf(" procs    memory      page%*s", 23, "");
1.29      thorpej   677:        if (ndrives > 0)
1.70      sommerfe  678:                (void)printf("%s %*sfaults      cpu\n",
1.75      enami     679:                    ((ndrives > 1) ? "disks" : "disk"),
                    680:                    ((ndrives > 1) ? ndrives * 3 - 4 : 0), "");
1.1       cgd       681:        else
1.29      thorpej   682:                (void)printf("%*s  faults   cpu\n",
1.75      enami     683:                    ndrives * 3, "");
1.29      thorpej   684:
1.104     mrg       685:        (void)printf(" r b w    avm    fre  flt  re  pi   po   fr   sr ");
1.1       cgd       686:        for (i = 0; i < dk_ndrive; i++)
1.29      thorpej   687:                if (dk_select[i])
1.1       cgd       688:                        (void)printf("%c%c ", dr_name[i][0],
                    689:                            dr_name[i][strlen(dr_name[i]) - 1]);
                    690:        (void)printf("  in   sy  cs us sy id\n");
                    691:        hdrcnt = winlines - 2;
                    692: }
                    693:
                    694: /*
                    695:  * Force a header to be prepended to the next output.
                    696:  */
                    697: void
1.73      simonb    698: needhdr(int dummy)
1.1       cgd       699: {
                    700:
                    701:        hdrcnt = 1;
                    702: }
                    703:
1.38      mrg       704: long
1.73      simonb    705: pct(long top, long bot)
1.1       cgd       706: {
1.13      cgd       707:        long ans;
                    708:
1.1       cgd       709:        if (bot == 0)
1.75      enami     710:                return (0);
1.13      cgd       711:        ans = (quad_t)top * 100 / bot;
                    712:        return (ans);
1.1       cgd       713: }
                    714:
1.38      mrg       715: #define        PCT(top, bot) (int)pct((long)(top), (long)(bot))
1.1       cgd       716:
                    717: void
1.73      simonb    718: dosum(void)
1.1       cgd       719: {
                    720:        struct nchstats nchstats;
1.123     enami     721:        u_long nchtotal;
1.1       cgd       722:
1.58      thorpej   723:        kread(X_UVMEXP, &uvmexp, sizeof(uvmexp));
1.41      mrg       724:
1.44      mrg       725:        (void)printf("%9u bytes per page\n", uvmexp.pagesize);
                    726:
1.81      thorpej   727:        (void)printf("%9u page color%s\n",
                    728:            uvmexp.ncolors, uvmexp.ncolors == 1 ? "" : "s");
                    729:
1.44      mrg       730:        (void)printf("%9u pages managed\n", uvmexp.npages);
                    731:        (void)printf("%9u pages free\n", uvmexp.free);
                    732:        (void)printf("%9u pages active\n", uvmexp.active);
                    733:        (void)printf("%9u pages inactive\n", uvmexp.inactive);
                    734:        (void)printf("%9u pages paging\n", uvmexp.paging);
                    735:        (void)printf("%9u pages wired\n", uvmexp.wired);
1.63      thorpej   736:        (void)printf("%9u zero pages\n", uvmexp.zeropages);
1.44      mrg       737:        (void)printf("%9u reserve pagedaemon pages\n",
                    738:            uvmexp.reserve_pagedaemon);
                    739:        (void)printf("%9u reserve kernel pages\n", uvmexp.reserve_kernel);
1.94      chs       740:        (void)printf("%9u anonymous pages\n", uvmexp.anonpages);
                    741:        (void)printf("%9u cached file pages\n", uvmexp.filepages);
                    742:        (void)printf("%9u cached executable pages\n", uvmexp.execpages);
1.44      mrg       743:
                    744:        (void)printf("%9u minimum free pages\n", uvmexp.freemin);
                    745:        (void)printf("%9u target free pages\n", uvmexp.freetarg);
                    746:        (void)printf("%9u target inactive pages\n", uvmexp.inactarg);
                    747:        (void)printf("%9u maximum wired pages\n", uvmexp.wiredmax);
                    748:
                    749:        (void)printf("%9u swap devices\n", uvmexp.nswapdev);
                    750:        (void)printf("%9u swap pages\n", uvmexp.swpages);
                    751:        (void)printf("%9u swap pages in use\n", uvmexp.swpginuse);
                    752:        (void)printf("%9u swap allocations\n", uvmexp.nswget);
                    753:        (void)printf("%9u anons\n", uvmexp.nanon);
                    754:        (void)printf("%9u free anons\n", uvmexp.nfreeanon);
                    755:
1.43      mrg       756:        (void)printf("%9u total faults taken\n", uvmexp.faults);
                    757:        (void)printf("%9u traps\n", uvmexp.traps);
                    758:        (void)printf("%9u device interrupts\n", uvmexp.intrs);
1.121     wiz       759:        (void)printf("%9u CPU context switches\n", uvmexp.swtch);
1.43      mrg       760:        (void)printf("%9u software interrupts\n", uvmexp.softs);
                    761:        (void)printf("%9u system calls\n", uvmexp.syscalls);
1.60      fredb     762:        (void)printf("%9u pagein requests\n", uvmexp.pageins);
                    763:        (void)printf("%9u pageout requests\n", uvmexp.pdpageouts);
1.43      mrg       764:        (void)printf("%9u swap ins\n", uvmexp.swapins);
                    765:        (void)printf("%9u swap outs\n", uvmexp.swapouts);
1.60      fredb     766:        (void)printf("%9u pages swapped in\n", uvmexp.pgswapin);
                    767:        (void)printf("%9u pages swapped out\n", uvmexp.pgswapout);
1.43      mrg       768:        (void)printf("%9u forks total\n", uvmexp.forks);
                    769:        (void)printf("%9u forks blocked parent\n", uvmexp.forks_ppwait);
                    770:        (void)printf("%9u forks shared address space with parent\n",
                    771:            uvmexp.forks_sharevm);
1.63      thorpej   772:        (void)printf("%9u pagealloc zero wanted and avail\n",
                    773:            uvmexp.pga_zerohit);
                    774:        (void)printf("%9u pagealloc zero wanted and not avail\n",
                    775:            uvmexp.pga_zeromiss);
1.68      thorpej   776:        (void)printf("%9u aborts of idle page zeroing\n",
                    777:            uvmexp.zeroaborts);
1.79      thorpej   778:        (void)printf("%9u pagealloc desired color avail\n",
                    779:            uvmexp.colorhit);
                    780:        (void)printf("%9u pagealloc desired color not avail\n",
                    781:            uvmexp.colormiss);
1.44      mrg       782:
                    783:        (void)printf("%9u faults with no memory\n", uvmexp.fltnoram);
                    784:        (void)printf("%9u faults with no anons\n", uvmexp.fltnoanon);
1.43      mrg       785:        (void)printf("%9u faults had to wait on pages\n", uvmexp.fltpgwait);
                    786:        (void)printf("%9u faults found released page\n", uvmexp.fltpgrele);
                    787:        (void)printf("%9u faults relock (%u ok)\n", uvmexp.fltrelck,
                    788:            uvmexp.fltrelckok);
                    789:        (void)printf("%9u anon page faults\n", uvmexp.fltanget);
                    790:        (void)printf("%9u anon retry faults\n", uvmexp.fltanretry);
                    791:        (void)printf("%9u amap copy faults\n", uvmexp.fltamcopy);
                    792:        (void)printf("%9u neighbour anon page faults\n", uvmexp.fltnamap);
                    793:        (void)printf("%9u neighbour object page faults\n", uvmexp.fltnomap);
                    794:        (void)printf("%9u locked pager get faults\n", uvmexp.fltlget);
                    795:        (void)printf("%9u unlocked pager get faults\n", uvmexp.fltget);
                    796:        (void)printf("%9u anon faults\n", uvmexp.flt_anon);
                    797:        (void)printf("%9u anon copy on write faults\n", uvmexp.flt_acow);
                    798:        (void)printf("%9u object faults\n", uvmexp.flt_obj);
                    799:        (void)printf("%9u promote copy faults\n", uvmexp.flt_prcopy);
                    800:        (void)printf("%9u promote zero fill faults\n", uvmexp.flt_przero);
1.44      mrg       801:
                    802:        (void)printf("%9u times daemon wokeup\n",uvmexp.pdwoke);
                    803:        (void)printf("%9u revolutions of the clock hand\n", uvmexp.pdrevs);
                    804:        (void)printf("%9u times daemon attempted swapout\n", uvmexp.pdswout);
                    805:        (void)printf("%9u pages freed by daemon\n", uvmexp.pdfreed);
                    806:        (void)printf("%9u pages scanned by daemon\n", uvmexp.pdscans);
1.75      enami     807:        (void)printf("%9u anonymous pages scanned by daemon\n",
                    808:            uvmexp.pdanscan);
1.44      mrg       809:        (void)printf("%9u object pages scanned by daemon\n", uvmexp.pdobscan);
                    810:        (void)printf("%9u pages reactivated\n", uvmexp.pdreact);
1.123     enami     811:        (void)printf("%9u anonymous pages reactivated\n", uvmexp.pdreanon);
                    812:        (void)printf("%9u cached file pages reactivated\n", uvmexp.pdrefile);
                    813:        (void)printf("%9u cached executable pages reactivated\n",
                    814:            uvmexp.pdreexec);
1.44      mrg       815:        (void)printf("%9u pages found busy by daemon\n", uvmexp.pdbusy);
                    816:        (void)printf("%9u total pending pageouts\n", uvmexp.pdpending);
                    817:        (void)printf("%9u pages deactivated\n", uvmexp.pddeact);
1.123     enami     818:
1.1       cgd       819:        kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
                    820:        nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
                    821:            nchstats.ncs_badhits + nchstats.ncs_falsehits +
                    822:            nchstats.ncs_miss + nchstats.ncs_long;
1.123     enami     823:        (void)printf("%9lu total name lookups\n", nchtotal);
                    824:        (void)printf("%9lu good hits\n", nchstats.ncs_goodhits);
                    825:        (void)printf("%9lu negative hits\n", nchstats.ncs_neghits);
                    826:        (void)printf("%9lu bad hits\n", nchstats.ncs_badhits);
                    827:        (void)printf("%9lu false hits\n", nchstats.ncs_falsehits);
                    828:        (void)printf("%9lu miss\n", nchstats.ncs_miss);
                    829:        (void)printf("%9lu too long\n", nchstats.ncs_long);
                    830:        (void)printf("%9lu pass2 hits\n", nchstats.ncs_pass2);
                    831:        (void)printf("%9lu 2passes\n", nchstats.ncs_2passes);
1.1       cgd       832:        (void)printf(
                    833:            "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
                    834:            "", PCT(nchstats.ncs_goodhits, nchtotal),
                    835:            PCT(nchstats.ncs_neghits, nchtotal),
                    836:            PCT(nchstats.ncs_pass2, nchtotal));
                    837:        (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
                    838:            PCT(nchstats.ncs_badhits, nchtotal),
                    839:            PCT(nchstats.ncs_falsehits, nchtotal),
                    840:            PCT(nchstats.ncs_long, nchtotal));
                    841: }
                    842:
                    843: void
1.73      simonb    844: doforkst(void)
1.1       cgd       845: {
1.41      mrg       846:
1.58      thorpej   847:        kread(X_UVMEXP, &uvmexp, sizeof(uvmexp));
                    848:
1.41      mrg       849:        (void)printf("%u forks total\n", uvmexp.forks);
                    850:        (void)printf("%u forks blocked parent\n", uvmexp.forks_ppwait);
                    851:        (void)printf("%u forks shared address space with parent\n",
                    852:            uvmexp.forks_sharevm);
1.1       cgd       853: }
                    854:
                    855: void
1.73      simonb    856: dkstats(void)
1.1       cgd       857: {
1.101     sommerfe  858:        int dn;
1.1       cgd       859:        double etime;
                    860:
1.29      thorpej   861:        /* Calculate disk stat deltas. */
                    862:        dkswap();
1.101     sommerfe  863:        etime = cur.cp_etime;
                    864:
1.1       cgd       865:        for (dn = 0; dn < dk_ndrive; ++dn) {
1.29      thorpej   866:                if (!dk_select[dn])
1.1       cgd       867:                        continue;
1.104     mrg       868:                (void)printf("%2.0f ",
                    869:                    (cur.dk_rxfer[dn] + cur.dk_wxfer[dn]) / etime);
1.1       cgd       870:        }
                    871: }
                    872:
                    873: void
1.73      simonb    874: cpustats(void)
1.1       cgd       875: {
1.38      mrg       876:        int state;
1.129     dsl       877:        double pcnt, total;
1.120     dbj       878:        double stat_us, stat_sy, stat_id;
1.1       cgd       879:
                    880:        total = 0;
                    881:        for (state = 0; state < CPUSTATES; ++state)
1.29      thorpej   882:                total += cur.cp_time[state];
1.1       cgd       883:        if (total)
1.129     dsl       884:                pcnt = 100 / total;
1.1       cgd       885:        else
1.129     dsl       886:                pcnt = 0;
                    887:        stat_us = (cur.cp_time[CP_USER] + cur.cp_time[CP_NICE]) * pcnt;
                    888:        stat_sy = (cur.cp_time[CP_SYS] + cur.cp_time[CP_INTR]) * pcnt;
                    889:        stat_id = cur.cp_time[CP_IDLE] * pcnt;
1.120     dbj       890:        (void)printf("%*.0f ", ((stat_sy >= 100) ? 1 : 2), stat_us);
                    891:        (void)printf("%*.0f ", ((stat_us >= 100 || stat_id >= 100) ? 1 : 2), stat_sy);
                    892:        (void)printf("%2.0f", stat_id);
1.1       cgd       893: }
                    894:
                    895: void
1.66      cgd       896: dointr(int verbose)
1.1       cgd       897: {
1.85      enami     898:        unsigned long *intrcnt;
                    899:        unsigned long long inttotal, uptime;
1.38      mrg       900:        int nintr, inamlen;
                    901:        char *intrname;
1.28      cgd       902:        struct evcntlist allevents;
                    903:        struct evcnt evcnt, *evptr;
1.66      cgd       904:        char evgroup[EVCNT_STRING_MAX], evname[EVCNT_STRING_MAX];
1.1       cgd       905:
                    906:        uptime = getuptime();
1.13      cgd       907:        nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
                    908:        inamlen =
                    909:            namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
1.1       cgd       910:        intrcnt = malloc((size_t)nintr);
                    911:        intrname = malloc((size_t)inamlen);
1.87      lukem     912:        if (intrcnt == NULL || intrname == NULL)
                    913:                errx(1, "%s", "");
1.1       cgd       914:        kread(X_INTRCNT, intrcnt, (size_t)nintr);
                    915:        kread(X_INTRNAMES, intrname, (size_t)inamlen);
1.83      matt      916:        (void)printf("%-34s %16s %8s\n", "interrupt", "total", "rate");
1.1       cgd       917:        inttotal = 0;
                    918:        nintr /= sizeof(long);
                    919:        while (--nintr >= 0) {
1.66      cgd       920:                if (*intrcnt || verbose)
1.85      enami     921:                        (void)printf("%-34s %16llu %8llu\n", intrname,
                    922:                            (unsigned long long)*intrcnt,
                    923:                            (unsigned long long)(*intrcnt / uptime));
1.1       cgd       924:                intrname += strlen(intrname) + 1;
                    925:                inttotal += *intrcnt++;
                    926:        }
1.18      pk        927:        kread(X_ALLEVENTS, &allevents, sizeof allevents);
1.28      cgd       928:        evptr = allevents.tqh_first;
                    929:        while (evptr) {
1.87      lukem     930:                deref_kptr(evptr, &evcnt, sizeof(evcnt), "event chain trashed");
1.66      cgd       931:                evptr = evcnt.ev_list.tqe_next;
                    932:                if (evcnt.ev_type != EVCNT_TYPE_INTR)
                    933:                        continue;
                    934:
                    935:                if (evcnt.ev_count == 0 && !verbose)
                    936:                        continue;
                    937:
1.87      lukem     938:                deref_kptr(evcnt.ev_group, evgroup, evcnt.ev_grouplen + 1,
                    939:                    "event chain trashed");
                    940:                deref_kptr(evcnt.ev_name, evname, evcnt.ev_namelen + 1,
                    941:                    "event chain trashed");
1.66      cgd       942:
1.85      enami     943:                (void)printf("%s %s%*s %16llu %8llu\n", evgroup, evname,
1.83      matt      944:                    34 - (evcnt.ev_grouplen + 1 + evcnt.ev_namelen), "",
1.85      enami     945:                    (unsigned long long)evcnt.ev_count,
                    946:                    (unsigned long long)(evcnt.ev_count / uptime));
1.66      cgd       947:
                    948:                inttotal += evcnt.ev_count++;
                    949:        }
1.85      enami     950:        (void)printf("%-34s %16llu %8llu\n", "Total", inttotal,
                    951:            (unsigned long long)(inttotal / uptime));
1.66      cgd       952: }
                    953:
                    954: void
                    955: doevcnt(int verbose)
                    956: {
1.83      matt      957:        static const char * evtypes [] = { "misc", "intr", "trap" };
1.85      enami     958:        unsigned long long uptime;
1.66      cgd       959:        struct evcntlist allevents;
                    960:        struct evcnt evcnt, *evptr;
                    961:        char evgroup[EVCNT_STRING_MAX], evname[EVCNT_STRING_MAX];
                    962:
                    963:        /* XXX should print type! */
                    964:
                    965:        uptime = getuptime();
1.83      matt      966:        (void)printf("%-34s %16s %8s %s\n", "event", "total", "rate", "type");
1.66      cgd       967:        kread(X_ALLEVENTS, &allevents, sizeof allevents);
                    968:        evptr = allevents.tqh_first;
                    969:        while (evptr) {
1.87      lukem     970:                deref_kptr(evptr, &evcnt, sizeof(evcnt), "event chain trashed");
1.32      cgd       971:
1.28      cgd       972:                evptr = evcnt.ev_list.tqe_next;
1.66      cgd       973:                if (evcnt.ev_count == 0 && !verbose)
                    974:                        continue;
                    975:
1.87      lukem     976:                deref_kptr(evcnt.ev_group, evgroup, evcnt.ev_grouplen + 1,
                    977:                    "event chain trashed");
                    978:                deref_kptr(evcnt.ev_name, evname, evcnt.ev_namelen + 1,
                    979:                    "event chain trashed");
1.66      cgd       980:
1.85      enami     981:                (void)printf("%s %s%*s %16llu %8llu %s\n", evgroup, evname,
1.83      matt      982:                    34 - (evcnt.ev_grouplen + 1 + evcnt.ev_namelen), "",
1.85      enami     983:                    (unsigned long long)evcnt.ev_count,
                    984:                    (unsigned long long)(evcnt.ev_count / uptime),
1.86      enami     985:                    (evcnt.ev_type < sizeof(evtypes)/sizeof(evtypes[0]) ?
                    986:                        evtypes[evcnt.ev_type] : "?"));
1.18      pk        987:        }
1.1       cgd       988: }
                    989:
1.109     thorpej   990: static char memname[64];
1.1       cgd       991:
                    992: void
1.73      simonb    993: domem(void)
1.1       cgd       994: {
1.38      mrg       995:        struct kmembuckets *kp;
1.109     thorpej   996:        struct malloc_type ks, *ksp;
1.38      mrg       997:        int i, j;
1.13      cgd       998:        int len, size, first;
                    999:        long totuse = 0, totfree = 0, totreq = 0;
1.1       cgd      1000:        struct kmembuckets buckets[MINBUCKET + 16];
                   1001:
                   1002:        kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
1.34      thorpej  1003:        for (first = 1, i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16;
                   1004:            i++, kp++) {
1.1       cgd      1005:                if (kp->kb_calls == 0)
                   1006:                        continue;
1.34      thorpej  1007:                if (first) {
                   1008:                        (void)printf("Memory statistics by bucket size\n");
                   1009:                        (void)printf(
                   1010:                 "    Size   In Use   Free   Requests  HighWater  Couldfree\n");
                   1011:                        first = 0;
                   1012:                }
1.1       cgd      1013:                size = 1 << i;
1.75      enami    1014:                (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
                   1015:                    kp->kb_total - kp->kb_totalfree,
                   1016:                    kp->kb_totalfree, kp->kb_calls,
                   1017:                    kp->kb_highwat, kp->kb_couldfree);
1.1       cgd      1018:                totfree += size * kp->kb_totalfree;
1.34      thorpej  1019:        }
                   1020:
                   1021:        /*
                   1022:         * If kmem statistics are not being gathered by the kernel,
                   1023:         * first will still be 1.
                   1024:         */
                   1025:        if (first) {
1.87      lukem    1026:                warnx("Kmem statistics are not being gathered by the kernel.");
1.34      thorpej  1027:                return;
1.1       cgd      1028:        }
                   1029:
1.13      cgd      1030:        (void)printf("\nMemory usage type by bucket size\n");
                   1031:        (void)printf("    Size  Type(s)\n");
                   1032:        kp = &buckets[MINBUCKET];
                   1033:        for (j =  1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
                   1034:                if (kp->kb_calls == 0)
                   1035:                        continue;
                   1036:                first = 1;
                   1037:                len = 8;
1.109     thorpej  1038:                for (kread(X_KMEMSTAT, &ksp, sizeof(ksp));
                   1039:                     ksp != NULL; ksp = ks.ks_next) {
                   1040:                        deref_kptr(ksp, &ks, sizeof(ks), "malloc type");
                   1041:                        if (ks.ks_calls == 0)
1.13      cgd      1042:                                continue;
1.109     thorpej  1043:                        if ((ks.ks_size & j) == 0)
1.13      cgd      1044:                                continue;
1.109     thorpej  1045:                        deref_kptr(ks.ks_shortdesc, memname,
                   1046:                            sizeof(memname), "malloc type name");
                   1047:                        len += 2 + strlen(memname);
1.13      cgd      1048:                        if (first)
1.109     thorpej  1049:                                printf("%8d  %s", j, memname);
1.13      cgd      1050:                        else
                   1051:                                printf(",");
                   1052:                        if (len >= 80) {
                   1053:                                printf("\n\t ");
1.109     thorpej  1054:                                len = 10 + strlen(memname);
1.13      cgd      1055:                        }
                   1056:                        if (!first)
1.109     thorpej  1057:                                printf(" %s", memname);
1.13      cgd      1058:                        first = 0;
                   1059:                }
1.87      lukem    1060:                putchar('\n');
1.13      cgd      1061:        }
                   1062:
1.1       cgd      1063:        (void)printf(
1.119     simonb   1064:            "\nMemory statistics by type                           Type  Kern\n");
1.13      cgd      1065:        (void)printf(
1.36      is       1066: "         Type  InUse MemUse HighUse  Limit Requests Limit Limit Size(s)\n");
1.109     thorpej  1067:        for (kread(X_KMEMSTAT, &ksp, sizeof(ksp));
                   1068:             ksp != NULL; ksp = ks.ks_next) {
                   1069:                deref_kptr(ksp, &ks, sizeof(ks), "malloc type");
                   1070:                if (ks.ks_calls == 0)
1.1       cgd      1071:                        continue;
1.109     thorpej  1072:                deref_kptr(ks.ks_shortdesc, memname,
                   1073:                    sizeof(memname), "malloc type name");
1.36      is       1074:                (void)printf("%14s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
1.109     thorpej  1075:                    memname,
                   1076:                    ks.ks_inuse, (ks.ks_memuse + 1023) / 1024,
                   1077:                    (ks.ks_maxused + 1023) / 1024,
                   1078:                    (ks.ks_limit + 1023) / 1024, ks.ks_calls,
                   1079:                    ks.ks_limblocks, ks.ks_mapblocks);
1.13      cgd      1080:                first = 1;
                   1081:                for (j =  1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
1.109     thorpej  1082:                        if ((ks.ks_size & j) == 0)
1.13      cgd      1083:                                continue;
                   1084:                        if (first)
                   1085:                                printf("  %d", j);
                   1086:                        else
                   1087:                                printf(",%d", j);
                   1088:                        first = 0;
                   1089:                }
                   1090:                printf("\n");
1.109     thorpej  1091:                totuse += ks.ks_memuse;
                   1092:                totreq += ks.ks_calls;
1.1       cgd      1093:        }
1.102     soren    1094:        (void)printf("\nMemory totals:  In Use    Free    Requests\n");
                   1095:        (void)printf("              %7ldK %6ldK    %8ld\n\n",
1.75      enami    1096:            (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
1.51      pk       1097: }
                   1098:
                   1099: void
1.126     simonb   1100: dopool(int verbose, int wide)
1.51      pk       1101: {
1.69      enami    1102:        int first, ovflw;
1.87      lukem    1103:        void *addr;
1.126     simonb   1104:        long total, inuse, this_total, this_inuse;
1.51      pk       1105:        TAILQ_HEAD(,pool) pool_head;
                   1106:        struct pool pool, *pp = &pool;
1.98      christos 1107:        struct pool_allocator pa;
1.87      lukem    1108:        char name[32], maxp[32];
1.51      pk       1109:
                   1110:        kread(X_POOLHEAD, &pool_head, sizeof(pool_head));
1.87      lukem    1111:        addr = TAILQ_FIRST(&pool_head);
1.51      pk       1112:
1.126     simonb   1113:        total = inuse = 0;
                   1114:
1.113     dsl      1115:        for (first = 1; addr != NULL; addr = TAILQ_NEXT(pp, pr_poollist) ) {
1.87      lukem    1116:                deref_kptr(addr, pp, sizeof(*pp), "pool chain trashed");
1.98      christos 1117:                deref_kptr(pp->pr_alloc, &pa, sizeof(pa),
1.125     dsainty  1118:                    "pool allocator trashed");
1.87      lukem    1119:                deref_kptr(pp->pr_wchan, name, sizeof(name),
1.98      christos 1120:                    "pool wait channel trashed");
1.87      lukem    1121:                name[sizeof(name)-1] = '\0';
1.51      pk       1122:
                   1123:                if (first) {
                   1124:                        (void)printf("Memory resource pool statistics\n");
                   1125:                        (void)printf(
1.126     simonb   1126:                            "%-*s%*s%*s%5s%*s%s%s%*s%*s%6s%s%6s%6s%6s%5s%s%s\n",
                   1127:                            wide ? 16 : 11, "Name",
                   1128:                            wide ? 6 : 5, "Size",
                   1129:                            wide ? 12 : 9, "Requests",
1.75      enami    1130:                            "Fail",
1.126     simonb   1131:                            wide ? 12 : 9, "Releases",
                   1132:                            wide ? " InUse" : "",
                   1133:                            wide ? " Avail" : "",
                   1134:                            wide ? 7 : 6, "Pgreq",
                   1135:                            wide ? 7 : 6, "Pgrel",
1.75      enami    1136:                            "Npage",
1.126     simonb   1137:                            wide ? " PageSz" : "",
1.75      enami    1138:                            "Hiwat",
                   1139:                            "Minpg",
                   1140:                            "Maxpg",
1.126     simonb   1141:                            "Idle",
                   1142:                            wide ? " Flags" : "",
                   1143:                            wide ? "   Util" : "");
1.51      pk       1144:                        first = 0;
                   1145:                }
1.113     dsl      1146:                if (pp->pr_nget == 0 && !verbose)
                   1147:                        continue;
1.51      pk       1148:                if (pp->pr_maxpages == UINT_MAX)
1.116     itojun   1149:                        snprintf(maxp, sizeof(maxp), "inf");
1.51      pk       1150:                else
1.116     itojun   1151:                        snprintf(maxp, sizeof(maxp), "%u", pp->pr_maxpages);
1.69      enami    1152: /*
                   1153:  * Print single word.  `ovflow' is number of characters didn't fit
                   1154:  * on the last word.  `fmt' is a format string to print this word.
                   1155:  * It must contain asterisk for field width.  `width' is a width
                   1156:  * occupied by this word.  `fixed' is a number of constant chars in
                   1157:  * `fmt'.  `val' is a value to be printed using format string `fmt'.
                   1158:  */
                   1159: #define        PRWORD(ovflw, fmt, width, fixed, val) do {      \
                   1160:        (ovflw) += printf((fmt),                        \
                   1161:            (width) - (fixed) - (ovflw) > 0 ?           \
                   1162:            (width) - (fixed) - (ovflw) : 0,            \
                   1163:            (val)) - (width);                           \
                   1164:        if ((ovflw) < 0)                                \
                   1165:                (ovflw) = 0;                            \
                   1166: } while (/* CONSTCOND */0)
                   1167:                ovflw = 0;
1.126     simonb   1168:                PRWORD(ovflw, "%-*s", wide ? 16 : 11, 0, name);
                   1169:                PRWORD(ovflw, " %*u", wide ? 6 : 5, 1, pp->pr_size);
                   1170:                PRWORD(ovflw, " %*lu", wide ? 12 : 9, 1, pp->pr_nget);
1.69      enami    1171:                PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nfail);
1.126     simonb   1172:                PRWORD(ovflw, " %*lu", wide ? 12 : 9, 1, pp->pr_nput);
                   1173:                if (wide)
                   1174:                        PRWORD(ovflw, " %*u", 6, 1, pp->pr_nout);
                   1175:                if (wide)
                   1176:                        PRWORD(ovflw, " %*u", 6, 1, pp->pr_nitems);
                   1177:                PRWORD(ovflw, " %*lu", wide ? 7 : 6, 1, pp->pr_npagealloc);
                   1178:                PRWORD(ovflw, " %*lu", wide ? 7 : 6, 1, pp->pr_npagefree);
                   1179:                PRWORD(ovflw, " %*u", 6, 1, pp->pr_npages);
                   1180:                if (wide)
                   1181:                        PRWORD(ovflw, " %*u", 7, 1, pa.pa_pagesz);
                   1182:                PRWORD(ovflw, " %*u", 6, 1, pp->pr_hiwat);
                   1183:                PRWORD(ovflw, " %*u", 6, 1, pp->pr_minpages);
1.69      enami    1184:                PRWORD(ovflw, " %*s", 6, 1, maxp);
1.126     simonb   1185:                PRWORD(ovflw, " %*lu", 5, 1, pp->pr_nidle);
                   1186:                if (wide)
                   1187:                        PRWORD(ovflw, " 0x%0*x", 4, 1,
                   1188:                            pp->pr_flags | pp->pr_roflags);
1.51      pk       1189:
1.126     simonb   1190:                this_inuse = pp->pr_nout * pp->pr_size;
                   1191:                this_total = pp->pr_npages * pa.pa_pagesz;
1.84      bjh21    1192:                if (pp->pr_roflags & PR_RECURSIVE) {
                   1193:                        /*
                   1194:                         * Don't count in-use memory, since it's part
                   1195:                         * of another pool and will be accounted for
                   1196:                         * there.
                   1197:                         */
1.126     simonb   1198:                        total += (this_total - this_inuse);
1.84      bjh21    1199:                } else {
1.126     simonb   1200:                        inuse += this_inuse;
                   1201:                        total += this_total;
1.84      bjh21    1202:                }
1.126     simonb   1203:                if (wide) {
                   1204:                        if (this_total == 0)
                   1205:                                printf("   ---");
                   1206:                        else
                   1207:                                printf(" %5.1f%%",
                   1208:                                    (100.0 * this_inuse) / this_total);
                   1209:                }
                   1210:                printf("\n");
1.96      enami    1211:                dopoolcache(pp, verbose);
1.51      pk       1212:        }
                   1213:
1.76      enami    1214:        inuse /= 1024;
                   1215:        total /= 1024;
1.51      pk       1216:        printf("\nIn use %ldK, total allocated %ldK; utilization %.1f%%\n",
1.126     simonb   1217:            inuse, total, (100.0 * inuse) / total);
1.1       cgd      1218: }
1.96      enami    1219:
                   1220: void
                   1221: dopoolcache(struct pool *pp, int verbose)
                   1222: {
                   1223:        struct pool_cache pool_cache, *pc = &pool_cache;
                   1224:        struct pool_cache_group pool_cache_group, *pcg = &pool_cache_group;
                   1225:        void *addr, *pcg_addr;
                   1226:        int i;
                   1227:
                   1228:        if (verbose < 1)
                   1229:                return;
                   1230:
                   1231:        for (addr = TAILQ_FIRST(&pp->pr_cachelist); addr != NULL;
                   1232:            addr = TAILQ_NEXT(pc, pc_poollist)) {
                   1233:                deref_kptr(addr, pc, sizeof(*pc), "pool cache trashed");
                   1234:                printf("\tcache %p: allocfrom %p freeto %p\n", addr,
                   1235:                    pc->pc_allocfrom, pc->pc_freeto);
                   1236:                printf("\t    hits %lu misses %lu ngroups %lu nitems %lu\n",
                   1237:                    pc->pc_hits, pc->pc_misses, pc->pc_ngroups, pc->pc_nitems);
                   1238:                if (verbose < 2)
                   1239:                        continue;
                   1240:                for (pcg_addr = TAILQ_FIRST(&pc->pc_grouplist);
                   1241:                    pcg_addr != NULL; pcg_addr = TAILQ_NEXT(pcg, pcg_list)) {
1.97      enami    1242:                        deref_kptr(pcg_addr, pcg, sizeof(*pcg),
                   1243:                            "pool cache group trashed");
1.96      enami    1244:                        printf("\t\tgroup %p: avail %d\n", pcg_addr,
                   1245:                            pcg->pcg_avail);
1.112     thorpej  1246:                        for (i = 0; i < PCG_NOBJECTS; i++) {
                   1247:                                if (pcg->pcg_objects[i].pcgo_pa !=
                   1248:                                    POOL_PADDR_INVALID) {
                   1249:                                        printf("\t\t\t%p, 0x%llx\n",
                   1250:                                            pcg->pcg_objects[i].pcgo_va,
                   1251:                                            (unsigned long long)
                   1252:                                            pcg->pcg_objects[i].pcgo_pa);
                   1253:                                } else {
                   1254:                                        printf("\t\t\t%p\n",
                   1255:                                            pcg->pcg_objects[i].pcgo_va);
                   1256:                                }
                   1257:                        }
1.96      enami    1258:                }
                   1259:        }
                   1260:
                   1261: }
1.90      lukem    1262:
1.87      lukem    1263: enum hashtype {                        /* from <sys/systm.h> */
                   1264:        HASH_LIST,
                   1265:        HASH_TAILQ
                   1266: };
                   1267:
                   1268: struct uidinfo {               /* XXX: no kernel header file */
                   1269:        LIST_ENTRY(uidinfo) ui_hash;
                   1270:        uid_t   ui_uid;
                   1271:        long    ui_proccnt;
                   1272: };
                   1273:
                   1274: struct kernel_hash {
1.90      lukem    1275:        const char *    description;    /* description */
                   1276:        int             hashsize;       /* nlist index for hash size */
                   1277:        int             hashtbl;        /* nlist index for hash table */
                   1278:        enum hashtype   type;           /* type of hash table */
1.101     sommerfe 1279:        size_t          offset;         /* offset of {LIST,TAILQ}_NEXT */
1.87      lukem    1280: } khashes[] =
                   1281: {
                   1282:        {
1.90      lukem    1283:                "buffer hash",
                   1284:                X_BUFHASH, X_BUFHASHTBL,
                   1285:                HASH_LIST, offsetof(struct buf, b_hash)
                   1286:        }, {
                   1287:                "inode cache (ihash)",
1.87      lukem    1288:                X_IHASH, X_IHASHTBL,
                   1289:                HASH_LIST, offsetof(struct inode, i_hash)
1.90      lukem    1290:        }, {
                   1291:                "ipv4 address -> interface hash",
1.87      lukem    1292:                X_IFADDRHASH, X_IFADDRHASHTBL,
                   1293:                HASH_LIST, offsetof(struct in_ifaddr, ia_hash),
1.90      lukem    1294:        }, {
                   1295:                "name cache hash",
1.89      lukem    1296:                X_NCHASH, X_NCHASHTBL,
                   1297:                HASH_LIST, offsetof(struct namecache, nc_hash),
1.90      lukem    1298:        }, {
                   1299:                "name cache directory hash",
1.89      lukem    1300:                X_NCVHASH, X_NCVHASHTBL,
                   1301:                HASH_LIST, offsetof(struct namecache, nc_vhash),
1.90      lukem    1302:        }, {
                   1303:                "nfs client node cache",
                   1304:                X_NFSNODE, X_NFSNODETBL,
                   1305:                HASH_LIST, offsetof(struct nfsnode, n_hash)
                   1306:        }, {
                   1307:                "user info (uid -> used processes) hash",
                   1308:                X_UIHASH, X_UIHASHTBL,
                   1309:                HASH_LIST, offsetof(struct uidinfo, ui_hash),
                   1310:        }, {
                   1311:                NULL, -1, -1, 0, 0,
1.87      lukem    1312:        }
                   1313: };
                   1314:
                   1315: void
1.88      lukem    1316: dohashstat(int verbose, int todo, const char *hashname)
1.101     sommerfe 1317: {
1.87      lukem    1318:        LIST_HEAD(, generic)    *hashtbl_list;
                   1319:        TAILQ_HEAD(, generic)   *hashtbl_tailq;
                   1320:        struct kernel_hash      *curhash;
1.118     itojun   1321:        void    *hashaddr, *hashbuf, *nhashbuf, *nextaddr;
1.87      lukem    1322:        size_t  elemsize, hashbufsize, thissize;
                   1323:        u_long  hashsize;
                   1324:        int     i, used, items, chain, maxchain;
                   1325:
                   1326:        hashbuf = NULL;
                   1327:        hashbufsize = 0;
1.88      lukem    1328:
                   1329:        if (todo & HASHLIST) {
1.90      lukem    1330:                printf("Supported hashes:\n");
                   1331:                for (curhash = khashes; curhash->description; curhash++) {
1.101     sommerfe 1332:                        if (hashnl[curhash->hashsize].n_value == 0 ||
1.90      lukem    1333:                            hashnl[curhash->hashtbl].n_value == 0)
                   1334:                                continue;
                   1335:                        printf("\t%-16s%s\n",
                   1336:                            hashnl[curhash->hashsize].n_name + 1,
                   1337:                            curhash->description);
1.88      lukem    1338:                }
                   1339:                return;
                   1340:        }
                   1341:
                   1342:        if (hashname != NULL) {
1.90      lukem    1343:                for (curhash = khashes; curhash->description; curhash++) {
                   1344:                        if (strcmp(hashnl[curhash->hashsize].n_name + 1,
                   1345:                            hashname) == 0 &&
1.101     sommerfe 1346:                            hashnl[curhash->hashsize].n_value != 0 &&
1.90      lukem    1347:                            hashnl[curhash->hashtbl].n_value != 0)
1.88      lukem    1348:                                break;
                   1349:                }
1.90      lukem    1350:                if (curhash->description == NULL) {
                   1351:                        warnx("%s: no such hash", hashname);
                   1352:                        return;
                   1353:                }
1.88      lukem    1354:        }
                   1355:
                   1356:        printf(
                   1357:            "%-16s %8s %8s %8s %8s %8s %8s\n"
                   1358:            "%-16s %8s %8s %8s %8s %8s %8s\n",
                   1359:            "", "total", "used", "util", "num", "average", "maximum",
                   1360:            "hash table", "buckets", "buckets", "%", "items", "chain",
                   1361:            "chain");
1.87      lukem    1362:
1.90      lukem    1363:        for (curhash = khashes; curhash->description; curhash++) {
1.101     sommerfe 1364:                if (hashnl[curhash->hashsize].n_value == 0 ||
1.90      lukem    1365:                    hashnl[curhash->hashtbl].n_value == 0)
                   1366:                        continue;
1.88      lukem    1367:                if (hashname != NULL &&
1.90      lukem    1368:                    strcmp(hashnl[curhash->hashsize].n_name + 1, hashname))
1.88      lukem    1369:                        continue;
1.87      lukem    1370:                elemsize = curhash->type == HASH_LIST ?
                   1371:                    sizeof(*hashtbl_list) : sizeof(*hashtbl_tailq);
1.90      lukem    1372:                deref_kptr((void *)hashnl[curhash->hashsize].n_value,
                   1373:                    &hashsize, sizeof(hashsize),
                   1374:                    hashnl[curhash->hashsize].n_name);
1.87      lukem    1375:                hashsize++;
1.90      lukem    1376:                deref_kptr((void *)hashnl[curhash->hashtbl].n_value,
                   1377:                    &hashaddr, sizeof(hashaddr),
                   1378:                    hashnl[curhash->hashtbl].n_name);
1.87      lukem    1379:                if (verbose)
1.91      jmc      1380:                        printf("%s %lu, %s %p, offset %ld, elemsize %llu\n",
1.90      lukem    1381:                            hashnl[curhash->hashsize].n_name + 1, hashsize,
                   1382:                            hashnl[curhash->hashtbl].n_name + 1, hashaddr,
1.101     sommerfe 1383:                            (long)curhash->offset,
1.91      jmc      1384:                            (unsigned long long)elemsize);
1.87      lukem    1385:                thissize = hashsize * elemsize;
                   1386:                if (thissize > hashbufsize) {
1.118     itojun   1387:                        if ((nhashbuf = realloc(hashbuf, thissize)) == NULL)
1.101     sommerfe 1388:                                errx(1, "malloc hashbuf %llu",
1.91      jmc      1389:                                    (unsigned long long)hashbufsize);
1.118     itojun   1390:                        hashbuf = nhashbuf;
                   1391:                        hashbufsize = thissize;
1.87      lukem    1392:                }
                   1393:                deref_kptr(hashaddr, hashbuf, thissize,
1.90      lukem    1394:                    hashnl[curhash->hashtbl].n_name);
1.87      lukem    1395:                used = 0;
                   1396:                items = maxchain = 0;
                   1397:                if (curhash->type == HASH_LIST)
                   1398:                        hashtbl_list = hashbuf;
                   1399:                else
                   1400:                        hashtbl_tailq = hashbuf;
                   1401:                for (i = 0; i < hashsize; i++) {
                   1402:                        if (curhash->type == HASH_LIST)
                   1403:                                nextaddr = LIST_FIRST(&hashtbl_list[i]);
                   1404:                        else
                   1405:                                nextaddr = TAILQ_FIRST(&hashtbl_tailq[i]);
                   1406:                        if (nextaddr == NULL)
                   1407:                                continue;
                   1408:                        if (verbose)
                   1409:                                printf("%5d: %p\n", i, nextaddr);
                   1410:                        used++;
                   1411:                        chain = 0;
                   1412:                        do {
                   1413:                                chain++;
                   1414:                                deref_kptr((char *)nextaddr + curhash->offset,
                   1415:                                    &nextaddr, sizeof(void *),
                   1416:                                    "hash chain corrupted");
                   1417:                                if (verbose > 1)
                   1418:                                        printf("got nextaddr as %p\n",
                   1419:                                            nextaddr);
                   1420:                        } while (nextaddr != NULL);
                   1421:                        items += chain;
                   1422:                        if (verbose && chain > 1)
                   1423:                                printf("\tchain = %d\n", chain);
                   1424:                        if (chain > maxchain)
                   1425:                                maxchain = chain;
                   1426:                }
1.93      lukem    1427:                printf("%-16s %8ld %8d %8.2f %8d %8.2f %8d\n",
1.90      lukem    1428:                    hashnl[curhash->hashsize].n_name + 1,
1.87      lukem    1429:                    hashsize, used, used * 100.0 / hashsize,
1.93      lukem    1430:                    items, used ? (double)items / used : 0.0, maxchain);
1.87      lukem    1431:        }
                   1432: }
                   1433:
1.1       cgd      1434: /*
1.90      lukem    1435:  * kread reads something from the kernel, given its nlist index in namelist[].
1.1       cgd      1436:  */
                   1437: void
1.73      simonb   1438: kread(int nlx, void *addr, size_t size)
1.1       cgd      1439: {
1.50      mycroft  1440:        const char *sym;
1.1       cgd      1441:
1.87      lukem    1442:        sym = namelist[nlx].n_name;
                   1443:        if (*sym == '_')
                   1444:                ++sym;
                   1445:        if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0)
                   1446:                errx(1, "symbol %s not defined", sym);
                   1447:        deref_kptr((void *)namelist[nlx].n_value, addr, size, sym);
                   1448: }
                   1449:
                   1450: /*
1.101     sommerfe 1451:  * Dereference the kernel pointer `kptr' and fill in the local copy
1.87      lukem    1452:  * pointed to by `ptr'.  The storage space must be pre-allocated,
                   1453:  * and the size of the copy passed in `len'.
                   1454:  */
                   1455: void
                   1456: deref_kptr(const void *kptr, void *ptr, size_t len, const char *msg)
                   1457: {
                   1458:
                   1459:        if (*msg == '_')
                   1460:                msg++;
                   1461:        if (kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len)
                   1462:                errx(1, "kptr %lx: %s: %s", (u_long)kptr, msg, kvm_geterr(kd));
1.1       cgd      1463: }
                   1464:
1.45      thorpej  1465: /*
                   1466:  * Traverse the UVM history buffers, performing the requested action.
                   1467:  *
                   1468:  * Note, we assume that if we're not listing, we're dumping.
                   1469:  */
                   1470: void
1.73      simonb   1471: hist_traverse(int todo, const char *histname)
1.45      thorpej  1472: {
                   1473:        struct uvm_history_head histhead;
                   1474:        struct uvm_history hist, *histkva;
                   1475:        char *name = NULL;
                   1476:        size_t namelen = 0;
                   1477:
1.90      lukem    1478:        if (histnl[0].n_value == 0) {
1.87      lukem    1479:                warnx("UVM history is not compiled into the kernel.");
1.45      thorpej  1480:                return;
                   1481:        }
                   1482:
1.87      lukem    1483:        deref_kptr((void *)histnl[X_UVM_HISTORIES].n_value, &histhead,
                   1484:            sizeof(histhead), histnl[X_UVM_HISTORIES].n_name);
1.45      thorpej  1485:
                   1486:        if (histhead.lh_first == NULL) {
1.87      lukem    1487:                warnx("No active UVM history logs.");
1.45      thorpej  1488:                return;
                   1489:        }
                   1490:
                   1491:        if (todo & HISTLIST)
                   1492:                printf("Active UVM histories:");
                   1493:
1.75      enami    1494:        for (histkva = LIST_FIRST(&histhead); histkva != NULL;
                   1495:            histkva = LIST_NEXT(&hist, list)) {
1.87      lukem    1496:                deref_kptr(histkva, &hist, sizeof(hist), "histkva");
1.45      thorpej  1497:                if (hist.namelen > namelen) {
                   1498:                        if (name != NULL)
                   1499:                                free(name);
                   1500:                        namelen = hist.namelen;
                   1501:                        if ((name = malloc(namelen + 1)) == NULL)
                   1502:                                err(1, "malloc history name");
                   1503:                }
                   1504:
1.87      lukem    1505:                deref_kptr(hist.name, name, namelen, "history name");
1.45      thorpej  1506:                name[namelen] = '\0';
                   1507:                if (todo & HISTLIST)
                   1508:                        printf(" %s", name);
                   1509:                else {
                   1510:                        /*
                   1511:                         * If we're dumping all histories, do it, else
                   1512:                         * check to see if this is the one we want.
                   1513:                         */
                   1514:                        if (histname == NULL || strcmp(histname, name) == 0) {
                   1515:                                if (histname == NULL)
                   1516:                                        printf("\nUVM history `%s':\n", name);
                   1517:                                hist_dodump(&hist);
                   1518:                        }
                   1519:                }
                   1520:        }
                   1521:
                   1522:        if (todo & HISTLIST)
1.87      lukem    1523:                putchar('\n');
1.45      thorpej  1524:
                   1525:        if (name != NULL)
                   1526:                free(name);
                   1527: }
                   1528:
                   1529: /*
                   1530:  * Actually dump the history buffer at the specified KVA.
                   1531:  */
                   1532: void
1.73      simonb   1533: hist_dodump(struct uvm_history *histp)
1.45      thorpej  1534: {
                   1535:        struct uvm_history_ent *histents, *e;
                   1536:        size_t histsize;
                   1537:        char *fmt = NULL, *fn = NULL;
                   1538:        size_t fmtlen = 0, fnlen = 0;
                   1539:        int i;
                   1540:
                   1541:        histsize = sizeof(struct uvm_history_ent) * histp->n;
                   1542:
                   1543:        if ((histents = malloc(histsize)) == NULL)
                   1544:                err(1, "malloc history entries");
                   1545:
                   1546:        memset(histents, 0, histsize);
                   1547:
1.87      lukem    1548:        deref_kptr(histp->e, histents, histsize, "history entries");
1.45      thorpej  1549:        i = histp->f;
                   1550:        do {
                   1551:                e = &histents[i];
                   1552:                if (e->fmt != NULL) {
                   1553:                        if (e->fmtlen > fmtlen) {
                   1554:                                if (fmt != NULL)
                   1555:                                        free(fmt);
                   1556:                                fmtlen = e->fmtlen;
                   1557:                                if ((fmt = malloc(fmtlen + 1)) == NULL)
                   1558:                                        err(1, "malloc printf format");
                   1559:                        }
                   1560:                        if (e->fnlen > fnlen) {
                   1561:                                if (fn != NULL)
                   1562:                                        free(fn);
                   1563:                                fnlen = e->fnlen;
                   1564:                                if ((fn = malloc(fnlen + 1)) == NULL)
                   1565:                                        err(1, "malloc function name");
                   1566:                        }
                   1567:
1.87      lukem    1568:                        deref_kptr(e->fmt, fmt, fmtlen, "printf format");
1.45      thorpej  1569:                        fmt[fmtlen] = '\0';
                   1570:
1.87      lukem    1571:                        deref_kptr(e->fn, fn, fnlen, "function name");
1.45      thorpej  1572:                        fn[fnlen] = '\0';
                   1573:
1.61      kleink   1574:                        printf("%06ld.%06ld ", (long int)e->tv.tv_sec,
                   1575:                            (long int)e->tv.tv_usec);
1.75      enami    1576:                        printf("%s#%ld: ", fn, e->call);
1.45      thorpej  1577:                        printf(fmt, e->v[0], e->v[1], e->v[2], e->v[3]);
1.87      lukem    1578:                        putchar('\n');
1.45      thorpej  1579:                }
                   1580:                i = (i + 1) % histp->n;
                   1581:        } while (i != histp->f);
                   1582:
                   1583:        free(histents);
                   1584:        if (fmt != NULL)
                   1585:                free(fmt);
                   1586:        if (fn != NULL)
                   1587:                free(fn);
                   1588: }
                   1589:
1.1       cgd      1590: void
1.73      simonb   1591: usage(void)
1.1       cgd      1592: {
1.47      mrg      1593:
1.1       cgd      1594:        (void)fprintf(stderr,
1.127     wiz      1595:            "usage: %s [-efHiLlmsUvW] [-c count] [-h hashname] [-M core] [-N system]\n"
                   1596:            "\t\t[-u histname] [-w wait] [disks]\n", getprogname());
1.1       cgd      1597:        exit(1);
                   1598: }

CVSweb <webmaster@jp.NetBSD.org>