#include <u.h>
#include <libc.h>
#include <ctype.h>
-#include <auth.h>
-#include <fcall.h>
#include <draw.h>
#include <event.h>
+#include <keyboard.h>
#define MAXNUM 10 /* maximum number of numbers on data line */
Swap,
Maxswap,
+ Kern,
+ Maxkern,
+ Draw,
+ Maxdraw,
+
/* /dev/sysstats */
Procno = 0,
Context,
int tempfd;
int disable;
- uvlong devswap[4];
+ uvlong devswap[8];
uvlong devsysstat[10];
uvlong prevsysstat[10];
int nproc;
enum
{
Mainproc,
- Mouseproc,
+ Inputproc,
NPROC,
};
Mload,
Mmem,
Mswap,
+ Mkern,
+ Mdraw,
Msyscall,
Mtlbmiss,
Mtlbpurge,
"add load ",
"add mem ",
"add swap ",
+ "add kern ",
+ "add draw ",
"add syscall ",
"add tlbmiss ",
"add tlbpurge",
idleval(Machine*, uvlong*, uvlong*, int),
memval(Machine*, uvlong*, uvlong*, int),
swapval(Machine*, uvlong*, uvlong*, int),
+ kernval(Machine*, uvlong*, uvlong*, int),
+ drawval(Machine*, uvlong*, uvlong*, int),
syscallval(Machine*, uvlong*, uvlong*, int),
tlbmissval(Machine*, uvlong*, uvlong*, int),
tlbpurgeval(Machine*, uvlong*, uvlong*, int),
loadval,
memval,
swapval,
+ kernval,
+ drawval,
syscallval,
tlbmissval,
tlbpurgeval,
Image *cols[Ncolor][3];
Graph *graph;
Machine *mach;
-Font *mediumfont;
char *mysysname;
-char argchars[] = "8bceEfiImlnpstwz";
+char argchars[] = "8bcdeEfiIkmlnpstwz";
int pids[NPROC];
int parity; /* toggled to avoid patterns in textured background */
int nmach;
double scale = 1.0;
int logscale = 0;
int ylabels = 0;
-int oldsystem = 0;
int sleeptime = 1000;
-char *procnames[NPROC] = {"main", "mouse"};
+char *procnames[NPROC] = {"main", "input"};
void
killall(char *s)
void
colinit(void)
{
- mediumfont = openfont(display, "/lib/font/bit/pelm/latin1.8.font");
- if(mediumfont == nil)
- mediumfont = font;
-
/* Peach */
mkcol(0, 0xFFAAAAFF, 0xFFAAAAFF, 0xBB5D5DFF);
/* Aqua */
maxw = 0;
r[1] = '\0';
for(s=text; *s; ){
- if(p.y+mediumfont->height-Ysqueeze > maxy)
+ if(p.y+font->height-Ysqueeze > maxy)
break;
w = chartorune(r, s);
s += w;
- w = runestringwidth(mediumfont, r);
+ w = runestringwidth(font, r);
if(w > maxw)
maxw = w;
- runestring(screen, p, display->black, ZP, mediumfont, r);
- p.y += mediumfont->height-Ysqueeze;
+ runestring(screen, p, display->black, ZP, font, r);
+ p.y += font->height-Ysqueeze;
}
}
y = (y+2.)/3.;
}
}
+ if(y >= 1.)
+ y = 1;
+ if(y <= 0.)
+ y = 0;
p.y = g->r.max.y - Dy(g->r)*y - Dot;
if(p.y < g->r.min.y)
p.y = g->r.min.y;
g->overflow = 1;
draw(g->overtmp, g->overtmp->r, screen, nil, g->overtmp->r.min);
sprint(buf, "%llud", v);
- string(screen, g->overtmp->r.min, display->black, ZP, mediumfont, buf);
+ string(screen, g->overtmp->r.min, display->black, ZP, font, buf);
}
}
return i == n;
}
-/* Network on fd1, mount driver on fd0 */
-static int
-filter(int fd)
-{
- int p[2];
-
- if(pipe(p) < 0){
- fprint(2, "stats: can't pipe: %r\n");
- killall("pipe");
- }
-
- switch(rfork(RFNOWAIT|RFPROC|RFFDG)) {
- case -1:
- sysfatal("rfork record module");
- case 0:
- dup(fd, 1);
- close(fd);
- dup(p[0], 0);
- close(p[0]);
- close(p[1]);
- execl("/bin/aux/fcall", "fcall", nil);
- fprint(2, "stats: can't exec fcall: %r\n");
- killall("fcall");
- default:
- close(fd);
- close(p[0]);
- }
- return p[1];
-}
-
-/*
- * 9fs
- */
-int
-connect9fs(char *addr)
-{
- char dir[256], *na;
- int fd;
-
- fprint(2, "connect9fs...");
- na = netmkaddr(addr, 0, "9fs");
-
- fprint(2, "dial %s...", na);
- if((fd = dial(na, 0, dir, 0)) < 0)
- return -1;
-
- fprint(2, "dir %s...", dir);
-// if(strstr(dir, "tcp"))
-// fd = filter(fd);
- return fd;
-}
-
-int
-old9p(int fd)
-{
- int p[2];
-
- if(pipe(p) < 0)
- return -1;
-
- switch(rfork(RFPROC|RFFDG|RFNAMEG)) {
- case -1:
- return -1;
- case 0:
- if(fd != 1){
- dup(fd, 1);
- close(fd);
- }
- if(p[0] != 0){
- dup(p[0], 0);
- close(p[0]);
- }
- close(p[1]);
- if(0){
- fd = open("/sys/log/cpu", OWRITE);
- if(fd != 2){
- dup(fd, 2);
- close(fd);
- }
- execl("/bin/srvold9p", "srvold9p", "-ds", nil);
- } else
- execl("/bin/srvold9p", "srvold9p", "-s", nil);
- return -1;
- default:
- close(fd);
- close(p[0]);
- }
- return p[1];
-}
-
-
-/*
- * exportfs
- */
-int
-connectexportfs(char *addr)
-{
- char buf[ERRMAX], dir[256], *na;
- int fd, n;
- char *tree;
- AuthInfo *ai;
-
- tree = "/";
- na = netmkaddr(addr, 0, "exportfs");
- if((fd = dial(na, 0, dir, 0)) < 0)
- return -1;
-
- ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client");
- if(ai == nil)
- return -1;
-
- n = write(fd, tree, strlen(tree));
- if(n < 0){
- close(fd);
- return -1;
- }
-
- strcpy(buf, "can't read tree");
- n = read(fd, buf, sizeof buf - 1);
- if(n!=2 || buf[0]!='O' || buf[1]!='K'){
- buf[sizeof buf - 1] = '\0';
- werrstr("bad remote tree: %s\n", buf);
- close(fd);
- return -1;
- }
-
-// if(strstr(dir, "tcp"))
-// fd = filter(fd);
-
- if(oldsystem)
- return old9p(fd);
-
- return fd;
-}
-
int
readswap(Machine *m, uvlong *a)
{
a[1] = a[4];
a[2] = a[5];
a[3] = a[6];
+
+ a[4] = 0;
+ a[5] = 0;
+ if(m->bufp = strstr(m->buf, "kernel malloc")){
+ while(m->bufp > m->buf && m->bufp[-1] != '\n')
+ m->bufp--;
+ a[4] = strtoull(m->bufp, &m->bufp, 10);
+ while(*m->bufp++ == '/')
+ a[5] = strtoull(m->bufp, &m->bufp, 10);
+ }
+
+ a[6] = 0;
+ a[7] = 0;
+ if(m->bufp = strstr(m->buf, "kernel draw")){
+ while(m->bufp > m->buf && m->bufp[-1] != '\n')
+ m->bufp--;
+ a[6] = strtoull(m->bufp, &m->bufp, 10);
+ while(*m->bufp++ == '/')
+ a[7] = strtoull(m->bufp, &m->bufp, 10);
+ }
+
return 1;
}
- return readnums(m, nelem(m->devswap), a, 0);
+
+ a[4] = 0;
+ a[5] = 0;
+ a[6] = 0;
+ a[7] = 0;
+ return readnums(m, 4, a, 0);
}
char*
int
initmach(Machine *m, char *name)
{
- int n, fd;
+ int n;
uvlong a[MAXNUM];
char *p, mpt[256], buf[256];
if(m->remote == 0)
strcpy(mpt, "");
else{
+ Waitmsg *w;
+ int pid;
+
snprint(mpt, sizeof mpt, "/n/%s", p);
- fd = connectexportfs(name);
- if(fd < 0){
- fprint(2, "can't connect to %s: %r\n", name);
+ snprint(buf, sizeof buf, "rimport %q / %q || import %q / %q", name, mpt, name, mpt);
+
+ pid = fork();
+ switch(pid){
+ case -1:
+ fprint(2, "can't fork: %r\n");
return 0;
+ case 0:
+ execl("/bin/rc", "rc", "-c", buf, nil);
+ fprint(2, "can't exec: %r\n");
+ exits("exec");
}
- /* BUG? need to use amount() now? */
- if(mount(fd, -1, mpt, MREPL, "") < 0){
- fprint(2, "stats: mount %s on %s failed (%r); trying /n/sid\n", name, mpt);
- strcpy(mpt, "/n/sid");
- if(mount(fd, -1, mpt, MREPL, "") < 0){
- fprint(2, "stats: mount %s on %s failed: %r\n", name, mpt);
- return 0;
- }
+ w = wait();
+ if(w == nil || w->pid != pid || w->msg[0] != '\0'){
+ free(w);
+ return 0;
}
+ free(w);
}
snprint(buf, sizeof buf, "%s/dev/swap", mpt);
m->swapfd = open(buf, OREAD);
if(loadbuf(m, &m->swapfd) && readswap(m, a))
memmove(m->devswap, a, sizeof m->devswap);
- else{
- m->devswap[Maxswap] = 100;
- m->devswap[Maxmem] = 100;
- }
snprint(buf, sizeof buf, "%s/dev/sysstat", mpt);
m->statsfd = open(buf, OREAD);
snprint(buf, sizeof buf, "%s/mnt/apm/battery", mpt);
m->batteryfd = open(buf, OREAD);
+ if(m->batteryfd < 0){
+ snprint(buf, sizeof buf, "%s/mnt/acpi/battery", mpt);
+ m->batteryfd = open(buf, OREAD);
+ }
m->bitsybatfd = -1;
if(m->batteryfd >= 0){
if(loadbuf(m, &m->batteryfd) && readnums(m, nelem(m->batterystats), a, 0))
}
snprint(buf, sizeof buf, "%s/dev/cputemp", mpt);
m->tempfd = open(buf, OREAD);
+ if(m->tempfd < 0){
+ snprint(buf, sizeof buf, "%s/mnt/acpi/cputemp", mpt);
+ m->tempfd = open(buf, OREAD);
+ }
if(loadbuf(m, &m->tempfd))
for(n=0; n < nelem(m->temp) && readnums(m, 2, a, 0); n++)
m->temp[n] = a[0];
jmp_buf catchalarm;
-void
+int
alarmed(void *a, char *s)
{
if(strcmp(s, "alarm") == 0)
notejmp(a, catchalarm, 1);
- noted(NDFLT);
+ return 0;
}
int
needswap(int init)
{
- return init | present[Mmem] | present[Mswap];
+ return init | present[Mmem] | present[Mswap] | present[Mkern] | present[Mdraw];
}
eresized(0);
}
if(m->remote){
- notify(alarmed);
+ atnotify(alarmed, 1);
alarm(5000);
}
if(needswap(init) && loadbuf(m, &m->swapfd) && readswap(m, a))
m->temp[n] = a[0];
if(m->remote){
alarm(0);
- notify(nil);
+ atnotify(alarmed, 0);
}
}
{
*v = m->devswap[Mem];
*vmax = m->devswap[Maxmem];
+ if(*vmax == 0)
+ *vmax = 1;
}
void
{
*v = m->devswap[Swap];
*vmax = m->devswap[Maxswap];
+ if(*vmax == 0)
+ *vmax = 1;
+}
+
+void
+kernval(Machine *m, uvlong *v, uvlong *vmax, int)
+{
+ *v = m->devswap[Kern];
+ *vmax = m->devswap[Maxkern];
+ if(*vmax == 0)
+ *vmax = 1;
+}
+
+void
+drawval(Machine *m, uvlong *v, uvlong *vmax, int)
+{
+ *v = m->devswap[Draw];
+ *vmax = m->devswap[Maxdraw];
+ if(*vmax == 0)
+ *vmax = 1;
}
void
contextval(Machine *m, uvlong *v, uvlong *vmax, int init)
{
- *v = m->devsysstat[Context]-m->prevsysstat[Context];
+ *v = (m->devsysstat[Context]-m->prevsysstat[Context])&0xffffffff;
*vmax = sleeptime*m->nproc;
if(init)
*vmax = sleeptime;
void
intrval(Machine *m, uvlong *v, uvlong *vmax, int init)
{
- *v = m->devsysstat[Interrupt]-m->prevsysstat[Interrupt];
+ *v = (m->devsysstat[Interrupt]-m->prevsysstat[Interrupt])&0xffffffff;
*vmax = sleeptime*m->nproc*10;
if(init)
*vmax = sleeptime*10;
void
syscallval(Machine *m, uvlong *v, uvlong *vmax, int init)
{
- *v = m->devsysstat[Syscall]-m->prevsysstat[Syscall];
+ *v = (m->devsysstat[Syscall]-m->prevsysstat[Syscall])&0xffffffff;
*vmax = sleeptime*m->nproc;
if(init)
*vmax = sleeptime;
void
faultval(Machine *m, uvlong *v, uvlong *vmax, int init)
{
- *v = m->devsysstat[Fault]-m->prevsysstat[Fault];
+ *v = (m->devsysstat[Fault]-m->prevsysstat[Fault])&0xffffffff;
*vmax = sleeptime*m->nproc;
if(init)
*vmax = sleeptime;
void
tlbmissval(Machine *m, uvlong *v, uvlong *vmax, int init)
{
- *v = m->devsysstat[TLBfault]-m->prevsysstat[TLBfault];
+ *v = (m->devsysstat[TLBfault]-m->prevsysstat[TLBfault])&0xffffffff;
*vmax = (sleeptime/1000)*10*m->nproc;
if(init)
*vmax = (sleeptime/1000)*10;
void
tlbpurgeval(Machine *m, uvlong *v, uvlong *vmax, int init)
{
- *v = m->devsysstat[TLBpurge]-m->prevsysstat[TLBpurge];
+ *v = (m->devsysstat[TLBpurge]-m->prevsysstat[TLBpurge])&0xffffffff;
*vmax = (sleeptime/1000)*10*m->nproc;
if(init)
*vmax = (sleeptime/1000)*10;
uvlong v, vmax;
g->newvalue(g->mach, &v, &vmax, 1);
+ if(vmax == 0)
+ vmax = 1;
if(logscale){
for(j=1; j<=2; j++)
sprint(strs[j-1], "%g", scale*pow(10., j)*(double)vmax/100.);
/* choose value for rightmost graph */
labelstrs(&graph[ngraph*(nmach-1)+i], strs, &n);
for(j=0; j<n; j++){
- w = stringwidth(mediumfont, strs[j]);
+ w = stringwidth(font, strs[j]);
if(w > maxw)
maxw = w;
}
/* label left edge */
x = screen->r.min.x;
- y = screen->r.min.y + Labspace+mediumfont->height+Labspace;
+ y = screen->r.min.y + Labspace+font->height+Labspace;
dy = (screen->r.max.y - y)/ngraph;
- dx = Labspace+stringwidth(mediumfont, "0")+Labspace;
+ dx = Labspace+stringwidth(font, "0")+Labspace;
startx = x+dx+1;
starty = y;
for(i=0; i<ngraph; i++,y+=dy){
dx = (screen->r.max.x - startx)/nmach;
for(x=startx, i=0; i<nmach; i++,x+=dx){
draw(screen, Rect(x-1, starty-1, x, screen->r.max.y), display->black, nil, ZP);
- j = dx/stringwidth(mediumfont, "0");
+ j = dx/stringwidth(font, "0");
n = mach[i].nproc;
if(n>1 && j>=1+3+mach[i].lgproc){ /* first char of name + (n) */
j -= 3+mach[i].lgproc;
snprint(buf, sizeof buf, "%.*s(%d)", j, mach[i].shortname, n);
}else
snprint(buf, sizeof buf, "%.*s", j, mach[i].shortname);
- string(screen, Pt(x+Labspace, screen->r.min.y + Labspace), display->black, ZP, mediumfont, buf);
+ string(screen, Pt(x+Labspace, screen->r.min.y + Labspace), display->black, ZP, font, buf);
}
maxx = screen->r.max.x;
/* label right, if requested */
- if(ylabels && dy>Nlab*(mediumfont->height+1)){
+ if(ylabels && dy>Nlab*(font->height+1)){
wid = labelwidth();
if(wid < (maxx-startx)-30){
/* else there's not enough room */
for(k=0; k<nlab; k++){
ly = y + (dy*(nlab-k)/(nlab+1));
draw(screen, Rect(maxx+1, ly, maxx+1+Lx, ly+1), display->black, nil, ZP);
- ly -= mediumfont->height/2;
- string(screen, Pt(maxx+1+Lx, ly), display->black, ZP, mediumfont, labs[k]);
+ ly -= font->height/2;
+ string(screen, Pt(maxx+1+Lx, ly), display->black, ZP, font, labs[k]);
}
}
}
draw(screen, g->r, cols[g->colindex][0], nil, paritypt(g->r.min.x));
g->overflow = 0;
r = g->r;
- r.max.y = r.min.y+mediumfont->height;
- r.max.x = r.min.x+stringwidth(mediumfont, "999999999999");
+ r.max.y = r.min.y+font->height;
+ r.max.x = r.min.x+stringwidth(font, "999999999999");
freeimage(g->overtmp);
g->overtmp = nil;
if(r.max.x <= g->r.max.x)
}
void
-mouseproc(void)
+inputproc(void)
{
- Mouse mouse;
+ Event e;
int i;
for(;;){
- mouse = emouse();
- if(mouse.buttons == 4){
- lockdisplay(display);
- for(i=0; i<Nmenu2; i++)
- if(present[i])
- memmove(menu2str[i], "drop ", Opwid);
- else
- memmove(menu2str[i], "add ", Opwid);
- i = emenuhit(3, &mouse, &menu2);
- if(i >= 0){
- if(!present[i])
- addgraph(i);
- else if(ngraph > 1)
- dropgraph(i);
- resize();
+ switch(eread(Emouse|Ekeyboard, &e)){
+ case Emouse:
+ if(e.mouse.buttons == 4){
+ lockdisplay(display);
+ for(i=0; i<Nmenu2; i++)
+ if(present[i])
+ memmove(menu2str[i], "drop ", Opwid);
+ else
+ memmove(menu2str[i], "add ", Opwid);
+ i = emenuhit(3, &e.mouse, &menu2);
+ if(i >= 0){
+ if(!present[i])
+ addgraph(i);
+ else if(ngraph > 1)
+ dropgraph(i);
+ resize();
+ }
+ unlockdisplay(display);
}
- unlockdisplay(display);
+ break;
+ case Ekeyboard:
+ if(e.kbdc==Kdel || e.kbdc=='q')
+ killall(nil);
+ break;
}
}
}
uvlong v, vmax, nargs;
char args[100];
+ quotefmtinstall();
+
nmach = 1;
mysysname = getenv("sysname");
if(mysysname == nil){
fprint(2, "stats: can't find $sysname: %r\n");
exits("sysname");
}
- mysysname = estrdup(mysysname);
nargs = 0;
ARGBEGIN{
ylabels++;
break;
case 'O':
- oldsystem = 1;
break;
default:
if(nargs>=sizeof args || strchr(argchars, ARGC())==nil)
initmach(&mach[0], mysysname);
readmach(&mach[0], 1);
}else{
+ rfork(RFNAMEG);
for(i=j=0; i<argc; i++){
if (addmachine(argv[i]))
readmach(&mach[j++], 1);
case 'w':
addgraph(Mswap);
break;
+ case 'k':
+ addgraph(Mkern);
+ break;
+ case 'd':
+ addgraph(Mdraw);
+ break;
case 'z':
addgraph(Mtemp);
break;
fprint(2, "stats: initdraw failed: %r\n");
exits("initdraw");
}
+ display->locking = 1; /* tell library we're using the display lock */
colinit();
- einit(Emouse);
- notify(nil);
- startproc(mouseproc, Mouseproc);
+ einit(Emouse|Ekeyboard);
+ startproc(inputproc, Inputproc);
pids[Mainproc] = getpid();
- display->locking = 1; /* tell library we're using the display lock */
resize();