121585Sdist /*
262431Sbostic * Copyright (c) 1980, 1986, 1991, 1993
362431Sbostic * The Regents of the University of California. All rights reserved.
436580Sbostic *
542784Sbostic * %sccs.include.redist.c%
621585Sdist */
721585Sdist
810826Ssam #ifndef lint
962431Sbostic static char copyright[] =
1062431Sbostic "@(#) Copyright (c) 1980, 1986, 1991, 1993\n\
1162431Sbostic The Regents of the University of California. All rights reserved.\n";
1236580Sbostic #endif /* not lint */
1310826Ssam
1421585Sdist #ifndef lint
15*68469Smckusick static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 03/01/95";
1636580Sbostic #endif /* not lint */
1721585Sdist
181155Sbill #include <sys/param.h>
1950004Skarels #include <sys/time.h>
2050004Skarels #include <sys/proc.h>
2146892Sbostic #include <sys/user.h>
2229664Ssam #include <sys/dkstat.h>
233162Stoy #include <sys/buf.h>
2417262Smckusick #include <sys/namei.h>
2533610Smckusick #include <sys/malloc.h>
2650004Skarels #include <sys/signal.h>
2750004Skarels #include <sys/fcntl.h>
2850004Skarels #include <sys/ioctl.h>
2958904Smckusick #include <sys/sysctl.h>
3050103Skarels #include <vm/vm.h>
3148570Sbostic #include <time.h>
3248570Sbostic #include <nlist.h>
3348570Sbostic #include <kvm.h>
3445834Sbostic #include <errno.h>
3548570Sbostic #include <unistd.h>
3645834Sbostic #include <stdio.h>
3748570Sbostic #include <ctype.h>
3845834Sbostic #include <stdlib.h>
3945834Sbostic #include <string.h>
4037912Sbostic #include <paths.h>
4154272Smccanne #include <limits.h>
421155Sbill
4350103Skarels #define NEWVM /* XXX till old has been updated or purged */
4456572Sbostic struct nlist namelist[] = {
451448Sbill #define X_CPTIME 0
461448Sbill { "_cp_time" },
4751359Smckusick #define X_DK_NDRIVE 1
4851359Smckusick { "_dk_ndrive" },
4950006Skarels #define X_SUM 2
5051359Smckusick { "_cnt" },
5150006Skarels #define X_BOOTTIME 3
529249Ssam { "_boottime" },
5350006Skarels #define X_DKXFER 4
541448Sbill { "_dk_xfer" },
5550006Skarels #define X_HZ 5
563162Stoy { "_hz" },
5754272Smccanne #define X_STATHZ 6
5854272Smccanne { "_stathz" },
5950006Skarels #define X_NCHSTATS 7
6015807Smckusick { "_nchstats" },
6150006Skarels #define X_INTRNAMES 8
6217262Smckusick { "_intrnames" },
6350006Skarels #define X_EINTRNAMES 9
6417262Smckusick { "_eintrnames" },
6550006Skarels #define X_INTRCNT 10
6617262Smckusick { "_intrcnt" },
6750006Skarels #define X_EINTRCNT 11
6817262Smckusick { "_eintrcnt" },
6951359Smckusick #define X_KMEMSTAT 12
7033610Smckusick { "_kmemstats" },
7151359Smckusick #define X_KMEMBUCKETS 13
7233610Smckusick { "_bucket" },
7350103Skarels #ifdef notdef
7451359Smckusick #define X_DEFICIT 14
7550004Skarels { "_deficit" },
7651359Smckusick #define X_FORKSTAT 15
7750004Skarels { "_forkstat" },
7851359Smckusick #define X_REC 16
7950004Skarels { "_rectime" },
8051359Smckusick #define X_PGIN 17
8150004Skarels { "_pgintime" },
8251359Smckusick #define X_XSTATS 18
8350004Skarels { "_xstats" },
8451359Smckusick #define X_END 18
8550103Skarels #else
8651359Smckusick #define X_END 14
8750004Skarels #endif
8856176Sbostic #if defined(hp300) || defined(luna68k)
8951359Smckusick #define X_HPDINIT (X_END)
9048570Sbostic { "_hp_dinit" },
9110826Ssam #endif
9258837Sralph #ifdef mips
9358837Sralph #define X_SCSI_DINIT (X_END)
9458837Sralph { "_scsi_dinit" },
9558837Sralph #endif
9625708Ssam #ifdef tahoe
9751359Smckusick #define X_VBDINIT (X_END)
9825708Ssam { "_vbdinit" },
9951359Smckusick #define X_CKEYSTATS (X_END+1)
10025960Ssam { "_ckeystats" },
10151359Smckusick #define X_DKEYSTATS (X_END+2)
10225960Ssam { "_dkeystats" },
10325708Ssam #endif
10448570Sbostic #ifdef vax
10551359Smckusick #define X_MBDINIT (X_END)
10648570Sbostic { "_mbdinit" },
10751359Smckusick #define X_UBDINIT (X_END+1)
10848570Sbostic { "_ubdinit" },
10942952Sbostic #endif
11010826Ssam { "" },
1111155Sbill };
1121155Sbill
11348570Sbostic struct _disk {
11448570Sbostic long time[CPUSTATES];
11548570Sbostic long *xfer;
11648570Sbostic } cur, last;
11718761Ssam
11850006Skarels struct vmmeter sum, osum;
11950004Skarels char **dr_name;
12050004Skarels int *dr_select, dk_ndrive, ndrives;
1211155Sbill
12250004Skarels int winlines = 20;
12350004Skarels
12454272Smccanne kvm_t *kd;
12554272Smccanne
12645834Sbostic #define FORKSTAT 0x01
12745834Sbostic #define INTRSTAT 0x02
12845834Sbostic #define MEMSTAT 0x04
12945834Sbostic #define SUMSTAT 0x08
13045834Sbostic #define TIMESTAT 0x10
13145834Sbostic #define VMSTAT 0x20
13245834Sbostic
13348570Sbostic #include "names.c" /* disk names -- machine dependent */
13448570Sbostic
13550004Skarels void cpustats(), dkstats(), dointr(), domem(), dosum();
13650103Skarels void dovmstat(), kread(), usage();
13750103Skarels #ifdef notdef
13850004Skarels void dotimes(), doforkst();
13950004Skarels #endif
14048570Sbostic
main(argc,argv)1411155Sbill main(argc, argv)
14245834Sbostic register int argc;
14345834Sbostic register char **argv;
1441155Sbill {
14545834Sbostic extern int optind;
14645834Sbostic extern char *optarg;
14748570Sbostic register int c, todo;
14848570Sbostic u_int interval;
14948570Sbostic int reps;
15052243Sbostic char *memf, *nlistf;
15154272Smccanne char errbuf[_POSIX2_LINE_MAX];
1521155Sbill
15352243Sbostic memf = nlistf = NULL;
15448570Sbostic interval = reps = todo = 0;
15550103Skarels while ((c = getopt(argc, argv, "c:fiM:mN:stw:")) != EOF) {
15645834Sbostic switch (c) {
15748570Sbostic case 'c':
15848570Sbostic reps = atoi(optarg);
15948570Sbostic break;
16050103Skarels #ifndef notdef
16145834Sbostic case 'f':
16245834Sbostic todo |= FORKSTAT;
16345834Sbostic break;
16450004Skarels #endif
16545834Sbostic case 'i':
16645834Sbostic todo |= INTRSTAT;
16745834Sbostic break;
16848570Sbostic case 'M':
16952243Sbostic memf = optarg;
17045834Sbostic break;
17145834Sbostic case 'm':
17245834Sbostic todo |= MEMSTAT;
17345834Sbostic break;
17448570Sbostic case 'N':
17552243Sbostic nlistf = optarg;
17648570Sbostic break;
17745834Sbostic case 's':
17845834Sbostic todo |= SUMSTAT;
17945834Sbostic break;
18050103Skarels #ifndef notdef
18145834Sbostic case 't':
18245834Sbostic todo |= TIMESTAT;
18345834Sbostic break;
18450004Skarels #endif
18548570Sbostic case 'w':
18648570Sbostic interval = atoi(optarg);
18745834Sbostic break;
18845834Sbostic case '?':
18948570Sbostic default:
19045834Sbostic usage();
19145834Sbostic }
19245834Sbostic }
19348570Sbostic argc -= optind;
19448570Sbostic argv += optind;
19545834Sbostic
19645834Sbostic if (todo == 0)
19745834Sbostic todo = VMSTAT;
19845834Sbostic
19952243Sbostic /*
20052243Sbostic * Discard setgid privileges if not the running kernel so that bad
20152243Sbostic * guys can't print interesting stuff from kernel memory.
20252243Sbostic */
20352243Sbostic if (nlistf != NULL || memf != NULL)
20452243Sbostic setgid(getgid());
20552243Sbostic
20654272Smccanne kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
20754272Smccanne if (kd == 0) {
20848570Sbostic (void)fprintf(stderr,
20954272Smccanne "vmstat: kvm_openfiles: %s\n", errbuf);
2101155Sbill exit(1);
2111155Sbill }
21245834Sbostic
21356572Sbostic if ((c = kvm_nlist(kd, namelist)) != 0) {
21450004Skarels if (c > 0) {
21550004Skarels (void)fprintf(stderr,
21658837Sralph "vmstat: undefined symbols:");
21756572Sbostic for (c = 0;
21856572Sbostic c < sizeof(namelist)/sizeof(namelist[0]); c++)
21956572Sbostic if (namelist[c].n_type == 0)
22058837Sralph fprintf(stderr, " %s",
22158837Sralph namelist[c].n_name);
22250004Skarels (void)fputc('\n', stderr);
22350004Skarels } else
22450004Skarels (void)fprintf(stderr, "vmstat: kvm_nlist: %s\n",
22554272Smccanne kvm_geterr(kd));
2261155Sbill exit(1);
2271155Sbill }
2281155Sbill
22948570Sbostic if (todo & VMSTAT) {
23048570Sbostic char **getdrivedata();
23150004Skarels struct winsize winsize;
23248570Sbostic
23348570Sbostic argv = getdrivedata(argv);
23450004Skarels winsize.ws_row = 0;
23550004Skarels (void) ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&winsize);
23650004Skarels if (winsize.ws_row > 0)
23750004Skarels winlines = winsize.ws_row;
23850004Skarels
23948570Sbostic }
24048570Sbostic
24148570Sbostic #define BACKWARD_COMPATIBILITY
24248570Sbostic #ifdef BACKWARD_COMPATIBILITY
24348570Sbostic if (*argv) {
24448570Sbostic interval = atoi(*argv);
24548570Sbostic if (*++argv)
24648570Sbostic reps = atoi(*argv);
24748570Sbostic }
24848570Sbostic #endif
24948570Sbostic
25048613Sbostic if (interval) {
25148613Sbostic if (!reps)
25248613Sbostic reps = -1;
25350103Skarels } else if (reps)
25450103Skarels interval = 1;
25548613Sbostic
25650103Skarels #ifdef notdef
25745834Sbostic if (todo & FORKSTAT)
25845834Sbostic doforkst();
25950004Skarels #endif
26045834Sbostic if (todo & MEMSTAT)
26145834Sbostic domem();
26245834Sbostic if (todo & SUMSTAT)
26345834Sbostic dosum();
26450103Skarels #ifdef notdef
26545834Sbostic if (todo & TIMESTAT)
26645834Sbostic dotimes();
26750004Skarels #endif
26845834Sbostic if (todo & INTRSTAT)
26945834Sbostic dointr();
27048570Sbostic if (todo & VMSTAT)
27148570Sbostic dovmstat(interval, reps);
27245834Sbostic exit(0);
27345834Sbostic }
27410826Ssam
27548570Sbostic char **
getdrivedata(argv)27648570Sbostic getdrivedata(argv)
27745834Sbostic char **argv;
27845834Sbostic {
27945834Sbostic register int i;
28045834Sbostic register char **cp;
28145834Sbostic char buf[30];
28245834Sbostic
28348570Sbostic kread(X_DK_NDRIVE, &dk_ndrive, sizeof(dk_ndrive));
28418761Ssam if (dk_ndrive <= 0) {
28548570Sbostic (void)fprintf(stderr, "vmstat: dk_ndrive %d\n", dk_ndrive);
28618761Ssam exit(1);
28718761Ssam }
28848570Sbostic dr_select = calloc((size_t)dk_ndrive, sizeof(int));
28948570Sbostic dr_name = calloc((size_t)dk_ndrive, sizeof(char *));
29045834Sbostic for (i = 0; i < dk_ndrive; i++)
29145834Sbostic dr_name[i] = NULL;
29248570Sbostic cur.xfer = calloc((size_t)dk_ndrive, sizeof(long));
29348570Sbostic last.xfer = calloc((size_t)dk_ndrive, sizeof(long));
29455663Sbostic if (!read_names())
29555663Sbostic exit (1);
29648570Sbostic for (i = 0; i < dk_ndrive; i++)
29745834Sbostic if (dr_name[i] == NULL) {
29848570Sbostic (void)sprintf(buf, "??%d", i);
29945834Sbostic dr_name[i] = strdup(buf);
30045834Sbostic }
30145834Sbostic
30218761Ssam /*
30348570Sbostic * Choose drives to be displayed. Priority goes to (in order) drives
30448570Sbostic * supplied as arguments, default drives. If everything isn't filled
30548570Sbostic * in and there are drives not taken care of, display the first few
30648570Sbostic * that fit.
30718761Ssam */
30848570Sbostic #define BACKWARD_COMPATIBILITY
30948570Sbostic for (ndrives = 0; *argv; ++argv) {
31048570Sbostic #ifdef BACKWARD_COMPATIBILITY
31148570Sbostic if (isdigit(**argv))
31248570Sbostic break;
31348570Sbostic #endif
31418761Ssam for (i = 0; i < dk_ndrive; i++) {
31548570Sbostic if (strcmp(dr_name[i], *argv))
31618761Ssam continue;
31718761Ssam dr_select[i] = 1;
31848570Sbostic ++ndrives;
31945834Sbostic break;
32018761Ssam }
32118761Ssam }
32218761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
32318761Ssam if (dr_select[i])
32418761Ssam continue;
32518761Ssam for (cp = defdrives; *cp; cp++)
32618761Ssam if (strcmp(dr_name[i], *cp) == 0) {
32718761Ssam dr_select[i] = 1;
32848570Sbostic ++ndrives;
32918761Ssam break;
33018761Ssam }
33118761Ssam }
33218761Ssam for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
33318761Ssam if (dr_select[i])
33418761Ssam continue;
33518761Ssam dr_select[i] = 1;
33648570Sbostic ++ndrives;
33718761Ssam }
33848570Sbostic return(argv);
33945834Sbostic }
34045834Sbostic
34145834Sbostic long
getuptime()34245834Sbostic getuptime()
34345834Sbostic {
34448570Sbostic static time_t now, boottime;
34548570Sbostic time_t uptime;
34645834Sbostic
34745834Sbostic if (boottime == 0)
34848570Sbostic kread(X_BOOTTIME, &boottime, sizeof(boottime));
34948570Sbostic (void)time(&now);
35045834Sbostic uptime = now - boottime;
35145834Sbostic if (uptime <= 0 || uptime > 60*60*24*365*10) {
35248570Sbostic (void)fprintf(stderr,
35345834Sbostic "vmstat: time makes no sense; namelist must be wrong.\n");
35445834Sbostic exit(1);
35545834Sbostic }
35648570Sbostic return(uptime);
35745834Sbostic }
35845834Sbostic
35950006Skarels int hz, hdrcnt;
36048613Sbostic
36148570Sbostic void
dovmstat(interval,reps)36248570Sbostic dovmstat(interval, reps)
36348570Sbostic u_int interval;
36448570Sbostic int reps;
36545834Sbostic {
36648570Sbostic struct vmtotal total;
36750103Skarels time_t uptime, halfuptime;
36850004Skarels void needhdr();
36958904Smckusick int mib[2], size;
37045834Sbostic
37148570Sbostic uptime = getuptime();
37250103Skarels halfuptime = uptime / 2;
37350004Skarels (void)signal(SIGCONT, needhdr);
37448570Sbostic
37556572Sbostic if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0)
37654272Smccanne kread(X_STATHZ, &hz, sizeof(hz));
37748613Sbostic if (!hz)
37848613Sbostic kread(X_HZ, &hz, sizeof(hz));
37948570Sbostic
38048570Sbostic for (hdrcnt = 1;;) {
38150004Skarels if (!--hdrcnt)
38248570Sbostic printhdr();
38348570Sbostic kread(X_CPTIME, cur.time, sizeof(cur.time));
38456107Sbostic kread(X_DKXFER, cur.xfer, sizeof(*cur.xfer) * dk_ndrive);
38550006Skarels kread(X_SUM, &sum, sizeof(sum));
38651359Smckusick size = sizeof(total);
38758904Smckusick mib[0] = CTL_VM;
38858904Smckusick mib[1] = VM_METER;
38958904Smckusick if (sysctl(mib, 2, &total, &size, NULL, 0) < 0) {
39051359Smckusick printf("Can't get kerninfo: %s\n", strerror(errno));
39151359Smckusick bzero(&total, sizeof(total));
39251359Smckusick }
39351359Smckusick (void)printf("%2d%2d%2d",
39459818Smckusick total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw);
39551359Smckusick #define pgtok(a) ((a) * sum.v_page_size >> 10)
39650103Skarels #define rate(x) (((x) + halfuptime) / uptime) /* round */
39751359Smckusick (void)printf("%6ld%6ld ",
39848570Sbostic pgtok(total.t_avm), pgtok(total.t_free));
39950006Skarels #ifdef NEWVM
40051359Smckusick (void)printf("%4lu ", rate(sum.v_faults - osum.v_faults));
40150006Skarels (void)printf("%3lu ",
40251359Smckusick rate(sum.v_reactivated - osum.v_reactivated));
40351359Smckusick (void)printf("%3lu ", rate(sum.v_pageins - osum.v_pageins));
40450006Skarels (void)printf("%3lu %3lu ",
40551359Smckusick rate(sum.v_pageouts - osum.v_pageouts), 0);
40650006Skarels #else
40750006Skarels (void)printf("%3lu %2lu ",
40850103Skarels rate(sum.v_pgrec - (sum.v_xsfrec+sum.v_xifrec) -
40950103Skarels (osum.v_pgrec - (osum.v_xsfrec+osum.v_xifrec))),
41050103Skarels rate(sum.v_xsfrec + sum.v_xifrec -
41150103Skarels osum.v_xsfrec - osum.v_xifrec));
41250006Skarels (void)printf("%3lu ",
41350103Skarels rate(pgtok(sum.v_pgpgin - osum.v_pgpgin)));
41450006Skarels (void)printf("%3lu %3lu ",
41550103Skarels rate(pgtok(sum.v_pgpgout - osum.v_pgpgout)),
41650103Skarels rate(pgtok(sum.v_dfree - osum.v_dfree)));
41750006Skarels (void)printf("%3d ", pgtok(deficit));
41850006Skarels #endif
41950103Skarels (void)printf("%3lu ", rate(sum.v_scan - osum.v_scan));
42048613Sbostic dkstats();
42150006Skarels (void)printf("%4lu %4lu %3lu ",
42250103Skarels rate(sum.v_intr - osum.v_intr),
42350103Skarels rate(sum.v_syscall - osum.v_syscall),
42450103Skarels rate(sum.v_swtch - osum.v_swtch));
42548613Sbostic cpustats();
42648570Sbostic (void)printf("\n");
42748570Sbostic (void)fflush(stdout);
42848613Sbostic if (reps >= 0 && --reps <= 0)
42948570Sbostic break;
43050006Skarels osum = sum;
43150103Skarels uptime = interval;
43250103Skarels /*
43350103Skarels * We round upward to avoid losing low-frequency events
43450103Skarels * (i.e., >= 1 per interval but < 1 per second).
43550103Skarels */
43650103Skarels halfuptime = (uptime + 1) / 2;
43748613Sbostic (void)sleep(interval);
4381155Sbill }
4391155Sbill }
4401155Sbill
printhdr()44117262Smckusick printhdr()
44217262Smckusick {
44348570Sbostic register int i;
44418761Ssam
44550006Skarels (void)printf(" procs memory page%*s", 20, "");
44648570Sbostic if (ndrives > 1)
44750006Skarels (void)printf("disks %*s faults cpu\n",
44848570Sbostic ndrives * 3 - 6, "");
44948570Sbostic else
45050006Skarels (void)printf("%*s faults cpu\n", ndrives * 3, "");
45150006Skarels #ifndef NEWVM
45248570Sbostic (void)printf(" r b w avm fre re at pi po fr de sr ");
45350006Skarels #else
45450006Skarels (void)printf(" r b w avm fre flt re pi po fr sr ");
45550006Skarels #endif
45618761Ssam for (i = 0; i < dk_ndrive; i++)
45718761Ssam if (dr_select[i])
45848570Sbostic (void)printf("%c%c ", dr_name[i][0],
45945834Sbostic dr_name[i][strlen(dr_name[i]) - 1]);
46050006Skarels (void)printf(" in sy cs us sy id\n");
46150004Skarels hdrcnt = winlines - 2;
46217262Smckusick }
46317262Smckusick
46450004Skarels /*
46550004Skarels * Force a header to be prepended to the next output.
46650004Skarels */
46748570Sbostic void
needhdr()46850004Skarels needhdr()
46950004Skarels {
47050004Skarels
47150004Skarels hdrcnt = 1;
47250004Skarels }
47350004Skarels
47450103Skarels #ifdef notdef
47550004Skarels void
dotimes()4761155Sbill dotimes()
4771155Sbill {
47848570Sbostic u_int pgintime, rectime;
4791155Sbill
48048570Sbostic kread(X_REC, &rectime, sizeof(rectime));
48148570Sbostic kread(X_PGIN, &pgintime, sizeof(pgintime));
48248570Sbostic kread(X_SUM, &sum, sizeof(sum));
48348570Sbostic (void)printf("%u reclaims, %u total time (usec)\n",
48448570Sbostic sum.v_pgrec, rectime);
48548570Sbostic (void)printf("average: %u usec / reclaim\n", rectime / sum.v_pgrec);
48648570Sbostic (void)printf("\n");
48748570Sbostic (void)printf("%u page ins, %u total time (msec)\n",
48848570Sbostic sum.v_pgin, pgintime / 10);
48948570Sbostic (void)printf("average: %8.1f msec / page in\n",
49048570Sbostic pgintime / (sum.v_pgin * 10.0));
4911155Sbill }
49250004Skarels #endif
4931155Sbill
pct(top,bot)49445834Sbostic pct(top, bot)
49545834Sbostic long top, bot;
49645834Sbostic {
49758251Smckusick long ans;
49858251Smckusick
49945834Sbostic if (bot == 0)
50048570Sbostic return(0);
50158251Smckusick ans = (quad_t)top * 100 / bot;
50258251Smckusick return (ans);
50345834Sbostic }
50445834Sbostic
50545834Sbostic #define PCT(top, bot) pct((long)(top), (long)(bot))
50645834Sbostic
50730069Ssam #if defined(tahoe)
50845834Sbostic #include <machine/cpu.h>
50930069Ssam #endif
51030069Ssam
51148570Sbostic void
dosum()5121155Sbill dosum()
5131155Sbill {
51418761Ssam struct nchstats nchstats;
51550004Skarels #ifndef NEWVM
51625960Ssam struct xstats xstats;
51750004Skarels #endif
51815807Smckusick long nchtotal;
51925960Ssam #if defined(tahoe)
52025960Ssam struct keystats keystats;
52125960Ssam #endif
5221155Sbill
52348570Sbostic kread(X_SUM, &sum, sizeof(sum));
52451359Smckusick (void)printf("%9u cpu context switches\n", sum.v_swtch);
52551359Smckusick (void)printf("%9u device interrupts\n", sum.v_intr);
52651359Smckusick (void)printf("%9u software interrupts\n", sum.v_soft);
52751359Smckusick #ifdef vax
52851359Smckusick (void)printf("%9u pseudo-dma dz interrupts\n", sum.v_pdma);
52951359Smckusick #endif
53051359Smckusick (void)printf("%9u traps\n", sum.v_trap);
53151359Smckusick (void)printf("%9u system calls\n", sum.v_syscall);
53251359Smckusick (void)printf("%9u total faults taken\n", sum.v_faults);
53348570Sbostic (void)printf("%9u swap ins\n", sum.v_swpin);
53448570Sbostic (void)printf("%9u swap outs\n", sum.v_swpout);
53548570Sbostic (void)printf("%9u pages swapped in\n", sum.v_pswpin / CLSIZE);
53648570Sbostic (void)printf("%9u pages swapped out\n", sum.v_pswpout / CLSIZE);
53751359Smckusick (void)printf("%9u page ins\n", sum.v_pageins);
53851359Smckusick (void)printf("%9u page outs\n", sum.v_pageouts);
53948570Sbostic (void)printf("%9u pages paged in\n", sum.v_pgpgin);
54048570Sbostic (void)printf("%9u pages paged out\n", sum.v_pgpgout);
54151359Smckusick (void)printf("%9u pages reactivated\n", sum.v_reactivated);
54251359Smckusick (void)printf("%9u intransit blocking page faults\n", sum.v_intrans);
54351359Smckusick (void)printf("%9u zero fill pages created\n", sum.v_nzfod / CLSIZE);
54451359Smckusick (void)printf("%9u zero fill page faults\n", sum.v_zfod / CLSIZE);
54551359Smckusick (void)printf("%9u pages examined by the clock daemon\n", sum.v_scan);
54651359Smckusick (void)printf("%9u revolutions of the clock hand\n", sum.v_rev);
54751359Smckusick #ifdef NEWVM
54851359Smckusick (void)printf("%9u VM object cache lookups\n", sum.v_lookups);
54951359Smckusick (void)printf("%9u VM object hits\n", sum.v_hits);
55051359Smckusick (void)printf("%9u total VM faults taken\n", sum.v_vm_faults);
55151359Smckusick (void)printf("%9u copy-on-write faults\n", sum.v_cow_faults);
55251359Smckusick (void)printf("%9u pages freed by daemon\n", sum.v_dfree);
55351359Smckusick (void)printf("%9u pages freed by exiting processes\n", sum.v_pfree);
55451359Smckusick (void)printf("%9u pages free\n", sum.v_free_count);
55551359Smckusick (void)printf("%9u pages wired down\n", sum.v_wire_count);
55651359Smckusick (void)printf("%9u pages active\n", sum.v_active_count);
55751359Smckusick (void)printf("%9u pages inactive\n", sum.v_inactive_count);
55851359Smckusick (void)printf("%9u bytes per page\n", sum.v_page_size);
559*68469Smckusick (void)printf("%9u target inactive pages\n", sum.v_inactive_target);
560*68469Smckusick (void)printf("%9u target free pages\n", sum.v_free_target);
561*68469Smckusick (void)printf("%9u minimum free pages\n", sum.v_free_min);
56251359Smckusick #else
56348570Sbostic (void)printf("%9u sequential process pages freed\n", sum.v_seqfree);
56448570Sbostic (void)printf("%9u total reclaims (%d%% fast)\n", sum.v_pgrec,
56545834Sbostic PCT(sum.v_fastpgrec, sum.v_pgrec));
56648570Sbostic (void)printf("%9u reclaims from free list\n", sum.v_pgfrec);
56748570Sbostic (void)printf("%9u executable fill pages created\n",
56845834Sbostic sum.v_nexfod / CLSIZE);
56948570Sbostic (void)printf("%9u executable fill page faults\n",
57045834Sbostic sum.v_exfod / CLSIZE);
57148570Sbostic (void)printf("%9u swap text pages found in free list\n",
57245834Sbostic sum.v_xsfrec);
57348570Sbostic (void)printf("%9u inode text pages found in free list\n",
57445834Sbostic sum.v_xifrec);
57548570Sbostic (void)printf("%9u file fill pages created\n", sum.v_nvrfod / CLSIZE);
57648570Sbostic (void)printf("%9u file fill page faults\n", sum.v_vrfod / CLSIZE);
57748570Sbostic (void)printf("%9u pages freed by the clock daemon\n",
57845834Sbostic sum.v_dfree / CLSIZE);
57950006Skarels #endif
58048570Sbostic kread(X_NCHSTATS, &nchstats, sizeof(nchstats));
58138773Smckusick nchtotal = nchstats.ncs_goodhits + nchstats.ncs_neghits +
58238773Smckusick nchstats.ncs_badhits + nchstats.ncs_falsehits +
58338773Smckusick nchstats.ncs_miss + nchstats.ncs_long;
58448570Sbostic (void)printf("%9ld total name lookups\n", nchtotal);
58548570Sbostic (void)printf(
58645834Sbostic "%9s cache hits (%d%% pos + %d%% neg) system %d%% per-process\n",
58745834Sbostic "", PCT(nchstats.ncs_goodhits, nchtotal),
58845834Sbostic PCT(nchstats.ncs_neghits, nchtotal),
58945834Sbostic PCT(nchstats.ncs_pass2, nchtotal));
59048570Sbostic (void)printf("%9s deletions %d%%, falsehits %d%%, toolong %d%%\n", "",
59145834Sbostic PCT(nchstats.ncs_badhits, nchtotal),
59245834Sbostic PCT(nchstats.ncs_falsehits, nchtotal),
59345834Sbostic PCT(nchstats.ncs_long, nchtotal));
59450004Skarels #ifndef NEWVM
59548570Sbostic kread(X_XSTATS, &xstats, sizeof(xstats));
59648570Sbostic (void)printf("%9lu total calls to xalloc (cache hits %d%%)\n",
59745834Sbostic xstats.alloc, PCT(xstats.alloc_cachehit, xstats.alloc));
59848570Sbostic (void)printf("%9s sticky %lu flushed %lu unused %lu\n", "",
59925512Ssam xstats.alloc_inuse, xstats.alloc_cacheflush, xstats.alloc_unused);
60048570Sbostic (void)printf("%9lu total calls to xfree", xstats.free);
60148570Sbostic (void)printf(" (sticky %lu cached %lu swapped %lu)\n",
60225512Ssam xstats.free_inuse, xstats.free_cache, xstats.free_cacheswap);
60350004Skarels #endif
60425960Ssam #if defined(tahoe)
60548570Sbostic kread(X_CKEYSTATS, &keystats, sizeof(keystats));
60648570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
60725960Ssam keystats.ks_allocs, "code cache keys allocated",
60845834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs),
60945834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs),
61045834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs),
61145834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs));
61248570Sbostic kread(X_DKEYSTATS, &keystats, sizeof(keystats));
61348570Sbostic (void)printf("%9d %s (free %d%% norefs %d%% taken %d%% shared %d%%)\n",
61425960Ssam keystats.ks_allocs, "data cache keys allocated",
61545834Sbostic PCT(keystats.ks_allocfree, keystats.ks_allocs),
61645834Sbostic PCT(keystats.ks_norefs, keystats.ks_allocs),
61745834Sbostic PCT(keystats.ks_taken, keystats.ks_allocs),
61845834Sbostic PCT(keystats.ks_shared, keystats.ks_allocs));
61925960Ssam #endif
6201155Sbill }
6211155Sbill
62250103Skarels #ifdef notdef
62348570Sbostic void
doforkst()6241155Sbill doforkst()
6251155Sbill {
62648570Sbostic struct forkstat fks;
6271155Sbill
62848570Sbostic kread(X_FORKSTAT, &fks, sizeof(struct forkstat));
62948570Sbostic (void)printf("%d forks, %d pages, average %.2f\n",
63048570Sbostic fks.cntfork, fks.sizfork, (double)fks.sizfork / fks.cntfork);
63148570Sbostic (void)printf("%d vforks, %d pages, average %.2f\n",
63248570Sbostic fks.cntvfork, fks.sizvfork, (double)fks.sizvfork / fks.cntvfork);
6331155Sbill }
63450004Skarels #endif
6351155Sbill
63648570Sbostic void
dkstats()63748613Sbostic dkstats()
6381155Sbill {
63948613Sbostic register int dn, state;
64048613Sbostic double etime;
64148613Sbostic long tmp;
64248613Sbostic
64348613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) {
64448613Sbostic tmp = cur.xfer[dn];
64548613Sbostic cur.xfer[dn] -= last.xfer[dn];
64648613Sbostic last.xfer[dn] = tmp;
64748613Sbostic }
64848613Sbostic etime = 0;
64948613Sbostic for (state = 0; state < CPUSTATES; ++state) {
65048613Sbostic tmp = cur.time[state];
65148613Sbostic cur.time[state] -= last.time[state];
65248613Sbostic last.time[state] = tmp;
65348613Sbostic etime += cur.time[state];
65448613Sbostic }
65548613Sbostic if (etime == 0)
65648613Sbostic etime = 1;
65748613Sbostic etime /= hz;
65848613Sbostic for (dn = 0; dn < dk_ndrive; ++dn) {
65948613Sbostic if (!dr_select[dn])
66048613Sbostic continue;
66150006Skarels (void)printf("%2.0f ", cur.xfer[dn] / etime);
66248613Sbostic }
6631155Sbill }
6641155Sbill
66548613Sbostic void
cpustats()66648613Sbostic cpustats()
6671155Sbill {
66848613Sbostic register int state;
66948613Sbostic double pct, total;
6701155Sbill
67148613Sbostic total = 0;
67248613Sbostic for (state = 0; state < CPUSTATES; ++state)
67348613Sbostic total += cur.time[state];
67448613Sbostic if (total)
67548613Sbostic pct = 100 / total;
67648613Sbostic else
67748613Sbostic pct = 0;
67858983Sralph (void)printf("%2.0f ", (cur.time[CP_USER] + cur.time[CP_NICE]) * pct);
67958983Sralph (void)printf("%2.0f ", (cur.time[CP_SYS] + cur.time[CP_INTR]) * pct);
68058983Sralph (void)printf("%2.0f", cur.time[CP_IDLE] * pct);
6811155Sbill }
6821155Sbill
68348570Sbostic void
dointr()68445834Sbostic dointr()
6851155Sbill {
68648570Sbostic register long *intrcnt, inttotal, uptime;
68745834Sbostic register int nintr, inamlen;
68845834Sbostic register char *intrname;
6891155Sbill
69048570Sbostic uptime = getuptime();
69156572Sbostic nintr = namelist[X_EINTRCNT].n_value - namelist[X_INTRCNT].n_value;
69256572Sbostic inamlen =
69356572Sbostic namelist[X_EINTRNAMES].n_value - namelist[X_INTRNAMES].n_value;
69448570Sbostic intrcnt = malloc((size_t)nintr);
69545834Sbostic intrname = malloc((size_t)inamlen);
69617262Smckusick if (intrcnt == NULL || intrname == NULL) {
69748570Sbostic (void)fprintf(stderr, "vmstat: %s.\n", strerror(errno));
69848570Sbostic exit(1);
69917262Smckusick }
70048570Sbostic kread(X_INTRCNT, intrcnt, (size_t)nintr);
70145834Sbostic kread(X_INTRNAMES, intrname, (size_t)inamlen);
70248570Sbostic (void)printf("interrupt total rate\n");
70317262Smckusick inttotal = 0;
70445834Sbostic nintr /= sizeof(long);
70545834Sbostic while (--nintr >= 0) {
70617262Smckusick if (*intrcnt)
70748570Sbostic (void)printf("%-12s %8ld %8ld\n", intrname,
70845834Sbostic *intrcnt, *intrcnt / uptime);
70917262Smckusick intrname += strlen(intrname) + 1;
71017262Smckusick inttotal += *intrcnt++;
71117262Smckusick }
71248570Sbostic (void)printf("Total %8ld %8ld\n", inttotal, inttotal / uptime);
71317262Smckusick }
71417262Smckusick
71533610Smckusick /*
71645152Smckusick * These names are defined in <sys/malloc.h>.
71733610Smckusick */
71845152Smckusick char *kmemnames[] = INITKMEMNAMES;
71933610Smckusick
72048570Sbostic void
domem()72133610Smckusick domem()
72233610Smckusick {
72345834Sbostic register struct kmembuckets *kp;
72445834Sbostic register struct kmemstats *ks;
72556612Smckusick register int i, j;
72656612Smckusick int len, size, first;
72750004Skarels long totuse = 0, totfree = 0, totreq = 0;
72856612Smckusick char *name;
72933610Smckusick struct kmemstats kmemstats[M_LAST];
73033610Smckusick struct kmembuckets buckets[MINBUCKET + 16];
73133610Smckusick
73248570Sbostic kread(X_KMEMBUCKETS, buckets, sizeof(buckets));
73348570Sbostic (void)printf("Memory statistics by bucket size\n");
73448570Sbostic (void)printf(
73545834Sbostic " Size In Use Free Requests HighWater Couldfree\n");
73633610Smckusick for (i = MINBUCKET, kp = &buckets[i]; i < MINBUCKET + 16; i++, kp++) {
73733610Smckusick if (kp->kb_calls == 0)
73833610Smckusick continue;
73950004Skarels size = 1 << i;
74050006Skarels (void)printf("%8d %8ld %6ld %10ld %7ld %10ld\n", size,
74133610Smckusick kp->kb_total - kp->kb_totalfree,
74233610Smckusick kp->kb_totalfree, kp->kb_calls,
74333610Smckusick kp->kb_highwat, kp->kb_couldfree);
74450004Skarels totfree += size * kp->kb_totalfree;
74533610Smckusick }
74650004Skarels
74748570Sbostic kread(X_KMEMSTAT, kmemstats, sizeof(kmemstats));
74856612Smckusick (void)printf("\nMemory usage type by bucket size\n");
74956612Smckusick (void)printf(" Size Type(s)\n");
75056612Smckusick kp = &buckets[MINBUCKET];
75156612Smckusick for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1, kp++) {
75256612Smckusick if (kp->kb_calls == 0)
75356612Smckusick continue;
75456612Smckusick first = 1;
75556612Smckusick len = 8;
75656612Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
75756612Smckusick if (ks->ks_calls == 0)
75856612Smckusick continue;
75956612Smckusick if ((ks->ks_size & j) == 0)
76056612Smckusick continue;
76156612Smckusick name = kmemnames[i] ? kmemnames[i] : "undefined";
76256612Smckusick len += 2 + strlen(name);
76356612Smckusick if (first)
76456612Smckusick printf("%8d %s", j, name);
76556612Smckusick else
76656612Smckusick printf(",");
76756612Smckusick if (len >= 80) {
76856612Smckusick printf("\n\t ");
76956612Smckusick len = 10 + strlen(name);
77056612Smckusick }
77156612Smckusick if (!first)
77256612Smckusick printf(" %s", name);
77356612Smckusick first = 0;
77456612Smckusick }
77556612Smckusick printf("\n");
77656612Smckusick }
77756612Smckusick
77848570Sbostic (void)printf(
77956612Smckusick "\nMemory statistics by type Type Kern\n");
78056612Smckusick (void)printf(
78156612Smckusick " Type InUse MemUse HighUse Limit Requests Limit Limit Size(s)\n");
78233610Smckusick for (i = 0, ks = &kmemstats[0]; i < M_LAST; i++, ks++) {
78333610Smckusick if (ks->ks_calls == 0)
78433610Smckusick continue;
78556612Smckusick (void)printf("%11s%6ld%6ldK%7ldK%6ldK%9ld%5u%6u",
78648570Sbostic kmemnames[i] ? kmemnames[i] : "undefined",
78748570Sbostic ks->ks_inuse, (ks->ks_memuse + 1023) / 1024,
78848570Sbostic (ks->ks_maxused + 1023) / 1024,
78948570Sbostic (ks->ks_limit + 1023) / 1024, ks->ks_calls,
79048570Sbostic ks->ks_limblocks, ks->ks_mapblocks);
79156612Smckusick first = 1;
79256612Smckusick for (j = 1 << MINBUCKET; j < 1 << (MINBUCKET + 16); j <<= 1) {
79356612Smckusick if ((ks->ks_size & j) == 0)
79456612Smckusick continue;
79556612Smckusick if (first)
79656612Smckusick printf(" %d", j);
79756612Smckusick else
79856612Smckusick printf(",%d", j);
79956612Smckusick first = 0;
80056612Smckusick }
80156612Smckusick printf("\n");
80250004Skarels totuse += ks->ks_memuse;
80350004Skarels totreq += ks->ks_calls;
80433610Smckusick }
80550004Skarels (void)printf("\nMemory Totals: In Use Free Requests\n");
80650004Skarels (void)printf(" %7ldK %6ldK %8ld\n",
80750004Skarels (totuse + 1023) / 1024, (totfree + 1023) / 1024, totreq);
80833610Smckusick }
80933610Smckusick
81025708Ssam /*
81148570Sbostic * kread reads something from the kernel, given its nlist index.
81225708Ssam */
81348570Sbostic void
kread(nlx,addr,size)81448570Sbostic kread(nlx, addr, size)
81548570Sbostic int nlx;
81648570Sbostic void *addr;
81748570Sbostic size_t size;
81825708Ssam {
81948570Sbostic char *sym;
82025708Ssam
82156572Sbostic if (namelist[nlx].n_type == 0 || namelist[nlx].n_value == 0) {
82256572Sbostic sym = namelist[nlx].n_name;
82348570Sbostic if (*sym == '_')
82448570Sbostic ++sym;
82548570Sbostic (void)fprintf(stderr,
82652243Sbostic "vmstat: symbol %s not defined\n", sym);
82725708Ssam exit(1);
82825708Ssam }
82956572Sbostic if (kvm_read(kd, namelist[nlx].n_value, addr, size) != size) {
83056572Sbostic sym = namelist[nlx].n_name;
83148570Sbostic if (*sym == '_')
83248570Sbostic ++sym;
83354272Smccanne (void)fprintf(stderr, "vmstat: %s: %s\n", sym, kvm_geterr(kd));
83448570Sbostic exit(1);
83525708Ssam }
83625708Ssam }
83742952Sbostic
83848570Sbostic void
usage()83948570Sbostic usage()
84042952Sbostic {
84148570Sbostic (void)fprintf(stderr,
84250004Skarels #ifndef NEWVM
84348570Sbostic "usage: vmstat [-fimst] [-c count] [-M core] \
84450103Skarels [-N system] [-w wait] [disks]\n");
84550004Skarels #else
84650004Skarels "usage: vmstat [-ims] [-c count] [-M core] \
84750103Skarels [-N system] [-w wait] [disks]\n");
84850004Skarels #endif
84948570Sbostic exit(1);
85042952Sbostic }
851