date and time created 90/06/25 13:56:22 by bostic
[unix-history] / usr / src / usr.bin / vmstat / vmstat.c
index 3994d35..b3cba17 100644 (file)
-static char *sccsid = "@(#)vmstat.c    4.1 (Berkeley) %G%";
-#include <stdio.h>
+/*
+ * Copyright (c) 1980 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)vmstat.c   5.21 (Berkeley) %G%";
+#endif /* not lint */
+
 #include <sys/param.h>
 #include <sys/param.h>
+#include <sys/file.h>
 #include <sys/vm.h>
 #include <sys/vm.h>
-#include <sys/dk.h>
+#include <sys/dkstat.h>
+#include <sys/buf.h>
+#include <sys/namei.h>
+#include <sys/text.h>
+#include <sys/malloc.h>
+#include <stdio.h>
+#include <ctype.h>
 #include <nlist.h>
 #include <nlist.h>
+#include <paths.h>
 
 struct nlist nl[] = {
 
 struct nlist nl[] = {
-#define        X_DKBUSY 0
-       { "_dk_busy" },
-#define        X_DKTIME 1
-       { "_dk_time" },
-#define        X_DKNUMB 2
-       { "_dk_numb" },
-#define        X_RATE 3
+#define        X_CPTIME        0
+       { "_cp_time" },
+#define        X_RATE          1
        { "_rate" },
        { "_rate" },
-#define X_TOTAL 4
+#define X_TOTAL                2
        { "_total" },
        { "_total" },
-#define        X_DEFICIT 5
+#define        X_DEFICIT       3
        { "_deficit" },
        { "_deficit" },
-#define        X_FORKSTAT 6
+#define        X_FORKSTAT      4
        { "_forkstat" },
        { "_forkstat" },
-#define X_SUM 7
+#define X_SUM          5
        { "_sum" },
        { "_sum" },
-#define        X_FIRSTFREE 8
+#define        X_FIRSTFREE     6
        { "_firstfree" },
        { "_firstfree" },
-#define        X_MAXFREE 9
+#define        X_MAXFREE       7
        { "_maxfree" },
        { "_maxfree" },
-#define        X_BOOTIME 10
-       { "_bootime" },
-#ifdef ERNIE
-#define X_REC 10
+#define        X_BOOTTIME      8
+       { "_boottime" },
+#define        X_DKXFER        9
+       { "_dk_xfer" },
+#define X_REC          10
        { "_rectime" },
        { "_rectime" },
-#define X_PGIN 11
+#define X_PGIN         11
        { "_pgintime" },
        { "_pgintime" },
+#define X_HZ           12
+       { "_hz" },
+#define X_PHZ          13
+       { "_phz" },
+#define X_NCHSTATS     14
+       { "_nchstats" },
+#define        X_INTRNAMES     15
+       { "_intrnames" },
+#define        X_EINTRNAMES    16
+       { "_eintrnames" },
+#define        X_INTRCNT       17
+       { "_intrcnt" },
+#define        X_EINTRCNT      18
+       { "_eintrcnt" },
+#define        X_DK_NDRIVE     19
+       { "_dk_ndrive" },
+#define        X_XSTATS        20
+       { "_xstats" },
+#define        X_KMEMSTAT      21
+       { "_kmemstats" },
+#define        X_KMEMBUCKETS   22
+       { "_bucket" },
+#define X_END          22
+#ifdef vax
+#define X_MBDINIT      (X_END+1)
+       { "_mbdinit" },
+#define X_UBDINIT      (X_END+2)
+       { "_ubdinit" },
+#endif
+#ifdef tahoe
+#define        X_VBDINIT       (X_END+1)
+       { "_vbdinit" },
+#define        X_CKEYSTATS     (X_END+2)
+       { "_ckeystats" },
+#define        X_DKEYSTATS     (X_END+3)
+       { "_dkeystats" },
+#endif
+#ifdef hp300
+#define        X_HPDINIT       (X_END+1)
+       { "_hp_dinit" },
 #endif
 #endif
-       { 0 },
+       { "" },
 };
 
 };
 
+char   **dr_name;
+int    *dr_select;
+int    dk_ndrive;
+int    ndrives = 0;
+#ifdef vax
+char   *defdrives[] = { "hp0", "hp1", "hp2",  0 };
+#else
+#ifdef hp300
+char   *defdrives[] = { "rd0", "rd1", "rd2",  0 };
+#else
+char   *defdrives[] = { 0 };
+#endif
+#endif
 double stat1();
 int    firstfree, maxfree;
 double stat1();
 int    firstfree, maxfree;
-struct
-{
+int    hz;
+int    phz;
+int    HZ;
+
+struct {
        int     busy;
        int     busy;
-       long    etime[CPUSTATES][DK_NSTATES];
-       long    numb[DK_NDRIVE];
+       long    time[CPUSTATES];
+       long    *xfer;
        struct  vmmeter Rate;
        struct  vmtotal Total;
        struct  vmmeter Sum;
        struct  forkstat Forkstat;
        struct  vmmeter Rate;
        struct  vmtotal Total;
        struct  vmmeter Sum;
        struct  forkstat Forkstat;
-#ifdef ERNIE
        unsigned rectime;
        unsigned pgintime;
        unsigned rectime;
        unsigned pgintime;
-#endif
 } s, s1, z;
 #define        rate            s.Rate
 #define        total           s.Total
 #define        sum             s.Sum
 #define        forkstat        s.Forkstat
 
 } s, s1, z;
 #define        rate            s.Rate
 #define        total           s.Total
 #define        sum             s.Sum
 #define        forkstat        s.Forkstat
 
-int    iflag = 1;
-int    zero;
+struct vmmeter osum;
 int    deficit;
 double etime;
 int    mf;
 int    deficit;
 double etime;
 int    mf;
+time_t now, boottime;
+int    printhdr();
+int    lines = 1;
+
+#define        INTS(x) ((x) - (hz + phz))
 
 main(argc, argv)
 
 main(argc, argv)
-char **argv;
+       int argc;
+       char **argv;
 {
 {
-       time_t now;
-       int lines;
        extern char *ctime();
        extern char *ctime();
-       register i,j;
-       int iter, nintv;
-       time_t bootime;
-       double f1, f2;
+       register i;
+       int iter, nintv, iflag = 0;
        long t;
        long t;
-       extern char _sobuf[];
+       char *arg, **cp, buf[BUFSIZ];
 
 
-       setbuf(stdout, _sobuf);
-       nlist("/vmunix", nl);
+       nlist(_PATH_UNIX, nl);
        if(nl[0].n_type == 0) {
        if(nl[0].n_type == 0) {
-               printf("no /vmunix namelist\n");
+               fprintf(stderr, "vmstat: no %s namelist\n", _PATH_UNIX);
                exit(1);
        }
                exit(1);
        }
-       mf = open("/dev/kmem", 0);
+       mf = open(_PATH_KMEM, 0);
        if(mf < 0) {
        if(mf < 0) {
-               printf("cannot open /dev/kmem\n");
+               fprintf(stderr, "vmstat: cannot open %s\n", _PATH_KMEM);
                exit(1);
        }
        iter = 0;
                exit(1);
        }
        iter = 0;
@@ -95,15 +169,14 @@ char **argv;
                argc--;
                while (*++cp) switch (*cp) {
 
                argc--;
                while (*++cp) switch (*cp) {
 
-#ifdef ERNIE
                case 't':
                        dotimes();
                        exit(0);
                case 't':
                        dotimes();
                        exit(0);
-#endif
+
                case 'z':
                        close(mf);
                case 'z':
                        close(mf);
-                       mf = open("/dev/kmem", 2);
-                       lseek(mf, (long)nl[X_SUM].n_value, 0);
+                       mf = open(_PATH_KMEM, 2);
+                       lseek(mf, (long)nl[X_SUM].n_value, L_SET);
                        write(mf, &z.Sum, sizeof z.Sum);
                        exit(0);
 
                        write(mf, &z.Sum, sizeof z.Sum);
                        exit(0);
 
@@ -111,109 +184,153 @@ char **argv;
                        doforkst();
                        exit(0);
                
                        doforkst();
                        exit(0);
                
+               case 'm':
+                       domem();
+                       exit(0);
+
                case 's':
                        dosum();
                        exit(0);
 
                case 'i':
                case 's':
                        dosum();
                        exit(0);
 
                case 'i':
-                       iflag = 0;
+                       iflag++;
                        break;
 
                default:
                        break;
 
                default:
-                       fprintf(stderr, "usage: vmstat [ -fs ] [ interval ] [ count]\n");
+                       fprintf(stderr,
+                           "usage: vmstat [ -fsim ] [ interval ] [ count]\n");
                        exit(1);
                }
        }
                        exit(1);
                }
        }
-       if(argc > 1)
-               iter = atoi(argv[1]);
-       lseek(mf, (long)nl[X_FIRSTFREE].n_value, 0);
+       lseek(mf, (long)nl[X_FIRSTFREE].n_value, L_SET);
        read(mf, &firstfree, sizeof firstfree);
        read(mf, &firstfree, sizeof firstfree);
-       lseek(mf, (long)nl[X_MAXFREE].n_value, 0);
+       lseek(mf, (long)nl[X_MAXFREE].n_value, L_SET);
        read(mf, &maxfree, sizeof maxfree);
        read(mf, &maxfree, sizeof maxfree);
-       lseek(mf, (long)nl[X_BOOTIME].n_value, 0);
-       read(mf, &bootime, sizeof bootime);
+       lseek(mf, (long)nl[X_BOOTTIME].n_value, L_SET);
+       read(mf, &boottime, sizeof boottime);
+       lseek(mf, (long)nl[X_HZ].n_value, L_SET);
+       read(mf, &hz, sizeof hz);
+       if (nl[X_PHZ].n_value != 0) {
+               lseek(mf, (long)nl[X_PHZ].n_value, L_SET);
+               read(mf, &phz, sizeof phz);
+       }
+       HZ = phz ? phz : hz;
+       if (nl[X_DK_NDRIVE].n_value == 0) {
+               fprintf(stderr, "dk_ndrive undefined in system\n");
+               exit(1);
+       }
+       lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET);
+       read(mf, &dk_ndrive, sizeof (dk_ndrive));
+       if (dk_ndrive <= 0) {
+               fprintf(stderr, "dk_ndrive %d\n", dk_ndrive);
+               exit(1);
+       }
+       dr_select = (int *)calloc(dk_ndrive, sizeof (int));
+       dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
+#define        allocate(e, t) \
+    s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
+    s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
+       allocate(xfer, long);
+       for (arg = buf, i = 0; i < dk_ndrive; i++) {
+               dr_name[i] = arg;
+               sprintf(dr_name[i], "dk%d", i);
+               arg += strlen(dr_name[i]) + 1;
+       }
+       read_names();
        time(&now);
        time(&now);
-       nintv = now - bootime;
+       nintv = now - boottime;
        if (nintv <= 0 || nintv > 60*60*24*365*10) {
        if (nintv <= 0 || nintv > 60*60*24*365*10) {
-               printf("Time makes no sense... namelist must be wrong.\n");
+               fprintf(stderr,
+                   "Time makes no sense... namelist must be wrong.\n");
                exit(1);
        }
                exit(1);
        }
-reprint:
-       lines = 20;
-       /* s1 = z; */
-       if (iflag==0)
-printf("\
-      Procs  Virtual Real         Page        Swap         Disk             Cpu\n\
-RQ DW PW SW   AVM TX  FRE  RE AT PI PO FR  DE  SR I O  D0 D1 D2 D3  CS US SY ID\n\
-");
-       else
-printf("\
- Procs     Memory            Page        Swap         Disk  Faults          Cpu\n\
- R B W   AVM  FRE  RE AT PI PO FR  DE  SR I O  D0 D1 D2 D3  IN  SY  CS US SY ID\n\
-");
-loop:
-       lseek(mf, (long)nl[X_DKBUSY].n_value, 0);
-       read(mf, &s.busy, sizeof s.busy);
-       lseek(mf, (long)nl[X_DKTIME].n_value, 0);
-       read(mf, s.etime, sizeof s.etime);
-       lseek(mf, (long)nl[X_DKNUMB].n_value, 0);
-       read(mf, s.numb, sizeof s.numb);
-       if (nintv != 1) {
-               lseek(mf, (long)nl[X_SUM].n_value, 0);
-               read(mf, &rate, sizeof rate);
-       } else {
-               lseek(mf, (long)nl[X_RATE].n_value, 0);
-               read(mf, &rate, sizeof rate);
+       if (iflag) {
+               dointr(nintv);
+               exit(0);
+       }
+       /*
+        * Choose drives to be displayed.  Priority
+        * goes to (in order) drives supplied as arguments,
+        * default drives.  If everything isn't filled
+        * in and there are drives not taken care of,
+        * display the first few that fit.
+        */
+       ndrives = 0;
+       while (argc > 0 && !isdigit(argv[0][0])) {
+               for (i = 0; i < dk_ndrive; i++) {
+                       if (strcmp(dr_name[i], argv[0]))
+                               continue;
+                       dr_select[i] = 1;
+                       ndrives++;
+               }
+               argc--, argv++;
        }
        }
-       lseek(mf, (long)nl[X_TOTAL].n_value, 0);
+       for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
+               if (dr_select[i])
+                       continue;
+               for (cp = defdrives; *cp; cp++)
+                       if (strcmp(dr_name[i], *cp) == 0) {
+                               dr_select[i] = 1;
+                               ndrives++;
+                               break;
+                       }
+       }
+       for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
+               if (dr_select[i])
+                       continue;
+               dr_select[i] = 1;
+               ndrives++;
+       }
+       if (argc > 1)
+               iter = atoi(argv[1]);
+       signal(SIGCONT, printhdr);
+loop:
+       if (--lines == 0)
+               printhdr();
+       lseek(mf, (long)nl[X_CPTIME].n_value, L_SET);
+       read(mf, s.time, sizeof s.time);
+       lseek(mf, (long)nl[X_DKXFER].n_value, L_SET);
+       read(mf, s.xfer, dk_ndrive * sizeof (long));
+       if (nintv != 1)
+               lseek(mf, (long)nl[X_SUM].n_value, L_SET);
+       else
+               lseek(mf, (long)nl[X_RATE].n_value, L_SET);
+       read(mf, &rate, sizeof rate);
+       lseek(mf, (long)nl[X_TOTAL].n_value, L_SET);
        read(mf, &total, sizeof total);
        read(mf, &total, sizeof total);
-       lseek(mf, (long)nl[X_DEFICIT].n_value, 0);
+       osum = sum;
+       lseek(mf, (long)nl[X_SUM].n_value, L_SET);
+       read(mf, &sum, sizeof sum);
+       lseek(mf, (long)nl[X_DEFICIT].n_value, L_SET);
        read(mf, &deficit, sizeof deficit);
        read(mf, &deficit, sizeof deficit);
-       for (i=0; i < DK_NDRIVE; i++) {
-               t = s.numb[i];
-               s.numb[i] -= s1.numb[i];
-               s1.numb[i] = t;
+       etime = 0;
+       for (i=0; i < dk_ndrive; i++) {
+               t = s.xfer[i];
+               s.xfer[i] -= s1.xfer[i];
+               s1.xfer[i] = t;
        }
        for (i=0; i < CPUSTATES; i++) {
        }
        for (i=0; i < CPUSTATES; i++) {
-               for (j=0; j < DK_NSTATES; j++) {
-                       t = s.etime[i][j];
-                       s.etime[i][j] -= s1.etime[i][j];
-                       s1.etime[i][j] = t;
-               }
+               t = s.time[i];
+               s.time[i] -= s1.time[i];
+               s1.time[i] = t;
+               etime += s.time[i];
        }
        }
-       t = 0;
-       for (i=0; i < CPUSTATES; i++)
-               for (j=0; j < DK_NSTATES; j++)
-                       t += s.etime[i][j];
-       etime = t;
        if(etime == 0.)
                etime = 1.;
        if(etime == 0.)
                etime = 1.;
