📄 stats.c
字号:
{ return init | present[Mmem] | present[Mswap];}intneedstat(int init){ return init | present[Mcontext] | present[Mfault] | present[Mintr] | present[Mload] | present[Midle] | present[Minintr] | present[Msyscall] | present[Mtlbmiss] | present[Mtlbpurge];}intneedether(int init){ return init | present[Mether] | present[Metherin] | present[Metherout] | present[Methererr];}intneedbattery(int init){ return init | present[Mbattery];}intneedsignal(int init){ return init | present[Msignal];}voidreadmach(Machine *m, int init){ int n, i; ulong a[8]; char buf[32]; if(m->remote && (m->disable || setjmp(catchalarm))){ if (m->disable++ >= 5) m->disable = 0; /* give it another chance */ memmove(m->devsysstat, m->prevsysstat, sizeof m->devsysstat); memmove(m->netetherstats, m->prevetherstats, sizeof m->netetherstats); return; } snprint(buf, sizeof buf, "%s", m->name); if (strcmp(m->name, buf) != 0){ free(m->name); m->name = estrdup(buf); if(display != nil) /* else we're still initializing */ eresized(0); } if(m->remote){ notify(alarmed); alarm(5000); } if(needswap(init) && loadbuf(m, &m->swapfd) && readswap(m, a)) memmove(m->devswap, a, sizeof m->devswap); if(needstat(init) && loadbuf(m, &m->statsfd)){ memmove(m->prevsysstat, m->devsysstat, sizeof m->devsysstat); memset(m->devsysstat, 0, sizeof m->devsysstat); for(n=0; n<m->nproc && readnums(m, nelem(m->devsysstat), a, 0); n++) for(i=0; i<nelem(m->devsysstat); i++) m->devsysstat[i] += a[i]; } if(needether(init) && loadbuf(m, &m->etherfd) && readnums(m, nelem(m->netetherstats), a, 1)){ memmove(m->prevetherstats, m->netetherstats, sizeof m->netetherstats); memmove(m->netetherstats, a, sizeof m->netetherstats); } if(needsignal(init) && loadbuf(m, &m->ifstatsfd) && strncmp(m->buf, "Signal: ", 8)==0 && readnums(m, nelem(m->netetherifstats), a, 1)){ memmove(m->netetherifstats, a, sizeof m->netetherifstats); } if(needbattery(init) && loadbuf(m, &m->batteryfd) && readnums(m, nelem(m->batterystats), a, 0)) memmove(m->batterystats, a, sizeof(m->batterystats)); if(needbattery(init) && loadbuf(m, &m->bitsybatfd) && readnums(m, 1, a, 0)) memmove(m->batterystats, a, sizeof(m->batterystats)); if(m->remote){ alarm(0); notify(nil); }}voidmemval(Machine *m, ulong *v, ulong *vmax, int){ *v = m->devswap[Mem]; *vmax = m->devswap[Maxmem];}voidswapval(Machine *m, ulong *v, ulong *vmax, int){ *v = m->devswap[Swap]; *vmax = m->devswap[Maxswap];}voidcontextval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->devsysstat[Context]-m->prevsysstat[Context]; *vmax = sleeptime*m->nproc; if(init) *vmax = sleeptime;}voidintrval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->devsysstat[Interrupt]-m->prevsysstat[Interrupt]; *vmax = sleeptime*m->nproc; if(init) *vmax = sleeptime;}voidsyscallval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->devsysstat[Syscall]-m->prevsysstat[Syscall]; *vmax = sleeptime*m->nproc; if(init) *vmax = sleeptime;}voidfaultval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->devsysstat[Fault]-m->prevsysstat[Fault]; *vmax = sleeptime*m->nproc; if(init) *vmax = sleeptime;}voidtlbmissval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->devsysstat[TLBfault]-m->prevsysstat[TLBfault]; *vmax = (sleeptime/1000)*10*m->nproc; if(init) *vmax = (sleeptime/1000)*10;}voidtlbpurgeval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->devsysstat[TLBpurge]-m->prevsysstat[TLBpurge]; *vmax = (sleeptime/1000)*10*m->nproc; if(init) *vmax = (sleeptime/1000)*10;}voidloadval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->devsysstat[Load]; *vmax = 1000*m->nproc; if(init) *vmax = 1000;}voididleval(Machine *m, ulong *v, ulong *vmax, int){ *v = m->devsysstat[Idle]/m->nproc; *vmax = 100;}voidinintrval(Machine *m, ulong *v, ulong *vmax, int){ *v = m->devsysstat[InIntr]/m->nproc; *vmax = 100;}voidetherval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->netetherstats[In]-m->prevetherstats[In] + m->netetherstats[Out]-m->prevetherstats[Out]; *vmax = sleeptime*m->nproc; if(init) *vmax = sleeptime;}voidetherinval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->netetherstats[In]-m->prevetherstats[In]; *vmax = sleeptime*m->nproc; if(init) *vmax = sleeptime;}voidetheroutval(Machine *m, ulong *v, ulong *vmax, int init){ *v = m->netetherstats[Out]-m->prevetherstats[Out]; *vmax = sleeptime*m->nproc; if(init) *vmax = sleeptime;}voidethererrval(Machine *m, ulong *v, ulong *vmax, int init){ int i; *v = 0; for(i=Err0; i<nelem(m->netetherstats); i++) *v += m->netetherstats[i]; *vmax = (sleeptime/1000)*10*m->nproc; if(init) *vmax = (sleeptime/1000)*10;}voidbatteryval(Machine *m, ulong *v, ulong *vmax, int){ *v = m->batterystats[0]; if(m->bitsybatfd >= 0) *vmax = 184; // at least on my bitsy... else *vmax = 100;}voidsignalval(Machine *m, ulong *v, ulong *vmax, int){ ulong l; *vmax = sleeptime; l = m->netetherifstats[0]; /* * Range is seen to be from about -45 (strong) to -95 (weak); rescale */ if(l == 0){ /* probably not present */ *v = 0; return; } *v = 20*(l+95);}voidusage(void){ fprint(2, "usage: stats [-O] [-S scale] [-LY] [-%s] [machine...]\n", argchars); exits("usage");}voidaddgraph(int n){ Graph *g, *ograph; int i, j; static int nadd; if(n > nelem(menu2str)) abort(); /* avoid two adjacent graphs of same color */ if(ngraph>0 && graph[ngraph-1].colindex==nadd%Ncolor) nadd++; ograph = graph; graph = emalloc(nmach*(ngraph+1)*sizeof(Graph)); for(i=0; i<nmach; i++) for(j=0; j<ngraph; j++) graph[i*(ngraph+1)+j] = ograph[i*ngraph+j]; free(ograph); ngraph++; for(i=0; i<nmach; i++){ g = &graph[i*ngraph+(ngraph-1)]; memset(g, 0, sizeof(Graph)); g->label = menu2str[n]+Opwid; g->newvalue = newvaluefn[n]; g->update = update1; /* no other update functions yet */ g->mach = &mach[i]; g->colindex = nadd%Ncolor; } present[n] = 1; nadd++;}voiddropgraph(int which){ Graph *ograph; int i, j, n; if(which > nelem(menu2str)) abort(); /* convert n to index in graph table */ n = -1; for(i=0; i<ngraph; i++) if(strcmp(menu2str[which]+Opwid, graph[i].label) == 0){ n = i; break; } if(n < 0){ fprint(2, "stats: internal error can't drop graph\n"); killall("error"); } ograph = graph; graph = emalloc(nmach*(ngraph-1)*sizeof(Graph)); for(i=0; i<nmach; i++){ for(j=0; j<n; j++) graph[i*(ngraph-1)+j] = ograph[i*ngraph+j]; free(ograph[i*ngraph+j].data); freeimage(ograph[i*ngraph+j].overtmp); for(j++; j<ngraph; j++) graph[i*(ngraph-1)+j-1] = ograph[i*ngraph+j]; } free(ograph); ngraph--; present[which] = 0;}intaddmachine(char *name){ if(ngraph > 0){ fprint(2, "stats: internal error: ngraph>0 in addmachine()\n"); usage(); } if(mach == nil) nmach = 0; /* a little dance to get us started with local machine by default */ mach = erealloc(mach, (nmach+1)*sizeof(Machine)); memset(mach+nmach, 0, sizeof(Machine)); if (initmach(mach+nmach, name)){ nmach++; return 1; } else return 0;}voidlabelstrs(Graph *g, char strs[Nlab][Lablen], int *np){ int j; ulong v, vmax; g->newvalue(g->mach, &v, &vmax, 1); if(logscale){ for(j=1; j<=2; j++) sprint(strs[j-1], "%g", scale*pow(10., j)*(double)vmax/100.); *np = 2; }else{ for(j=1; j<=3; j++) sprint(strs[j-1], "%g", scale*(double)j*(double)vmax/4.0); *np = 3; }}intlabelwidth(void){ int i, j, n, w, maxw; char strs[Nlab][Lablen]; maxw = 0; for(i=0; i<ngraph; i++){ /* choose value for rightmost graph */ labelstrs(&graph[ngraph*(nmach-1)+i], strs, &n); for(j=0; j<n; j++){ w = stringwidth(mediumfont, strs[j]); if(w > maxw) maxw = w; } } return maxw;}voidresize(void){ int i, j, k, n, startx, starty, x, y, dx, dy, ly, ondata, maxx, wid, nlab; Graph *g; Rectangle machr, r; ulong v, vmax; char buf[128], labs[Nlab][Lablen]; draw(screen, screen->r, display->white, nil, ZP); /* label left edge */ x = screen->r.min.x; y = screen->r.min.y + Labspace+mediumfont->height+Labspace; dy = (screen->r.max.y - y)/ngraph; dx = Labspace+stringwidth(mediumfont, "0")+Labspace; startx = x+dx+1; starty = y; for(i=0; i<ngraph; i++,y+=dy){ draw(screen, Rect(x, y-1, screen->r.max.x, y), display->black, nil, ZP); draw(screen, Rect(x, y, x+dx, screen->r.max.y), cols[graph[i].colindex][0], nil, paritypt(x)); label(Pt(x, y), dy, graph[i].label); draw(screen, Rect(x+dx, y, x+dx+1, screen->r.max.y), cols[graph[i].colindex][2], nil, ZP); } /* label top edge */ 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"); n = mach[i].nproc; if(n>1 && j>=1+3+(n>10)+(n>100)){ /* first char of name + (n) */ j -= 3+(n>10)+(n>100); if(j <= 0) j = 1; snprint(buf, sizeof buf, "%.*s(%d)", j, mach[i].name, n); }else snprint(buf, sizeof buf, "%.*s", j, mach[i].name); string(screen, Pt(x+Labspace, screen->r.min.y + Labspace), display->black, ZP, mediumfont, buf); } maxx = screen->r.max.x; /* label right, if requested */ if(ylabels && dy>Nlab*(mediumfont->height+1)){ wid = labelwidth(); if(wid < (maxx-startx)-30){ /* else there's not enough room */ maxx -= 1+Lx+wid; draw(screen, Rect(maxx, starty, maxx+1, screen->r.max.y), display->black, nil, ZP); y = starty; for(j=0; j<ngraph; j++, y+=dy){ /* choose value for rightmost graph */ g = &graph[ngraph*(nmach-1)+j]; labelstrs(g, labs, &nlab); r = Rect(maxx+1, y, screen->r.max.x, y+dy-1); if(j == ngraph-1) r.max.y = screen->r.max.y; draw(screen, r, cols[g->colindex][0], nil, paritypt(r.min.x)); 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]); } } } } /* create graphs */ for(i=0; i<nmach; i++){ machr = Rect(startx+i*dx, starty, maxx, screen->r.max.y); if(i < nmach-1) machr.max.x = startx+(i+1)*dx - 1; y = starty; for(j=0; j<ngraph; j++, y+=dy){ g = &graph[i*ngraph+j]; /* allocate data */ ondata = g->ndata; g->ndata = Dx(machr)+1; /* may be too many if label will be drawn here; so what? */ g->data = erealloc(g->data, g->ndata*sizeof(ulong)); if(g->ndata > ondata) memset(g->data+ondata, 0, (g->ndata-ondata)*sizeof(ulong)); /* set geometry */ g->r = machr; g->r.min.y = y; g->r.max.y = y+dy - 1; if(j == ngraph-1) g->r.max.y = screen->r.max.y; 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"); freeimage(g->overtmp); g->overtmp = nil; if(r.max.x <= g->r.max.x) g->overtmp = allocimage(display, r, screen->chan, 0, -1); g->newvalue(g->mach, &v, &vmax, 0); redraw(g, vmax); } } flushimage(display, 1);}voideresized(int new){ lockdisplay(display); if(new && getwindow(display, Refnone) < 0) { fprint(2, "stats: can't reattach to window\n"); killall("reattach"); } resize(); unlockdisplay(display);}voidmouseproc(void){ Mouse mouse; 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(); } unlockdisplay(display); } }}voidstartproc(void (*f)(void), int index){ int pid; switch(pid = rfork(RFPROC|RFMEM|RFNOWAIT)){ case -1: fprint(2, "stats: fork failed: %r\n"); killall("fork failed"); case 0: f(); fprint(2, "stats: %s process exits\n", procnames[index]); if(index >= 0) killall("process died"); exits(nil); } if(index >= 0) pids[index] = pid;}voidmain(int argc, char *argv[]){ int i, j; double secs; ulong v, vmax, nargs; char args[100]; 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{ case 'T': secs = atof(EARGF(usage())); if(secs > 0) sleeptime = 1000*secs; break; case 'S': scale = atof(EARGF(usage())); if(scale <= 0) usage(); break; case 'L': logscale++; break; case 'Y': ylabels++; break; case 'O': oldsystem = 1; break; default: if(nargs>=sizeof args || strchr(argchars, ARGC())==nil) usage(); args[nargs++] = ARGC(); }ARGEND if(argc == 0){ mach = emalloc(nmach*sizeof(Machine)); initmach(&mach[0], mysysname); readmach(&mach[0], 1); }else{ for(i=j=0; i<argc; i++){ if (addmachine(argv[i])) readmach(&mach[j++], 1); } if (j == 0) exits("connect"); } for(i=0; i<nargs; i++) switch(args[i]){ default: fprint(2, "stats: internal error: unknown arg %c\n", args[i]); usage(); case 'b': addgraph(Mbattery); break; case 'c': addgraph(Mcontext); break; case 'e': addgraph(Mether); break; case 'E': addgraph(Metherin); addgraph(Metherout); break; case 'f': addgraph(Mfault); break; case 'i': addgraph(Mintr); break; case 'I': addgraph(Mload); addgraph(Midle); addgraph(Minintr); break; case 'l': addgraph(Mload); break; case 'm': addgraph(Mmem); break; case 'n': addgraph(Metherin); addgraph(Metherout); addgraph(Methererr); break; case 'p': addgraph(Mtlbpurge); break; case 's': addgraph(Msyscall); break; case 't': addgraph(Mtlbmiss); addgraph(Mtlbpurge); break; case '8': addgraph(Msignal); break; case 'w': addgraph(Mswap); break; } if(ngraph == 0) addgraph(Mload); for(i=0; i<nmach; i++) for(j=0; j<ngraph; j++) graph[i*ngraph+j].mach = &mach[i]; if(initdraw(nil, nil, "stats") < 0){ fprint(2, "stats: initdraw failed: %r\n"); exits("initdraw"); } colinit(); einit(Emouse); notify(nil); startproc(mouseproc, Mouseproc); pids[Mainproc] = getpid(); display->locking = 1; /* tell library we're using the display lock */ resize(); unlockdisplay(display); /* display is still locked from initdraw() */ for(;;){ for(i=0; i<nmach; i++) readmach(&mach[i], 0); lockdisplay(display); parity = 1-parity; for(i=0; i<nmach*ngraph; i++){ graph[i].newvalue(graph[i].mach, &v, &vmax, 0); graph[i].update(&graph[i], v, vmax); } flushimage(display, 1); unlockdisplay(display); sleep(sleeptime); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -