pull interrupt stats from event counts
fix disk xfer byte count fix absolute counts - were divided by time interval
This commit is contained in:
parent
54ba9fedfe
commit
24ec5512d1
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vmstat.c,v 1.43 2002/11/01 12:47:58 mrg Exp $ */
|
||||
/* $NetBSD: vmstat.c,v 1.44 2003/01/18 21:02:35 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1983, 1989, 1992, 1993
|
||||
|
@ -38,7 +38,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94";
|
||||
#endif
|
||||
__RCSID("$NetBSD: vmstat.c,v 1.43 2002/11/01 12:47:58 mrg Exp $");
|
||||
__RCSID("$NetBSD: vmstat.c,v 1.44 2003/01/18 21:02:35 dsl Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
@ -50,6 +50,7 @@ __RCSID("$NetBSD: vmstat.c,v 1.43 2002/11/01 12:47:58 mrg Exp $");
|
|||
#include <sys/user.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
|
@ -68,6 +69,7 @@ static struct Info {
|
|||
struct nchstats nchstats;
|
||||
long nchcount;
|
||||
long *intrcnt;
|
||||
u_int64_t *evcnt;
|
||||
} s, s1, s2, z;
|
||||
|
||||
#define cnt s.Cnt
|
||||
|
@ -124,6 +126,8 @@ static struct nlist namelist[] = {
|
|||
{ "_intrcnt" },
|
||||
#define X_EINTRCNT 4
|
||||
{ "_eintrcnt" },
|
||||
#define X_ALLEVENTS 5
|
||||
{ "_allevents" },
|
||||
{ "" },
|
||||
};
|
||||
|
||||
|
@ -159,12 +163,55 @@ static struct nlist namelist[] = {
|
|||
#define MAXDRIVES DK_NDRIVE /* max # to display */
|
||||
#endif
|
||||
|
||||
typedef struct intr_evcnt intr_evcnt_t;
|
||||
struct intr_evcnt {
|
||||
char *ie_group;
|
||||
char *ie_name;
|
||||
u_int64_t *ie_count; /* kernel address... */
|
||||
int ie_loc; /* screen row */
|
||||
} *ie_head;
|
||||
int nevcnt;
|
||||
|
||||
static void
|
||||
get_interrupt_events(void)
|
||||
{
|
||||
struct evcntlist allevents;
|
||||
struct evcnt evcnt, *evptr;
|
||||
intr_evcnt_t *ie;
|
||||
|
||||
if (!NREAD(X_ALLEVENTS, &allevents, sizeof allevents))
|
||||
return;
|
||||
evptr = allevents.tqh_first;
|
||||
for (; evptr != NULL; evptr = evcnt.ev_list.tqe_next) {
|
||||
if (!KREAD(evptr, &evcnt, sizeof evcnt))
|
||||
return;
|
||||
if (evcnt.ev_type != EVCNT_TYPE_INTR)
|
||||
continue;
|
||||
ie_head = realloc(ie_head, sizeof *ie * (nevcnt + 1));
|
||||
if (ie_head == NULL) {
|
||||
error("realloc failed");
|
||||
die(0);
|
||||
}
|
||||
ie = ie_head + nevcnt;
|
||||
ie->ie_group = malloc(evcnt.ev_grouplen + 1);
|
||||
ie->ie_name = malloc(evcnt.ev_namelen + 1);
|
||||
if (ie->ie_group == NULL || ie->ie_name == NULL)
|
||||
return;
|
||||
if (!KREAD(evcnt.ev_group, ie->ie_group, evcnt.ev_grouplen + 1))
|
||||
return;
|
||||
if (!KREAD(evcnt.ev_name, ie->ie_name, evcnt.ev_namelen + 1))
|
||||
return;
|
||||
ie->ie_count = &evptr->ev_count;
|
||||
ie->ie_loc = 0;
|
||||
nevcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
initvmstat(void)
|
||||
{
|
||||
char *intrnamebuf, *cp;
|
||||
int i;
|
||||
static int once = 0;
|
||||
|
||||
if (namelist[0].n_type == 0) {
|
||||
if (kvm_nlist(kd, namelist)) {
|
||||
|
@ -177,47 +224,43 @@ initvmstat(void)
|
|||
}
|
||||
}
|
||||
hertz = stathz ? stathz : hz;
|
||||
if (! dkinit(1))
|
||||
if (!dkinit(1))
|
||||
return(0);
|
||||
|
||||
/* Old style interrupt counts - deprecated */
|
||||
nintr = (namelist[X_EINTRCNT].n_value -
|
||||
namelist[X_INTRCNT].n_value) / sizeof (long);
|
||||
intrloc = calloc(nintr, sizeof (long));
|
||||
intrname = calloc(nintr, sizeof (long));
|
||||
intrnamebuf = malloc(namelist[X_EINTRNAMES].n_value -
|
||||
namelist[X_INTRNAMES].n_value);
|
||||
if (intrnamebuf == NULL || intrname == 0 || intrloc == 0) {
|
||||
error("Out of memory\n");
|
||||
if (intrnamebuf)
|
||||
free(intrnamebuf);
|
||||
if (intrname)
|
||||
free(intrname);
|
||||
if (intrloc)
|
||||
free(intrloc);
|
||||
nintr = 0;
|
||||
return(0);
|
||||
if (dk_ndrive && !once) {
|
||||
#define allocate(e, t) \
|
||||
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));
|
||||
once = 1;
|
||||
#undef allocate
|
||||
}
|
||||
if (nintr == 0) {
|
||||
nintr = (namelist[X_EINTRCNT].n_value -
|
||||
namelist[X_INTRCNT].n_value) / sizeof (long);
|
||||
intrloc = calloc(nintr, sizeof (long));
|
||||
intrname = calloc(nintr, sizeof (long));
|
||||
intrnamebuf = malloc(namelist[X_EINTRNAMES].n_value -
|
||||
namelist[X_INTRNAMES].n_value);
|
||||
if (intrnamebuf == NULL || intrname == 0 || intrloc == 0) {
|
||||
error("Out of memory\n");
|
||||
if (intrnamebuf)
|
||||
free(intrnamebuf);
|
||||
if (intrname)
|
||||
free(intrname);
|
||||
if (intrloc)
|
||||
free(intrloc);
|
||||
nintr = 0;
|
||||
return(0);
|
||||
}
|
||||
NREAD(X_INTRNAMES, intrnamebuf, NVAL(X_EINTRNAMES) -
|
||||
NVAL(X_INTRNAMES));
|
||||
for (cp = intrnamebuf, i = 0; i < nintr; i++) {
|
||||
intrname[i] = cp;
|
||||
cp += strlen(cp) + 1;
|
||||
}
|
||||
nextintsrow = INTSROW + 2;
|
||||
allocinfo(&s);
|
||||
allocinfo(&s1);
|
||||
allocinfo(&s2);
|
||||
allocinfo(&z);
|
||||
NREAD(X_INTRNAMES, intrnamebuf, NVAL(X_EINTRNAMES) -
|
||||
NVAL(X_INTRNAMES));
|
||||
for (cp = intrnamebuf, i = 0; i < nintr; i++) {
|
||||
intrname[i] = cp;
|
||||
cp += strlen(cp) + 1;
|
||||
}
|
||||
|
||||
/* event counter interrupt counts */
|
||||
get_interrupt_events();
|
||||
|
||||
nextintsrow = INTSROW + 2;
|
||||
allocinfo(&s);
|
||||
allocinfo(&s1);
|
||||
allocinfo(&s2);
|
||||
allocinfo(&z);
|
||||
|
||||
getinfo(&s2, RUN);
|
||||
copyinfo(&s2, &s1);
|
||||
return(1);
|
||||
|
@ -234,6 +277,36 @@ fetchvmstat(void)
|
|||
getinfo(&s, state);
|
||||
}
|
||||
|
||||
static void
|
||||
print_ie_title(int i)
|
||||
{
|
||||
int width, name_width, group_width;
|
||||
|
||||
width = COLS - (INTSCOL + 9);
|
||||
if (width <= 0)
|
||||
return;
|
||||
|
||||
move(ie_head[i].ie_loc, INTSCOL + 9);
|
||||
group_width = strlen(ie_head[i].ie_group);
|
||||
name_width = strlen(ie_head[i].ie_name);
|
||||
width -= group_width + 1 + name_width;
|
||||
if (width < 0) {
|
||||
/* screen to narrow for full strings */
|
||||
width = -width;
|
||||
group_width -= (width + 1) / 2;
|
||||
name_width -= width / 2;
|
||||
if (group_width <= 3 || name_width < 0) {
|
||||
/* don't display group */
|
||||
name_width += group_width + 1;
|
||||
group_width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (group_width)
|
||||
printw("%-.*s ", group_width, ie_head[i].ie_group);
|
||||
printw("%-.*s", name_width, ie_head[i].ie_name);
|
||||
}
|
||||
|
||||
void
|
||||
labelvmstat(void)
|
||||
{
|
||||
|
@ -301,6 +374,11 @@ labelvmstat(void)
|
|||
continue;
|
||||
mvprintw(intrloc[i], INTSCOL + 9, "%-8.8s", intrname[i]);
|
||||
}
|
||||
for (i = 0; i < nevcnt; i++) {
|
||||
if (ie_head[i].ie_loc == 0)
|
||||
continue;
|
||||
print_ie_title(i);
|
||||
}
|
||||
}
|
||||
|
||||
#define X(fld) {t=s.fld[i]; s.fld[i]-=s1.fld[i]; if(state==TIME) s1.fld[i]=t;}
|
||||
|
@ -321,11 +399,13 @@ showvmstat(void)
|
|||
int i, l, c;
|
||||
static int failcnt = 0;
|
||||
|
||||
if (state == TIME)
|
||||
if (state == TIME) {
|
||||
dkswap();
|
||||
etime = cur.cp_etime;
|
||||
if ((etime * hertz) < 1.0) { /* < 5 ticks - ignore this trash */
|
||||
if (failcnt++ >= MAXFAIL) {
|
||||
etime = cur.cp_etime;
|
||||
/* < 5 ticks - ignore this trash */
|
||||
if ((etime * hertz) < 1.0) {
|
||||
if (failcnt++ > MAXFAIL)
|
||||
return;
|
||||
clear();
|
||||
mvprintw(2, 10, "The alternate system clock has died!");
|
||||
mvprintw(3, 10, "Reverting to ``pigs'' display.");
|
||||
|
@ -334,9 +414,11 @@ showvmstat(void)
|
|||
failcnt = 0;
|
||||
sleep(5);
|
||||
command("pigs");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else
|
||||
etime = 1.0;
|
||||
|
||||
failcnt = 0;
|
||||
inttotal = 0;
|
||||
for (i = 0; i < nintr; i++) {
|
||||
|
@ -354,6 +436,20 @@ showvmstat(void)
|
|||
inttotal += l;
|
||||
putint(l, intrloc[i], INTSCOL, 8);
|
||||
}
|
||||
for (i = 0; i < nevcnt; i++) {
|
||||
if (s.evcnt[i] == 0)
|
||||
continue;
|
||||
if (ie_head[i].ie_loc == 0) {
|
||||
if (nextintsrow == LINES)
|
||||
continue;
|
||||
ie_head[i].ie_loc = nextintsrow++;
|
||||
print_ie_title(i);
|
||||
}
|
||||
X(evcnt);
|
||||
l = (int)((float)s.evcnt[i]/etime + 0.5);
|
||||
inttotal += l;
|
||||
putint(l, ie_head[i].ie_loc, 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);
|
||||
|
@ -466,8 +562,7 @@ vmstat_run(char *args)
|
|||
}
|
||||
|
||||
void
|
||||
vmstat_time (args)
|
||||
char * args;
|
||||
vmstat_time(char *args)
|
||||
{
|
||||
state = TIME;
|
||||
}
|
||||
|
@ -519,7 +614,7 @@ cputime(int indx)
|
|||
}
|
||||
|
||||
static void
|
||||
puthumanint(int n, int l, int c, int w)
|
||||
puthumanint(u_int64_t n, int l, int c, int w)
|
||||
{
|
||||
char b[128];
|
||||
|
||||
|
@ -528,8 +623,7 @@ puthumanint(int n, int l, int c, int w)
|
|||
hline(' ', w);
|
||||
return;
|
||||
}
|
||||
if (humanize_number(b, w, (int64_t)n * 1024, "", HN_AUTOSCALE,
|
||||
HN_NOSPACE) == -1 ) {
|
||||
if (humanize_number(b, w, n, "", HN_AUTOSCALE, HN_NOSPACE) == -1 ) {
|
||||
hline('*', w);
|
||||
return;
|
||||
}
|
||||
|
@ -579,10 +673,13 @@ getinfo(struct Info *s, enum state st)
|
|||
{
|
||||
int mib[2];
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
dkreadstats();
|
||||
NREAD(X_NCHSTATS, &s->nchstats, sizeof s->nchstats);
|
||||
NREAD(X_INTRCNT, s->intrcnt, nintr * LONG);
|
||||
for (i = 0; i < nevcnt; i++)
|
||||
KREAD(ie_head[i].ie_count, &s->evcnt[i], sizeof s->evcnt[i]);
|
||||
size = sizeof(s->uvmexp);
|
||||
mib[0] = CTL_VM;
|
||||
mib[1] = VM_UVMEXP2;
|
||||
|
@ -603,8 +700,12 @@ static void
|
|||
allocinfo(struct Info *s)
|
||||
{
|
||||
|
||||
if ((s->intrcnt = malloc(nintr * sizeof(long))) == NULL) {
|
||||
error("malloc failed");
|
||||
if ((s->intrcnt = calloc(nintr, sizeof(long))) == NULL) {
|
||||
error("calloc failed");
|
||||
die(0);
|
||||
}
|
||||
if ((s->evcnt = calloc(nevcnt, sizeof(u_int64_t))) == NULL) {
|
||||
error("calloc failed");
|
||||
die(0);
|
||||
}
|
||||
}
|
||||
|
@ -613,16 +714,19 @@ static void
|
|||
copyinfo(struct Info *from, struct Info *to)
|
||||
{
|
||||
long *intrcnt;
|
||||
u_int64_t *evcnt;
|
||||
|
||||
intrcnt = to->intrcnt;
|
||||
evcnt = to->evcnt;
|
||||
*to = *from;
|
||||
memmove(to->intrcnt = intrcnt, from->intrcnt, nintr * sizeof (int));
|
||||
memmove(to->evcnt = evcnt, from->evcnt, nevcnt * sizeof *evcnt);
|
||||
}
|
||||
|
||||
static void
|
||||
dinfo(int dn, int c)
|
||||
{
|
||||
double words, atime;
|
||||
double atime;
|
||||
|
||||
c = DISKCOL + c * 5;
|
||||
|
||||
|
@ -630,13 +734,11 @@ dinfo(int dn, int c)
|
|||
atime = (double)cur.dk_time[dn].tv_sec +
|
||||
((double)cur.dk_time[dn].tv_usec / (double)1000000);
|
||||
|
||||
/* # of k transferred */
|
||||
words = (cur.dk_rbytes[dn] | cur.dk_wbytes[dn]) / 1024.0;
|
||||
|
||||
putint((int)((float)cur.dk_seek[dn]/etime+0.5), DISKROW + 1, c, 5);
|
||||
putint((int)((float)(cur.dk_rxfer[dn]+cur.dk_wxfer[dn])/etime+0.5),
|
||||
DISKROW + 2, c, 5);
|
||||
puthumanint((int)(words/etime + 0.5), DISKROW + 3, c, 5);
|
||||
puthumanint((cur.dk_rbytes[dn] + cur.dk_wbytes[dn]) / etime + 0.5,
|
||||
DISKROW + 3, c, 5);
|
||||
if (atime*100.0/etime >= 100)
|
||||
putint(100, DISKROW + 4, c, 5);
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue