* Copyright (c) 1983, 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)vmstat.c 5.17 (Berkeley) %G%";
* Cursed vmstat -- from Robert Elz.
ut
= open(_PATH_UTMP
, O_RDONLY
);
static struct nlist nlst
[] = {
struct nchstats nchstats
;
#define nchtotal s.nchstats
#define oldnchtotal s1.nchstats
static enum state
{ BOOT
, TIME
, RUN
} state
= TIME
;
static void putint(), putfloat(), putrate();
static void getinfo(), allocinfo(), copyinfo(), dinfo();
* These constants define where the major pieces are laid out
#define STATROW 0 /* uses 1 row and 68 cols */
#define MEMROW 2 /* uses 4 rows and 31 cols */
#define PAGEROW 2 /* uses 4 rows and 26 cols */
#define INTSROW 2 /* uses all rows to bottom and 17 cols */
#define PROCSROW 7 /* uses 2 rows and 20 cols */
#define GENSTATROW 7 /* uses 2 rows and 30 cols */
#define VMSTATROW 7 /* uses 16 rows and 12 cols */
#define GRAPHROW 10 /* uses 3 rows and 51 cols */
#define NAMEIROW 14 /* uses 3 rows and 38 cols */
#define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */
#define DRIVESPACE 9 /* max # for space */
#if DK_NDRIVE > DRIVESPACE
#define MAXDRIVES DRIVESPACE /* max # to display */
#define MAXDRIVES DK_NDRIVE /* max # to display */
if (nlst
[0].n_type
== 0) {
if (nlst
[0].n_type
== 0) {
if (dk_ndrive
&& !once
) {
s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
s1./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
s2./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
z./**/e = (t *)calloc(dk_ndrive, sizeof (t));
nintr
= (nlst
[X_EINTRCNT
].n_value
-
nlst
[X_INTRCNT
].n_value
) / sizeof (long);
intrloc
= (long *) calloc(nintr
, sizeof (long));
intrname
= (char **) calloc(nintr
, sizeof (long));
intrnamebuf
= malloc(nlst
[X_EINTRNAMES
].n_value
-
nlst
[X_INTRNAMES
].n_value
);
if (intrnamebuf
== 0 || intrname
== 0 || intrloc
== 0) {
error("Out of memory\n");
NREAD(X_INTRNAMES
, intrnamebuf
, NVAL(X_EINTRNAMES
) -
for (cp
= intrnamebuf
, i
= 0; i
< nintr
; i
++) {
nextintsrow
= INTSROW
+ 2;
strcpy(buf
, ctime(&now
));
mvprintw(STATROW
, STATCOL
+ 4, "users Load");
mvprintw(MEMROW
, MEMCOL
, "Mem:KB REAL VIRTUAL");
mvprintw(MEMROW
+ 1, MEMCOL
, " Tot Share Tot Share");
mvprintw(MEMROW
+ 2, MEMCOL
, "Act");
mvprintw(MEMROW
+ 3, MEMCOL
, "All");
mvprintw(MEMROW
+ 1, MEMCOL
+ 31, "Free");
mvprintw(PAGEROW
, PAGECOL
, " PAGING SWAPPING ");
mvprintw(PAGEROW
+ 1, PAGECOL
, " in out in out ");
mvprintw(PAGEROW
+ 2, PAGECOL
, "count");
mvprintw(PAGEROW
+ 3, PAGECOL
, "pages");
mvprintw(INTSROW
, INTSCOL
+ 3, " Interrupts");
mvprintw(INTSROW
+ 1, INTSCOL
+ 9, "total");
mvprintw(VMSTATROW
, VMSTATCOL
+ 10, "vmflt");
mvprintw(VMSTATROW
+ 1, VMSTATCOL
+ 10, "cow");
mvprintw(VMSTATROW
+ 2, VMSTATCOL
+ 10, "objlk");
mvprintw(VMSTATROW
+ 3, VMSTATCOL
+ 10, "objht");
mvprintw(VMSTATROW
+ 4, VMSTATCOL
+ 10, "zfod");
mvprintw(VMSTATROW
+ 5, VMSTATCOL
+ 10, "nzfod");
mvprintw(VMSTATROW
+ 6, VMSTATCOL
+ 10, "%%zfod");
mvprintw(VMSTATROW
+ 7, VMSTATCOL
+ 10, "kern");
mvprintw(VMSTATROW
+ 8, VMSTATCOL
+ 10, "wire");
mvprintw(VMSTATROW
+ 9, VMSTATCOL
+ 10, "act");
mvprintw(VMSTATROW
+ 10, VMSTATCOL
+ 10, "inact");
mvprintw(VMSTATROW
+ 11, VMSTATCOL
+ 10, "free");
mvprintw(VMSTATROW
+ 12, VMSTATCOL
+ 10, "daefr");
mvprintw(VMSTATROW
+ 13, VMSTATCOL
+ 10, "prcfr");
mvprintw(VMSTATROW
+ 14, VMSTATCOL
+ 10, "react");
mvprintw(VMSTATROW
+ 15, VMSTATCOL
+ 10, "scan");
if (LINES
- 1 > VMSTATROW
+ 16)
mvprintw(VMSTATROW
+ 16, VMSTATCOL
+ 10, "hdrev");
if (LINES
- 1 > VMSTATROW
+ 17)
mvprintw(VMSTATROW
+ 17, VMSTATCOL
+ 10, "intrn");
mvprintw(GENSTATROW
, GENSTATCOL
, " Csw Trp Sys Int Sof Flt");
mvprintw(GRAPHROW
, GRAPHCOL
,
" . %% Sys . %% User . %% Nice . %% Idle");
mvprintw(PROCSROW
, PROCSCOL
, "Proc:r p d s w");
mvprintw(GRAPHROW
+ 1, GRAPHCOL
,
"| | | | | | | | | | |");
mvprintw(NAMEIROW
, NAMEICOL
, "Namei Sys-cache Proc-cache");
mvprintw(NAMEIROW
+ 1, NAMEICOL
,
" Calls hits %% hits %%");
mvprintw(DISKROW
, DISKCOL
, "Discs");
mvprintw(DISKROW
+ 1, DISKCOL
, "seeks");
mvprintw(DISKROW
+ 2, DISKCOL
, "xfers");
mvprintw(DISKROW
+ 3, DISKCOL
, " blks");
mvprintw(DISKROW
+ 4, DISKCOL
, " msps");
for (i
= 0; i
< dk_ndrive
&& j
< MAXDRIVES
; i
++)
mvprintw(DISKROW
, DISKCOL
+ 5 + 5 * j
,
for (i
= 0; i
< nintr
; i
++) {
mvprintw(intrloc
[i
], INTSCOL
+ 9, "%-8.8s", intrname
[i
]);
#define X(fld) {t=s.fld[i]; s.fld[i]-=s1.fld[i]; if(state==TIME) s1.fld[i]=t;}
#define Y(fld) {t = s.fld; s.fld -= s1.fld; if(state == TIME) s1.fld = t;}
#define Z(fld) {t = s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld; \
if(state == TIME) s1.nchstats.fld = t;}
#define PUTRATE(fld, l, c, w) \
putint((int)((float)s.fld/etime + 0.5), l, c, w)
static char cpuchar
[CPUSTATES
] = { '=' , '>', '-', ' ' };
static char cpuorder
[CPUSTATES
] = { CP_SYS
, CP_USER
, CP_NICE
, CP_IDLE
};
for (i
= 0; i
< dk_ndrive
; i
++) {
X(dk_xfer
); X(dk_seek
); X(dk_wds
); X(dk_time
);
for(i
= 0; i
< CPUSTATES
; i
++) {
if (etime
< 5.0) { /* < 5 ticks - ignore this trash */
if (failcnt
++ >= MAXFAIL
) {
mvprintw(2, 10, "The alternate system clock has died!");
mvprintw(3, 10, "Reverting to ``pigs'' display.");
for (i
= 0; i
< nintr
; i
++) {
if (nextintsrow
== LINES
)
intrloc
[i
] = nextintsrow
++;
mvprintw(intrloc
[i
], INTSCOL
+ 9, "%-8.8s",
l
= (int)((float)s
.intrcnt
[i
]/etime
+ 0.5);
putint(l
, intrloc
[i
], INTSCOL
, 8);
putint(inttotal
, INTSROW
+ 1, INTSCOL
, 8);
Z(ncs_goodhits
); Z(ncs_badhits
); Z(ncs_miss
);
Z(ncs_long
); Z(ncs_pass2
); Z(ncs_2passes
);
s
.nchcount
= nchtotal
.ncs_goodhits
+ nchtotal
.ncs_badhits
+
nchtotal
.ncs_miss
+ nchtotal
.ncs_long
;
s1
.nchcount
= s
.nchcount
;
for (c
= 0; c
< CPUSTATES
; c
++) {
l
= (int) ((f2
+ 1.0) / 2.0) - psiz
;
putfloat(f1
, GRAPHROW
, GRAPHCOL
+ 1, 5, 1, 0);
putfloat(f1
, GRAPHROW
, GRAPHCOL
+ 12 * c
,
move(GRAPHROW
+ 2, psiz
);
putint(ucount(), STATROW
, STATCOL
, 3);
putfloat(avenrun
[0], STATROW
, STATCOL
+ 17, 6, 2, 0);
putfloat(avenrun
[1], STATROW
, STATCOL
+ 23, 6, 2, 0);
putfloat(avenrun
[2], STATROW
, STATCOL
+ 29, 6, 2, 0);
mvaddstr(STATROW
, STATCOL
+ 53, buf
);
#define pgtokb(pg) ((pg) * cnt.v_page_size / 1024)
putint(pgtokb(total
.t_arm
), MEMROW
+ 2, MEMCOL
+ 3, 6);
putint(pgtokb(total
.t_armshr
), MEMROW
+ 2, MEMCOL
+ 9, 6);
putint(pgtokb(total
.t_avm
), MEMROW
+ 2, MEMCOL
+ 15, 7);
putint(pgtokb(total
.t_avmshr
), MEMROW
+ 2, MEMCOL
+ 22, 7);
putint(pgtokb(total
.t_rm
), MEMROW
+ 3, MEMCOL
+ 3, 6);
putint(pgtokb(total
.t_rmshr
), MEMROW
+ 3, MEMCOL
+ 9, 6);
putint(pgtokb(total
.t_vm
), MEMROW
+ 3, MEMCOL
+ 15, 7);
putint(pgtokb(total
.t_vmshr
), MEMROW
+ 3, MEMCOL
+ 22, 7);
putint(pgtokb(total
.t_free
), MEMROW
+ 2, MEMCOL
+ 29, 6);
putint(total
.t_rq
, PROCSROW
+ 1, PROCSCOL
+ 3, 3);
putint(total
.t_pw
, PROCSROW
+ 1, PROCSCOL
+ 6, 3);
putint(total
.t_dw
, PROCSROW
+ 1, PROCSCOL
+ 9, 3);
putint(total
.t_sl
, PROCSROW
+ 1, PROCSCOL
+ 12, 3);
putint(total
.t_sw
, PROCSROW
+ 1, PROCSCOL
+ 15, 3);
PUTRATE(Cnt
.v_vm_faults
, VMSTATROW
, VMSTATCOL
+ 3, 6);
PUTRATE(Cnt
.v_cow_faults
, VMSTATROW
+ 1, VMSTATCOL
+ 3, 6);
PUTRATE(Cnt
.v_lookups
, VMSTATROW
+ 2, VMSTATCOL
+ 3, 6);
PUTRATE(Cnt
.v_hits
, VMSTATROW
+ 3, VMSTATCOL
+ 3, 6);
PUTRATE(Cnt
.v_zfod
, VMSTATROW
+ 4, VMSTATCOL
+ 4, 5);
PUTRATE(Cnt
.v_nzfod
, VMSTATROW
+ 5, VMSTATCOL
+ 3, 6);
putfloat(cnt
.v_nzfod
== 0 ? 0.0 : (100.0 * cnt
.v_zfod
/ cnt
.v_nzfod
),
VMSTATROW
+ 6, VMSTATCOL
+ 2, 7, 2, 1);
putint(pgtokb(cnt
.v_kernel_pages
), VMSTATROW
+ 7, VMSTATCOL
, 9);
putint(pgtokb(cnt
.v_wire_count
), VMSTATROW
+ 8, VMSTATCOL
, 9);
putint(pgtokb(cnt
.v_active_count
), VMSTATROW
+ 9, VMSTATCOL
, 9);
putint(pgtokb(cnt
.v_inactive_count
), VMSTATROW
+ 10, VMSTATCOL
, 9);
putint(pgtokb(cnt
.v_free_count
), VMSTATROW
+ 11, VMSTATCOL
, 9);
PUTRATE(Cnt
.v_dfree
, VMSTATROW
+ 12, VMSTATCOL
, 9);
PUTRATE(Cnt
.v_pfree
, VMSTATROW
+ 13, VMSTATCOL
, 9);
PUTRATE(Cnt
.v_reactivated
, VMSTATROW
+ 14, VMSTATCOL
, 9);
PUTRATE(Cnt
.v_scan
, VMSTATROW
+ 15, VMSTATCOL
, 9);
if (LINES
- 1 > VMSTATROW
+ 16)
PUTRATE(Cnt
.v_rev
, VMSTATROW
+ 16, VMSTATCOL
, 9);
if (LINES
- 1 > VMSTATROW
+ 17)
PUTRATE(Cnt
.v_intrans
, VMSTATROW
+ 17, VMSTATCOL
, 9);
PUTRATE(Cnt
.v_pageins
, PAGEROW
+ 2, PAGECOL
+ 5, 5);
PUTRATE(Cnt
.v_pageouts
, PAGEROW
+ 2, PAGECOL
+ 10, 5);
PUTRATE(Cnt
.v_swpin
, PAGEROW
+ 2, PAGECOL
+ 15, 5); /* - */
PUTRATE(Cnt
.v_swpout
, PAGEROW
+ 2, PAGECOL
+ 20, 5); /* - */
PUTRATE(Cnt
.v_pgpgin
, PAGEROW
+ 3, PAGECOL
+ 5, 5); /* ? */
PUTRATE(Cnt
.v_pgpgout
, PAGEROW
+ 3, PAGECOL
+ 10, 5); /* ? */
PUTRATE(Cnt
.v_pswpin
, PAGEROW
+ 3, PAGECOL
+ 15, 5); /* - */
PUTRATE(Cnt
.v_pswpout
, PAGEROW
+ 3, PAGECOL
+ 20, 5); /* - */
PUTRATE(Cnt
.v_swtch
, GENSTATROW
+ 1, GENSTATCOL
, 5);
PUTRATE(Cnt
.v_trap
, GENSTATROW
+ 1, GENSTATCOL
+ 5, 5);
PUTRATE(Cnt
.v_syscall
, GENSTATROW
+ 1, GENSTATCOL
+ 10, 5);
PUTRATE(Cnt
.v_intr
, GENSTATROW
+ 1, GENSTATCOL
+ 15, 5);
PUTRATE(Cnt
.v_soft
, GENSTATROW
+ 1, GENSTATCOL
+ 20, 5);
PUTRATE(Cnt
.v_faults
, GENSTATROW
+ 1, GENSTATCOL
+ 25, 5);
mvprintw(DISKROW
, DISKCOL
+ 5, " ");
for (i
= 0, c
= 0; i
< dk_ndrive
&& c
< MAXDRIVES
; i
++)
mvprintw(DISKROW
, DISKCOL
+ 5 + 5 * c
,
putint(s
.nchcount
, NAMEIROW
+ 2, NAMEICOL
, 9);
putint(nchtotal
.ncs_goodhits
, NAMEIROW
+ 2, NAMEICOL
+ 9, 9);
#define nz(x) ((x) ? (x) : 1)
putfloat(nchtotal
.ncs_goodhits
* 100.0 / nz(s
.nchcount
),
NAMEIROW
+ 2, NAMEICOL
+ 19, 4, 0, 1);
putint(nchtotal
.ncs_pass2
, NAMEIROW
+ 2, NAMEICOL
+ 23, 9);
putfloat(nchtotal
.ncs_pass2
* 100.0 / nz(s
.nchcount
),
NAMEIROW
+ 2, NAMEICOL
+ 34, 4, 0, 1);
if (prefix(cmd
, "run")) {
if (prefix(cmd
, "boot")) {
if (prefix(cmd
, "time")) {
if (prefix(cmd
, "zero")) {
return (dkcmd(cmd
, args
));
/* calculate number of users on the system */
while (read(ut
, &utmp
, sizeof(utmp
)))
if (utmp
.ut_name
[0] != '\0')
for (i
= 0; i
< CPUSTATES
; i
++)
return (s
.time
[indx
] * 100.0 / t
);
if (state
== RUN
|| state
== TIME
)
putint((int)((float)r
/etime
+ 0.5), l
, c
, w
);
putfloat(f
, l
, c
, w
, d
, nz
)
sprintf(b
, "%*.*f", w
, d
, f
);
NREAD(X_CPTIME
, s
->time
, sizeof s
->time
);
NREAD(X_CNT
, &s
->Cnt
, sizeof s
->Cnt
);
NREAD(X_DK_BUSY
, &s
->dk_busy
, LONG
);
NREAD(X_DK_TIME
, s
->dk_time
, dk_ndrive
* LONG
);
NREAD(X_DK_XFER
, s
->dk_xfer
, dk_ndrive
* LONG
);
NREAD(X_DK_WDS
, s
->dk_wds
, dk_ndrive
* LONG
);
NREAD(X_DK_SEEK
, s
->dk_seek
, dk_ndrive
* LONG
);
NREAD(X_NCHSTATS
, &s
->nchstats
, sizeof s
->nchstats
);
NREAD(X_INTRCNT
, s
->intrcnt
, nintr
* LONG
);
if (getkerninfo(KINFO_METER
, &s
->Total
, &size
, 0) < 0) {
error("Can't get kerninfo: %s\n", strerror(errno
));
bzero(&s
->Total
, sizeof(s
->Total
));
s
->intrcnt
= (long *) malloc(nintr
* sizeof(long));
if (s
->intrcnt
== NULL
) {
fprintf(stderr
, "systat: out of memory\n");
register struct Info
*from
, *to
;
long *time
, *wds
, *seek
, *xfer
;
* time, wds, seek, and xfer are malloc'd so we have to
* save the pointers before the structure copy and then
time
= to
->dk_time
; wds
= to
->dk_wds
; seek
= to
->dk_seek
;
xfer
= to
->dk_xfer
; intrcnt
= to
->intrcnt
;
bcopy(from
->dk_time
, to
->dk_time
= time
, dk_ndrive
* sizeof (long));
bcopy(from
->dk_wds
, to
->dk_wds
= wds
, dk_ndrive
* sizeof (long));
bcopy(from
->dk_seek
, to
->dk_seek
= seek
, dk_ndrive
* sizeof (long));
bcopy(from
->dk_xfer
, to
->dk_xfer
= xfer
, dk_ndrive
* sizeof (long));
bcopy(from
->intrcnt
, to
->intrcnt
= intrcnt
, nintr
* sizeof (int));
double words
, atime
, itime
, xtime
;
words
= s
.dk_wds
[dn
]*32.0; /* number of words transferred */
xtime
= dk_mspw
[dn
]*words
; /* transfer time */
itime
= atime
- xtime
; /* time not transferring */
itime
+= xtime
, xtime
= 0;
xtime
+= itime
, itime
= 0;
putint((int)((float)s
.dk_seek
[dn
]/etime
+0.5), DISKROW
+ 1, c
, 5);
putint((int)((float)s
.dk_xfer
[dn
]/etime
+0.5), DISKROW
+ 2, c
, 5);
putint((int)(words
/etime
/512.0 + 0.5), DISKROW
+ 3, c
, 5);
putfloat(itime
*1000.0/s
.dk_seek
[dn
], DISKROW
+ 4, c
, 5, 1, 1);
putint(0, DISKROW
+ 4, c
, 5);