home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1980, 1986, 1991 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
- #ifndef lint
- char copyright[] =
- "@(#) Copyright (c) 1980, 1986, 1991 The Regents of the University of California.\n\
- All rights reserved.\n";
- #endif /* not lint */
-
- #ifndef lint
- static char sccsid[] = "@(#)vmstat.c 5.31 (Berkeley) 7/2/91";
- #endif /* not lint */
-
- #include <sys/param.h>
- #include <sys/time.h>
- #include <sys/proc.h>
- #include <sys/user.h>
- #include <sys/dkstat.h>
- #include <sys/buf.h>
- #include <sys/namei.h>
- #include <sys/malloc.h>
- #include <sys/signal.h>
- #include <sys/fcntl.h>
- #include <sys/ioctl.h>
- #include <sys/vmmeter.h>
- #include <vm/vm.h>
- #include <vm/vm_statistics.h>
- #include <time.h>
- #include <nlist.h>
- #include <kvm.h>
- #include <errno.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- #include <paths.h>
-
- #define NEWVM /* XXX till old has been updated or purged */
- struct nlist nl[] = {
- #define X_CPTIME 0
- { "_cp_time" },
- #define X_TOTAL 1
- { "_total" },
- #define X_SUM 2
- { "_cnt" }, /* XXX for now that's where it is */
- #define X_BOOTTIME 3
- { "_boottime" },
- #define X_DKXFER 4
- { "_dk_xfer" },
- #define X_HZ 5
- { "_hz" },
- #define X_PHZ 6
- { "_phz" },
- #define X_NCHSTATS 7
- { "_nchstats" },
- #define X_INTRNAMES 8
- { "_intrnames" },
- #define X_EINTRNAMES 9
- { "_eintrnames" },
- #define X_INTRCNT 10
- { "_intrcnt" },
- #define X_EINTRCNT 11
- { "_eintrcnt" },
- #define X_DK_NDRIVE 12
- { "_dk_ndrive" },
- #define X_KMEMSTAT 13
- { "_kmemstats" },
- #define X_KMEMBUCKETS 14
- { "_bucket" },
- #define X_VMSTAT 15
- { "_vm_stat" },
- #ifdef notdef
- #define X_DEFICIT 15
- { "_deficit" },
- #define X_FORKSTAT 16
- { "_forkstat" },
- #define X_REC 17
- { "_rectime" },
- #define X_PGIN 18
- { "_pgintime" },
- #define X_XSTATS 19
- { "_xstats" },
- #define X_END 19
- #else
- #define X_END 15
- #endif
- #ifdef hp300
- #define X_HPDINIT (X_END+1)
- { "_hp_dinit" },
- #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 vax
- #define X_MBDINIT (X_END+1)
- { "_mbdinit" },
- #define X_UBDINIT (X_END+2)
- { "_ubdinit" },
- #endif
- { "" },
- };
-
- struct _disk {
- long time[CPUSTATES];
- long *xfer;
- } cur, last;
-
- struct vm_statistics vm_stat, ostat;
- struct vmmeter sum, osum;
- char *vmunix = _PATH_UNIX;
- char **dr_name;
- int *dr_select, dk_ndrive, ndrives;
-
- int winlines = 20;
-
- #define FORKSTAT 0x01
- #define INTRSTAT 0x02
- #define MEMSTAT 0x04
- #define SUMSTAT 0x08
- #define TIMESTAT 0x10
- #define VMSTAT 0x20
-
- #include "names.c" /* disk names -- machine dependent */
-
- void cpustats(), dkstats(), dointr(), domem(), dosum();
- void dovmstat(), kread(), usage();
- #ifdef notdef
- void dotimes(), doforkst();
- #endif
-
- main(argc, argv)
- register int argc;
- register char **argv;
- {
- extern int optind;
- extern char *optarg;
- register int c, todo;
- u_int interval;
- int reps;
- char *kmem;
-
- kmem = NULL;
- interval = reps = todo = 0;
- while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) {
- switch (c) {
- case 'c':
- reps = atoi(optarg);
- break;
- #ifndef notdef
- case 'f':
- todo |= FORKSTAT;
- break;
- #endif
- case 'i':
- todo |= INTRSTAT;
- break;
- case 'M':
- kmem = optarg;
- break;
- case 'm':
- todo |= MEMSTAT;
- break;
- case 'N':
- vmunix = optarg;
- break;
- case 's':
- todo |= SUMSTAT;
- break;
- #ifndef notdef
- case 't':
- todo |= TIMESTAT;
- break;
- #endif
- case 'w':
- interval = atoi(optarg);
- break;
- case '?':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- if (todo == 0)
- todo = VMSTAT;
-
- if (kvm_openfiles(vmunix, kmem, NULL) < 0) {
- (void)fprintf(stderr,
- "vmstat: kvm_openfiles: %s\n", kvm_geterr());
- exit(1);
- }
-
- if ((c = kvm_nlist(nl)) != 0) {
- if (c > 0) {
- (void)fprintf(stderr,
- "vmstat: undefined symbols in %s:", vmunix);
- for (c = 0; c < sizeof(nl)/sizeof(nl[0]); c++)
- if (nl[c].n_type == 0)
- printf(" %s", nl[c].n_name);
- (void)fputc('\n', stderr);
- } else
- (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
- kvm_geterr());
- exit(1);
- }
-
- if (todo & VMSTAT) {
- char **getdrivedata();
- struct winsize winsize;
-
- argv = getdrivedata(argv);
- winsize.ws_row = 0;
- (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
- if (winsize.ws_row > 0)
- winlines = winsize.ws_row;
-
- }
-
- #define BACKWARD_COMPATIBILITY
- #ifdef BACKWARD_COMPATIBILITY
- if (*argv) {
- interval = atoi(*argv);
- if (*++argv)
- reps = atoi(*argv);
- }
- #endif
-
- if (interval) {
- if (!reps)
- reps = -1;
- } else if (reps)
- interval = 1;
-
- #ifdef notdef
- if (todo & FORKSTAT)
- doforkst();
- #endif
- if (todo & MEMSTAT)
- domem();
- if (todo & SUMSTAT)
- dosum();
- #ifdef notdef
- if (todo & TIMESTAT)
- dotimes();
- #endif
- if (todo & INTRSTAT)
- dointr();
- if (todo & VMSTAT)
- dovmstat(interval, reps);
- exit(0);
- }
-
- char **
- getdrivedata(argv)
- char **argv;
- {
- register int i;
- register char **cp;
- char buf[30];
-
- kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive));
- if (dk_ndrive <= 0) {
- (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive);
- exit(1);
- }
- dr_select = calloc((size_t)dk_ndrive, sizeof(int));
- dr_name = calloc((size_t)dk_ndrive, sizeof(char *));
- for (i = 0; i < dk_ndrive; i++)
- dr_name[i] = NULL;
- cur.xfer = calloc((size_t)dk_ndrive, sizeof(long));
- last.xfer = calloc((size_t)dk_ndrive, sizeof(long));
- read_names();
- for (i = 0; i < dk_ndrive; i++)
- if (dr_name[i] == NULL) {
- (void)sprintf(buf, "??%d", i);
- dr_name[i] = strdup(buf);
- }
-
- /*
- * 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.
- */
- #define BACKWARD_COMPATIBILITY
- for (ndrives = 0; *argv; ++argv) {
- #ifdef BACKWARD_COMPATIBILITY
- if (isdigit(**argv))
- break;
- #endif
- for (i = 0; i < dk_ndrive; i++) {
- if (strcmp(dr_name[i], *argv))
- continue;
- dr_select[i] = 1;
- ++ndrives;
- break;
- }
- }
- 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;
- }
- return(argv);
- }
-
- long
- getuptime()
- {
- static time_t now, boottime;
- time_t uptime;
-
- if (boottime == 0)
- kread(X_BOOTTIME, &boottime, sizeof(boottime));
- (void)time(&now);
- uptime = now - boottime;
- if (uptime <= 0 || uptime > 60*60*24*365*10) {
- (void)fprintf(stderr,
- "vmstat: time makes no sense; namelist must be wrong.\n");
- exit(1);
- }
- return(uptime);
- }
-
- int hz, hdrcnt;
-
- void
- dovmstat(interval, reps)
- u_int interval;
- int reps;
- {
- struct vmtotal total;
- time_t uptime, halfuptime;
- void needhdr();
- #ifndef notdef
- int deficit;
- #endif
-
- uptime = getuptime();
- halfuptime = uptime / 2;
- (void)signal(SIGCONT, needhdr);
-
- if (nl[X_PHZ].n_type != 0 && nl[X_PHZ].n_value != 0)
- kread(X_PHZ, &hz, sizeof(hz));
- if (!hz)
- kread(X_HZ, &hz, sizeof(hz));
-
- for (hdrcnt = 1;;) {
- if (!--hdrcnt)
- printhdr();
- kread(X_CPTIME, cur.time, sizeof(cur.time));
- kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer * dk_ndrive));
- kread(X_SUM, &sum, sizeof(sum));
- kread(X_TOTAL, &total, sizeof(total));
- kread(X_VMSTAT, &vm_stat, sizeof(vm_stat));
- #ifdef notdef
- kread(X_DEFICIT, &deficit, sizeof(deficit));
- #endif
- (void)printf("%2d %1d %1d ",
- total.t_rq, total.t_dw + total.t_pw, total.t_sw);
- #define pgtok(a) ((a)*NBPG >> 10)
- #define rate(x) (((x) + halfuptime) / uptime) /* round */
- (void)printf("%5ld %5ld ",
- pgtok(total.t_avm), pgtok(total.t_free));
- #ifdef NEWVM
- (void)printf("%4lu ", rate(vm_stat.faults - ostat.faults));
- (void)printf("%3lu ",
- rate(vm_stat.reactivations - ostat.reactivations));
- (void)printf("%3lu ", rate(vm_stat.pageins - ostat.pageins));
- (void)printf("%3lu %3lu ",
- rate(vm_stat.pageouts - ostat.pageouts), 0);
- #else
- (void)printf("%3lu %2lu ",
- rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) -
- (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))),
- rate(sum.v_xsfrec + sum.v_xifrec -
- osum.v_xsfrec - osum.v_xifrec));
- (void)printf("%3lu ",
- rate(pgtok(sum.v_pgpgin - osum.v_pgpgin)));
- (void)printf("%3lu %3lu ",
- rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)),
- rate(pgtok(sum.v_dfree - osum.v_dfree)));
- (void)printf("%3d ", pgtok(deficit));
- #endif
- (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan));
- dkstats();
- (void)printf("%4lu %4lu %3lu ",
- rate(sum.v_intr - osum.v_intr),
- rate(sum.v_syscall - osum.v_syscall),
- rate(sum.v_swtch - osum.v_swtch));
- cpustats();
- (void)printf("\n");
- (void)fflush(stdout);
- if (reps >= 0 && --reps <= 0)
- break;
- osum = sum;
- ostat = vm_stat;
- uptime = interval;
- /*
- * We round upward to avoid losing low-frequency events
- * (i.e., >= 1 per interval but < 1 per second).
- */
- halfuptime = (uptime + 1) / 2;
- (void)sleep(interval);
- }
- }
-
- printhdr()
- {
- register int i;
-
- (void)printf(" procs memory page%*s", 20, "");
- if (ndrives > 1)
- (void)printf("disks %*s faults cpu\n",
- ndrives * 3 - 6, "");
- else
- (void)printf("%*s faults cpu\n", ndrives * 3, "");
- #ifndef NEWVM
- (void)printf(" r b w avm fre re at pi po fr de sr ");
- #else
- (void)printf(" r b w avm fre flt re pi po fr sr ");
- #endif
- for (i = 0; i < dk_ndrive; i++)
- if (dr_select[i])
- (void)printf("%c%c ", dr_name[i][0],
- dr_name[i][strlen(dr_name[i]) - 1]);
- (void)printf(" in sy cs us sy id\n");
- hdrcnt = winlines - 2;
- }
-
- /*
- * Force a header to be prepended to the next output.
- */
- void
- needhdr()
- {
-
- hdrcnt = 1;
- }
-
- #ifdef notdef
- void
- dotimes()
- {
- u_int pgintime, rectime;
-
- kread(X_REC, &rectime, sizeof(rectime));
- kread(X_PGIN, &pgintime, sizeof(pgintime));
- kread(X_SUM, &sum, sizeof(sum));
- (void)printf("%u reclaims, %u total time (usec)\n",
- sum.v_pgrec, rectime);
- (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec);
- (void)printf("\n");
- (void)printf("%u page ins, %u total time (msec)\n",
- sum.v_pgin, pgintime / 10);
- (void)printf("average: %8.1f msec / page in\n",
- pgintime / (sum.v_pgin * 10.0));
- }
- #endif
-
- pct(top, bot)
- long top, bot;
- {
- if (bot == 0)
- return(0);
- return((top * 100) / bot);
- }
-
- #define PCT(top, bot) pct((long)(top), (long)(bot))
-
- #if defined(tahoe)
- #include <machine/cpu.h>
- #endif
-
- void
- dosum()
- {
- struct nchstats nchstats;
- #ifndef NEWVM
- struct xstats xstats;
- #endif
- long nchtotal;
- #if defined(tahoe)
- struct keystats keystats;
- #endif
-
- kread(X_SUM, &sum, sizeof(sum));
- #ifdef NEWVM
- kread(X_VMSTAT, &vm_stat, sizeof(vm_stat));
- #else
- (void)printf("%9u swap ins\n", sum.v_swpin);
- (void)printf("%9u swap outs\n", sum.v_swpout);
- (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
- (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
- (void)printf("%9u total address trans. faults taken\n", sum.v_faults);
- (void)printf("%9u page ins\n", sum.v_pgin);
- (void)printf("%9u page outs\n", sum.v_pgout);
- (void)printf("%9u pages paged in\n", sum.v_pgpgin);
- (void)printf("%9u pages paged out\n", sum.v_pgpgout);
- (void)printf("%9u sequential process pages freed\n", sum.v_seqfree);
- (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec,
- PCT(sum.v_fastpgrec, sum.v_pgrec));
- (void)printf("%9u reclaims from free list\n", sum.v_pgfrec);
- (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
- (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
- (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
- (void)printf("%9u executable fill pages created\n",
- sum.v_nexfod / CLSIZE);
- (void)printf("%9u executable fill page faults\n",
- sum.v_exfod / CLSIZE);
- (void)printf("%9u swap text pages found in free list\n",
- sum.v_xsfrec);
- (void)printf("%9u inode text pages found in free list\n",
- sum.v_xifrec);
- (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE);
- (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE);
- (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
- (void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
- (void)printf("%9u pages freed by the clock daemon\n",
- sum.v_dfree / CLSIZE);
- #endif
- (void)printf("%9u cpu context switches\n", sum.v_swtch);
- (void)printf("%9u device interrupts\n", sum.v_intr);
- (void)printf("%9u software interrupts\n", sum.v_soft);
- #ifdef vax
- (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma);
- #endif
- (void)printf("%9u traps\n", sum.v_trap);
- (void)printf("%9u system calls\n", sum.v_syscall);
- #ifdef NEWVM
- (void)printf("%9u bytes per page\n", vm_stat.pagesize);
- (void)printf("%9u pages free\n", vm_stat.free_count);
- (void)printf("%9u pages active\n", vm_stat.active_count);
- (void)printf("%9u pages inactive\n", vm_stat.inactive_count);
- (void)printf("%9u pages wired down\n", vm_stat.wire_count);
- (void)printf("%9u zero-fill pages\n", vm_stat.zero_fill_count);
- (void)printf("%9u pages reactivated\n", vm_stat.reactivations);
- (void)printf("%9u pageins\n", vm_stat.pageins);
- (void)printf("%9u pageouts\n", vm_stat.pageouts);
- (void)printf("%9u VM faults\n", vm_stat.faults);
- (void)printf("%9u copy-on-write faults\n", vm_stat.cow_faults);
- (void)printf("%9u VM object cache lookups\n", vm_stat.lookups);
- (void)printf("%9u VM object hits\n", vm_stat.hits);
- #endif
-
- kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
- nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
- nchstats.ncs_badhits + nchstats.ncs_falsehits +
- nchstats.ncs_miss + nchstats.ncs_long;
- (void)printf("%9ld total name lookups\n", nchtotal);
- (void)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));
- (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
- PCT(nchstats.ncs_badhits, nchtotal),
- PCT(nchstats.ncs_falsehits, nchtotal),
- PCT(nchstats.ncs_long, nchtotal));
- #ifndef NEWVM
- kread(X_XSTATS, &xstats, sizeof(xstats));
- (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n",
- xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc));
- (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "",
- xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
- (void)printf("%9lu total calls to xfree", xstats.free);
- (void)printf(" (sticky %lu cached %lu swapped %lu)\n",
- xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
- #endif
- #if defined(tahoe)
- kread(X_CKEYSTATS, &keystats, sizeof(keystats));
- (void)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));
- kread(X_DKEYSTATS, &keystats, sizeof(keystats));
- (void)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
- }
-
- #ifdef notdef
- void
- doforkst()
- {
- struct forkstat fks;
-
- kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
- (void)printf("%d forks, %d pages, average %.2f\n",
- fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
- (void)printf("%d vforks, %d pages, average %.2f\n",
- fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork);
- }
- #endif
-
- void
- dkstats()
- {
- register int dn, state;
- double etime;
- long tmp;
-
- for (dn = 0; dn < dk_ndrive; ++dn) {
- tmp = cur.xfer[dn];
- cur.xfer[dn] -= last.xfer[dn];
- last.xfer[dn] = tmp;
- }
- etime = 0;
- for (state = 0; state < CPUSTATES; ++state) {
- tmp = cur.time[state];
- cur.time[state] -= last.time[state];
- last.time[state] = tmp;
- etime += cur.time[state];
- }
- if (etime == 0)
- etime = 1;
- etime /= hz;
- for (dn = 0; dn < dk_ndrive; ++dn) {
- if (!dr_select[dn])
- continue;
- (void)printf("%2.0f ", cur.xfer[dn] / etime);
- }
- }
-
- void
- cpustats()
- {
- register int state;
- double pct, total;
-
- total = 0;
- for (state = 0; state < CPUSTATES; ++state)
- total += cur.time[state];
- if (total)
- pct = 100 / total;
- else
- pct = 0;
- (void)printf("%2.0f ", /* user + nice */
- (cur.time[0] + cur.time[1]) * pct);
- (void)printf("%2.0f ", cur.time[2] * pct); /* system */
- (void)printf("%2.0f", cur.time[3] * pct); /* idle */
- }
-
- void
- dointr()
- {
- register long *intrcnt, inttotal, uptime;
- register int nintr, inamlen;
- register char *intrname;
-
- uptime = getuptime();
- nintr = nl[X_EINTRCNT].n_value - nl[X_INTRCNT].n_value;
- inamlen = nl[X_EINTRNAMES].n_value - nl[X_INTRNAMES].n_value;
- intrcnt = malloc((size_t)nintr);
- intrname = malloc((size_t)inamlen);
- if (intrcnt == NULL || intrname == NULL) {
- (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
- exit(1);
- }
- kread(X_INTRCNT, intrcnt, (size_t)nintr);
- kread(X_INTRNAMES, intrname, (size_t)inamlen);
- (void)printf("interrupt total rate\n");
- inttotal = 0;
- nintr /= sizeof(long);
- while (--nintr >= 0) {
- if (*intrcnt)
- (void)printf("%-12s %8ld %8ld\n", intrname,
- *intrcnt, *intrcnt / uptime);
- intrname += strlen(intrname) + 1;
- inttotal += *intrcnt++;
- }
- (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
- }
-
- /*
- * These names are defined in <sys/malloc.h>.
- */
- char *kmemnames[] = INITKMEMNAMES;
-
- void
- domem()
- {
- register struct kmembuckets *kp;
- register struct kmemstats *ks;
- register int i;
- int size;
- long totuse = 0, totfree = 0, totreq = 0;
- struct kmemstats kmemstats[M_LAST];
- struct kmembuckets buckets[MINBUCKET + 16];
-
- kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
- (void)printf("Memory statistics by bucket size\n");
- (void)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;
- size = 1 << i;
- (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
- kp->kb_total - kp->kb_totalfree,
- kp->kb_totalfree, kp->kb_calls,
- kp->kb_highwat, kp->kb_couldfree);
- totfree += size * kp->kb_totalfree;
- }
-
- kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
- (void)printf("\nMemory statistics by type\n");
- (void)printf(
- " Type In Use MemUse HighUse Limit Requests TypeLimit KernLimit\n");
- for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
- if (ks->ks_calls == 0)
- continue;
- (void)printf("%10s %6ld %7ldK %8ldK %5ldK %8ld %6u %9u\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);
- totuse += ks->ks_memuse;
- totreq += ks->ks_calls;
- }
- (void)printf("\nMemory Totals: In Use Free Requests\n");
- (void)printf(" %7ldK %6ldK %8ld\n",
- (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
- }
-
- /*
- * kread reads something from the kernel, given its nlist index.
- */
- void
- kread(nlx, addr, size)
- int nlx;
- void *addr;
- size_t size;
- {
- char *sym;
-
- if (nl[nlx].n_type == 0 || nl[nlx].n_value == 0) {
- sym = nl[nlx].n_name;
- if (*sym == '_')
- ++sym;
- (void)fprintf(stderr,
- "vmstat: %s: symbol %s not defined\n", vmunix, sym);
- exit(1);
- }
- if (kvm_read((void *)nl[nlx].n_value, addr, size) != size) {
- sym = nl[nlx].n_name;
- if (*sym == '_')
- ++sym;
- (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr());
- exit(1);
- }
- }
-
- void
- usage()
- {
- (void)fprintf(stderr,
- #ifndef NEWVM
- "usage: vmstat [-fimst] [-c count] [-M core] \
- [-N system] [-w wait] [disks]\n");
- #else
- "usage: vmstat [-ims] [-c count] [-M core] \
- [-N system] [-w wait] [disks]\n");
- #endif
- exit(1);
- }
-