-       if (iflag)
-               printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw,
-                   total.t_sw);
-       else
-               printf("%2d%3d%3d%3d%3d", total.t_rq, total.t_dw, total.t_pw,
-                   total.t_sw);
-       if (iflag)
-               printf("%6d%5d", total.t_avm/2, total.t_free/2);
-       else
-               printf("%6d%3d%5d", total.t_avm/2,
-                   pct(total.t_avmtxt, total.t_avm), total.t_free/2);
-       printf("%4d%3d%3d",
-           (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
-           (rate.v_xsfrec+rate.v_xifrec)/nintv, rate.v_pgin/nintv);
-       printf("%3d%3d%4d%4.1f%2d%2d", rate.v_pgout/nintv,
-           rate.v_dfree/nintv, deficit/2,
-           (60.0 * rate.v_scan) / (LOOPSIZ*nintv),
-           rate.v_swpin/nintv, rate.v_swpout/nintv);
-       etime /= 60.;
-       printf(" ");
-       for(i=0; i<4; i++)
-               stats(i);
-       if (iflag)
-               printf("%4d%4d", (rate.v_intr/nintv) - HZ,
-                   rate.v_syscall/nintv);
-       printf("%4d", rate.v_swtch/nintv);
+       printf("%2d%2d%2d", total.t_rq, total.t_dw+total.t_pw, total.t_sw);
+#define pgtok(a) ((a)*NBPG/1024)
+       printf("%6d%6d", pgtok(total.t_avm), pgtok(total.t_free));
+       printf("%4d%3d", (rate.v_pgrec - (rate.v_xsfrec+rate.v_xifrec))/nintv,
+           (rate.v_xsfrec+rate.v_xifrec)/nintv);
+       printf("%4d", pgtok(rate.v_pgpgin)/nintv);
+       printf("%4d%4d%4d%4d", pgtok(rate.v_pgpgout)/nintv,
+           pgtok(rate.v_dfree)/nintv, pgtok(deficit), rate.v_scan/nintv);
+       etime /= (float)HZ;
+       for (i = 0; i < dk_ndrive; i++)
+               if (dr_select[i])
+                       stats(i);
+       printf("%4d%4d%4d", INTS(rate.v_intr/nintv), rate.v_syscall/nintv,
+           rate.v_swtch/nintv);
        for(i=0; i<CPUSTATES; i++) {
                float f = stat1(i);
                if (i == 0) {           /* US+NI */
        for(i=0; i<CPUSTATES; i++) {
                float f = stat1(i);
                if (i == 0) {           /* US+NI */
@@ -224,27 +341,44 @@ loop:
        }
        printf("\n");
        fflush(stdout);
        }
        printf("\n");
        fflush(stdout);
-contin:
        nintv = 1;
        nintv = 1;
-       --iter;
-       if(iter)
-       if(argc > 0) {
+       if (--iter &&argc > 0) {
                sleep(atoi(argv[0]));
                sleep(atoi(argv[0]));
-               if (--lines <= 0)
-                       goto reprint;
                goto loop;
        }
 }
 
                goto loop;
        }
 }
 
-#ifdef ERNIE
+printhdr()
+{
+       register int i, j;
+
+       printf(" procs     memory              page           ");
+       i = (ndrives * 3 - 6) / 2;
+       if (i < 0)
+               i = 0;
+       for (j = 0; j < i; j++)
+               putchar(' ');
+       printf("faults");
+       i = ndrives * 3 - 6 - i;
+       for (j = 0; j < i; j++)
+               putchar(' ');
+       printf("               cpu\n");
+       printf(" r b w   avm   fre  re at  pi  po  fr  de  sr ");
+       for (i = 0; i < dk_ndrive; i++)
+               if (dr_select[i])
+                       printf("%c%c ", dr_name[i][0], dr_name[i][2]);  
+       printf(" in  sy  cs us sy id\n");
+       lines = 19;
+}
+
 dotimes()
 {
 
 dotimes()
 {
 
-       lseek(mf, (long)nl[X_REC].n_value, 0);
+       lseek(mf, (long)nl[X_REC].n_value, L_SET);
        read(mf, &s.rectime, sizeof s.rectime);
        read(mf, &s.rectime, sizeof s.rectime);
-       lseek(mf, (long)nl[X_PGIN].n_value, 0);
+       lseek(mf, (long)nl[X_PGIN].n_value, L_SET);
        read(mf, &s.pgintime, sizeof s.pgintime);
        read(mf, &s.pgintime, sizeof s.pgintime);
-       lseek(mf, (long)nl[X_SUM].n_value, 0);
+       lseek(mf, (long)nl[X_SUM].n_value, L_SET);
        read(mf, &sum, sizeof sum);
        printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
        printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
        read(mf, &sum, sizeof sum);
        printf("%d reclaims, %d total time (usec)\n", sum.v_pgrec, s.rectime);
        printf("average: %d usec / reclaim\n", s.rectime/sum.v_pgrec);
@@ -252,12 +386,21 @@ dotimes()
        printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
        printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
 }
        printf("%d page ins, %d total time (msec)\n",sum.v_pgin, s.pgintime/10);
        printf("average: %8.1f msec / page in\n", s.pgintime/(sum.v_pgin*10.0));
 }
+
+#if defined(tahoe)
+#include <tahoe/cpu.h>
 #endif
 
 dosum()
 {
 #endif
 
 dosum()
 {
+       struct nchstats nchstats;
+       struct xstats xstats;
+       long nchtotal;
+#if defined(tahoe)
+       struct keystats keystats;
+#endif
 
 
-       lseek(mf, (long)nl[X_SUM].n_value, 0);
+       lseek(mf, (long)nl[X_SUM].n_value, L_SET);
        read(mf, &sum, sizeof sum);
        printf("%9d swap ins\n", sum.v_swpin);
        printf("%9d swap outs\n", sum.v_swpout);
        read(mf, &sum, sizeof sum);
        printf("%9d swap ins\n", sum.v_swpin);
        printf("%9d swap outs\n", sum.v_swpout);
@@ -266,7 +409,11 @@ dosum()
        printf("%9d total address trans. faults taken\n", sum.v_faults);
        printf("%9d page ins\n", sum.v_pgin);
        printf("%9d page outs\n", sum.v_pgout);
        printf("%9d total address trans. faults taken\n", sum.v_faults);
        printf("%9d page ins\n", sum.v_pgin);
        printf("%9d page outs\n", sum.v_pgout);
-       printf("%9d total reclaims\n", sum.v_pgrec);
+       printf("%9d pages paged in\n", sum.v_pgpgin);
+       printf("%9d pages paged out\n", sum.v_pgpgout);
+       printf("%9d sequential process pages freed\n", sum.v_seqfree);
+       printf("%9d total reclaims (%d%% fast)\n", sum.v_pgrec,
+           pct(sum.v_fastpgrec, sum.v_pgrec));
        printf("%9d reclaims from free list\n", sum.v_pgfrec);
        printf("%9d intransit blocking page faults\n", sum.v_intrans);
        printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
        printf("%9d reclaims from free list\n", sum.v_pgfrec);
        printf("%9d intransit blocking page faults\n", sum.v_intrans);
        printf("%9d zero fill pages created\n", sum.v_nzfod / CLSIZE);
@@ -282,16 +429,59 @@ dosum()
        printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
        printf("%9d cpu context switches\n", sum.v_swtch);
        printf("%9d device interrupts\n", sum.v_intr);
        printf("%9d pages freed by the clock daemon\n", sum.v_dfree / CLSIZE);
        printf("%9d cpu context switches\n", sum.v_swtch);
        printf("%9d device interrupts\n", sum.v_intr);
-       printf("%9d pseduo-dma dz interrupts\n", sum.v_pdma);
+       printf("%9d software interrupts\n", sum.v_soft);
+#ifdef vax
+       printf("%9d pseudo-dma dz interrupts\n", sum.v_pdma);
+#endif
        printf("%9d traps\n", sum.v_trap);
        printf("%9d system calls\n", sum.v_syscall);
        printf("%9d traps\n", sum.v_trap);
        printf("%9d system calls\n", sum.v_syscall);
+       lseek(mf, (long)nl[X_NCHSTATS].n_value, 0);
+       read(mf, &nchstats, sizeof nchstats);
+       nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
+           nchstats.ncs_badhits + nchstats.ncs_falsehits +
+           nchstats.ncs_miss + nchstats.ncs_long;
+       printf("%9d total name lookups\n", nchtotal);
+       printf("%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
+           "", pct(nchstats.ncs_goodhits, nchtotal),
+           pct(nchstats.ncs_neghits, nchtotal),
+           pct(nchstats.ncs_pass2, nchtotal));
+       printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
+           pct(nchstats.ncs_badhits, nchtotal),
+           pct(nchstats.ncs_falsehits, nchtotal),
+           pct(nchstats.ncs_long, nchtotal));
+       lseek(mf, (long)nl[X_XSTATS].n_value, 0);
+       read(mf, &xstats, sizeof xstats);
+       printf("%9d total calls to xalloc (cache hits %d%%)\n",
+           xstats.alloc, pct(xstats.alloc_cachehit, xstats.alloc));
+       printf("%9s sticky %d flushed %d unused %d\n", "",
+           xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
+       printf("%9d total calls to xfree", xstats.free);
+       printf(" (sticky %d cached %d swapped %d)\n",
+           xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
+#if defined(tahoe)
+       lseek(mf, (long)nl[X_CKEYSTATS].n_value, 0);
+       read(mf, &keystats, sizeof keystats);
+       printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
+           keystats.ks_allocs, "code cache keys allocated",
+           pct(keystats.ks_allocfree, keystats.ks_allocs),
+           pct(keystats.ks_norefs, keystats.ks_allocs),
+           pct(keystats.ks_taken, keystats.ks_allocs),
+           pct(keystats.ks_shared, keystats.ks_allocs));
+       lseek(mf, (long)nl[X_DKEYSTATS].n_value, 0);
+       read(mf, &keystats, sizeof keystats);
+       printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
+           keystats.ks_allocs, "data cache keys allocated",
+           pct(keystats.ks_allocfree, keystats.ks_allocs),
+           pct(keystats.ks_norefs, keystats.ks_allocs),
+           pct(keystats.ks_taken, keystats.ks_allocs),
+           pct(keystats.ks_shared, keystats.ks_allocs));
+#endif
 }
 
 }
 
-
 doforkst()
 {
 
 doforkst()
 {
 
-       lseek(mf, (long)nl[X_FORKSTAT].n_value, 0);
+       lseek(mf, (long)nl[X_FORKSTAT].n_value, L_SET);
        read(mf, &forkstat, sizeof forkstat);
        printf("%d forks, %d pages, average=%.2f\n",
                forkstat.cntfork, forkstat.sizfork,
        read(mf, &forkstat, sizeof forkstat);
        printf("%d forks, %d pages, average=%.2f\n",
                forkstat.cntfork, forkstat.sizfork,
@@ -304,32 +494,25 @@ doforkst()
 stats(dn)
 {
 
 stats(dn)
 {
 
-       if (dn >= DK_NDRIVE) {
+       if (dn >= dk_ndrive) {
                printf("  0");
                return;
        }
                printf("  0");
                return;
        }
-       printf("%3.0f", s.numb[dn]/etime);
+       printf("%3.0f", s.xfer[dn]/etime);
 }
 
 double
 stat1(row)
 {
 }
 
 double
 stat1(row)
 {
-       register i, j;
-       long t;
-       double f1, f2;
+       double t;
+       register i;
 
        t = 0;
        for(i=0; i<CPUSTATES; i++)
 
        t = 0;
        for(i=0; i<CPUSTATES; i++)
-               for(j=0; j<DK_NSTATES; j++)
-                       t += s.etime[i][j];
-       f1 = t;
-       if(f1 == 0.)
-               f1 = 1.;
-       t = 0;
-       for(j=0; j<DK_NSTATES; j++)
-               t += s.etime[row][j];
-       f2 = t;
-       return(f2*100./f1);
+               t += s.time[i];
+       if(t == 0.)
+               t = 1.;
+       return(s.time[row]*100./t);
 }
 
 pct(top, bot)
 }
 
 pct(top, bot)
@@ -339,3 +522,233 @@ pct(top, bot)
                return (0);
        return ((top * 100) / bot);
 }
                return (0);
        return ((top * 100) / bot);
 }
+
+dointr(nintv)
+{
+       int nintr, inttotal;
+       long *intrcnt;
+       char *intrname, *malloc();
+
+       nintr = (nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value) / sizeof(long);
+       intrcnt = (long *) malloc(nl[X_EINTRCNT].n_value -
+               nl[X_INTRCNT].n_value);
+       intrname = malloc(nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
+       if (intrcnt == NULL || intrname == NULL) {
+               fprintf(stderr, "vmstat: out of memory\n");
+               exit(9);
+       }
+       lseek(mf, (long)nl[X_INTRCNT].n_value, L_SET);
+       read(mf, intrcnt, nintr * sizeof (long));
+       lseek(mf, (long)nl[X_INTRNAMES].n_value, L_SET);
+       read(mf, intrname, nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value);
+       printf("interrupt      total      rate\n");
+       inttotal = 0;
+       while (nintr--) {
+               if (*intrcnt)
+                       printf("%-12s %8ld %8ld\n", intrname,
+                           *intrcnt, *intrcnt / nintv);
+               intrname += strlen(intrname) + 1;
+               inttotal += *intrcnt++;
+       }
+       printf("Total        %8ld %8ld\n", inttotal, inttotal / nintv);
+}
+
+/*
+ * These names must be kept in sync with
+ * the types defined in <sys/malloc.h>.
+ */
+char *kmemnames[] = {
+       "free",         /* 0 M_FREE */
+       "mbuf",         /* 1 M_MBUF */
+       "devbuf",       /* 2 M_DEVBUF */
+       "socket",       /* 3 M_SOCKET */
+       "pcb",          /* 4 M_PCB */
+       "routetbl",     /* 5 M_RTABLE */
+       "hosttbl",      /* 6 M_HTABLE */
+       "fragtbl",      /* 7 M_FTABLE */
+       "zombie",       /* 8 M_ZOMBIE */
+       "ifaddr",       /* 9 M_IFADDR */
+       "soopts",       /* 10 M_SOOPTS */
+       "soname",       /* 11 M_SONAME */
+       "namei",        /* 12 M_NAMEI */
+       "gprof",        /* 13 M_GPROF */
+       "ioctlops",     /* 14 M_IOCTLOPS */
+       "superblk",     /* 15 M_SUPERBLK */
+       "cred",         /* 16 M_CRED */
+       "pgrp",         /* 17 M_PGRP */
+       "session",      /* 18 M_SESSION */
+       "iov",          /* 19 M_IOV */
+       "mount",        /* 20 M_MOUNT */
+       "fhandle",      /* 21 M_FHANDLE */
+       "NFS req",      /* 22 M_NFSREQ */
+       "NFS mount",    /* 23 M_NFSMNT */
+       "vnodes",       /* 24 M_VNODE */
+       "namecache",    /* 25 M_CACHE */
+       "UFS quota",    /* 26 M_DQUOT */
+       "UFS mount",    /* 27 M_UFSMNT */
+       "mapmem",       /* 28 M_MAPMEM */
+       "shm",          /* 29 M_SHM */
+       0, 0, 0, 0,
+       0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0,
+       "temp",         /* 49 M_TEMP */
+};
+
+domem()
+{
+       struct kmemstats kmemstats[M_LAST];
+       struct kmembuckets buckets[MINBUCKET + 16];
+       register struct kmembuckets *kp;
+       register struct kmemstats *ks;
+       int i;
+
+       lseek(mf, (long)nl[X_KMEMBUCKETS].n_value, L_SET);
+       read(mf, buckets, sizeof buckets);
+       printf("Memory statistics by bucket size\n");
+       printf("    Size   In Use   Free   Requests  HighWater  Couldfree\n");
+       for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
+               if (kp->kb_calls == 0)
+                       continue;
+               printf("%8d%9d%7d%11d%8d%11d\n", 1 << i, 
+                       kp->kb_total - kp->kb_totalfree,
+                       kp->kb_totalfree, kp->kb_calls,
+                       kp->kb_highwat, kp->kb_couldfree);
+               
+       }
+       lseek(mf, (long)nl[X_KMEMSTAT].n_value, L_SET);
+       read(mf, kmemstats, sizeof kmemstats);
+       printf("Memory statistics by type\n");
+       printf("     Type   In Use  MemUse   HighUse  Limit  Requests %s\n",
+               "TypeLimit KernLimit");
+       for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
+               if (ks->ks_calls == 0)
+                       continue;
+               printf("%10s%7d%8dK%9dK%6dK%9d%7d%10d\n",
+                       kmemnames[i] ? kmemnames[i] : "undefined",
+                       ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
+                       (ks->ks_maxused + 1023) / 1024,
+                       (ks->ks_limit + 1023) / 1024, ks->ks_calls,
+                       ks->ks_limblocks, ks->ks_mapblocks);
+       }
+}
+
+#define steal(where, var) \
+       lseek(mf, where, L_SET); read(mf, &var, sizeof var);
+/*
+ * Read the drive names out of kmem.
+ */
+#ifdef vax
+#include <vaxuba/ubavar.h>
+#include <vaxmba/mbavar.h>
+
+read_names()
+{
+       struct mba_device mdev;
+       register struct mba_device *mp;
+       struct mba_driver mdrv;
+       short two_char;
+       char *cp = (char *) &two_char;
+       struct uba_device udev, *up;
+       struct uba_driver udrv;
+
+       mp = (struct mba_device *) nl[X_MBDINIT].n_value;
+       up = (struct uba_device *) nl[X_UBDINIT].n_value;
+       if (up == 0) {
+               fprintf(stderr, "vmstat: Disk init info not in namelist\n");
+               exit(1);
+       }
+       if (mp) for (;;) {
+               steal(mp++, mdev);
+               if (mdev.mi_driver == 0)
+                       break;
+               if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
+                       continue;
+               steal(mdev.mi_driver, mdrv);
+               steal(mdrv.md_dname, two_char);
+               sprintf(dr_name[mdev.mi_dk], "%c%c%d",
+                   cp[0], cp[1], mdev.mi_unit);
+       }
+       for (;;) {
+               steal(up++, udev);
+               if (udev.ui_driver == 0)
+                       break;
+               if (udev.ui_dk < 0 || udev.ui_alive == 0)
+                       continue;
+               steal(udev.ui_driver, udrv);
+               steal(udrv.ud_dname, two_char);
+               sprintf(dr_name[udev.ui_dk], "%c%c%d",
+                   cp[0], cp[1], udev.ui_unit);
+       }
+}
+#endif
+
+#ifdef tahoe
+#include <tahoevba/vbavar.h>
+
+/*
+ * Read the drive names out of kmem.
+ */
+read_names()
+{
+       struct vba_device udev, *up;
+       struct vba_driver udrv;
+       short two_char;
+       char *cp = (char *)&two_char;
+
+       up = (struct vba_device *) nl[X_VBDINIT].n_value;
+       if (up == 0) {
+               fprintf(stderr, "vmstat: Disk init info not in namelist\n");
+               exit(1);
+       }
+       for (;;) {
+               steal(up++, udev);
+               if (udev.ui_driver == 0)
+                       break;
+               if (udev.ui_dk < 0 || udev.ui_alive == 0)
+                       continue;
+               steal(udev.ui_driver, udrv);
+               steal(udrv.ud_dname, two_char);
+               sprintf(dr_name[udev.ui_dk], "%c%c%d",
+                    cp[0], cp[1], udev.ui_unit);
+       }
+}
+#endif
+
+#ifdef hp300
+#include <hpdev/device.h>
+
+#define validdisk(cp)  ((cp)[1] == 'd' && ((cp)[0] == 'r' || (cp)[0] == 's'))
+
+read_names()
+{
+       struct hp_device hdev;
+       register struct hp_device *hp;
+       struct driver hdrv;
+       short two_char;
+       char *cp = (char *) &two_char;
+       register char *dp;
+
+       hp = (struct hp_device *) nl[X_HPDINIT].n_value;
+       if (hp == 0) {
+               fprintf(stderr, "vmstat: Disk init info not in namelist\n");
+               exit(1);
+       }
+       for (;;) {
+               steal(hp++, hdev);
+               if (hdev.hp_driver == 0)
+                       break;
+               steal(hdev.hp_driver, hdrv);
+               steal(hdrv.d_name, two_char);
+               /*
+                * hp_dk is meaningless if the device isn't a disk
+                * (d_name not valid) or the disk was not found when
+                * booting (hp_alive == 0).
+                */
+               if (!validdisk(cp) || hdev.hp_alive == 0)
+                       continue;
+               dp = dr_name[hdev.hp_dk];
+               sprintf(dp, "%c%c%d", cp[0], cp[1], hdev.hp_unit);
+       }
+}
+#endif