ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/wm/memory.b/
implement WmMemory;
include "sys.m";
sys: Sys;
include "draw.m";
draw: Draw;
Display, Image, Rect: import draw;
include "tk.m";
tk: Tk;
t: ref Tk->Toplevel;
include "tkclient.m";
tkclient: Tkclient;
WmMemory: module
{
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
Arena: adt
{
name: string;
limit: int;
size: int;
hw: int;
allocs: int;
frees: int;
exts: int;
chunk: int;
y: int;
tag: string;
tagsz: string;
taghw: string;
tagiu: string;
};
a := array[10] of Arena;
mem_cfg := array[] of {
"canvas .c -width 240 -height 45",
"pack .c",
"update",
};
init(ctxt: ref Draw->Context, nil: list of string)
{
spawn realinit(ctxt);
}
realinit(ctxt: ref Draw->Context)
{
sys = load Sys Sys->PATH;
if (ctxt == nil) {
sys->fprint(sys->fildes(2), "memory: no window context\n");
raise "fail:bad context";
}
draw = load Draw Draw->PATH;
tk = load Tk Tk->PATH;
tkclient = load Tkclient Tkclient->PATH;
sys->pctl(Sys->NEWPGRP, nil);
tkclient->init();
menubut := chan of string;
(t, menubut) = tkclient->toplevel(ctxt, "", "Memory", 0);
for(j := 0; j < len mem_cfg; j++)
cmd(t, mem_cfg[j]);
tkclient->startinput(t, "ptr"::nil);
tkclient->onscreen(t, nil);
tick := chan of int;
spawn ticker(tick);
mfd := sys->open("/dev/memory", sys->OREAD);
n := getmem(mfd);
maxx := initdraw(n);
pid: int;
for(;;) alt {
s := <-t.ctxt.ptr =>
tk->pointer(t, *s);
s := <-t.ctxt.ctl or
s = <-t.wreq or
s = <-menubut =>
if(s == "exit"){
kill(pid);
return;
}
tkclient->wmctl(t, s);
pid = <-tick =>
update(mfd);
for(i := 0; i < n; i++) {
if(a[i].limit <= 0)
continue;
x := int ((big a[i].size * big (230-maxx)) / big a[i].limit);
s := sys->sprint(".c coords %s %d %d %d %d",
a[i].tag,
maxx,
a[i].y + 4,
maxx + x,
a[i].y + 8);
cmd(t, s);
x = int ((big a[i].hw * big (230-maxx)) / big a[i].limit);
s = sys->sprint(".c coords %s %d %d %d %d",
a[i].taghw,
maxx,
a[i].y + 4,
maxx+x,
a[i].y + 8);
cmd(t, s);
s = sys->sprint(".c itemconfigure %s -text '%s", a[i].tagsz, string a[i].size);
cmd(t, s);
s = sys->sprint(".c itemconfigure %s -text '%d", a[i].tagiu, a[i].allocs-a[i].frees);
cmd(t, s);
}
cmd(t, "update");
}
}
ticker(c: chan of int)
{
pid := sys->pctl(0, nil);
for(;;) {
c <-= pid;
sys->sleep(1000);
}
}
initdraw(n: int): int
{
y := 15;
maxx := 0;
for (i := 0; i < n; i++) {
id := cmd(t, ".c create text 5 "+string y+" -anchor w -text "+a[i].name);
r := s2r(cmd(t, ".c bbox " + id));
if (r.max.x > maxx)
maxx = r.max.x;
y += 20;
}
maxx += 5;
y = 15;
for(i = 0; i < n; i++) {
s := sys->sprint(".c create rectangle %d %d 230 %d -fill white", maxx, y+4, y+8);
cmd(t, s);
s = sys->sprint(".c create rectangle %d %d 230 %d -fill white", maxx, y+4, y+8);
a[i].taghw = cmd(t, s);
s = sys->sprint(".c create rectangle %d %d 230 %d -fill red", maxx, y+4, y+8);
a[i].tag = cmd(t, s);
s = sys->sprint(".c create text 230 %d -anchor e -text '%s", y - 2, sizestr(a[i].limit));
cmd(t, s);
s = sys->sprint(".c create text %d %d -anchor w -text '%s", maxx, y - 2, string a[i].size);
a[i].tagsz = cmd(t, s);
s = sys->sprint(".c create text 120 %d -fill red -anchor w -text '%d", y - 2, a[i].allocs-a[i].frees);
a[i].tagiu = cmd(t, s);
a[i].y = y;
y += 20;
}
cmd(t, ".c configure -height "+string y);
cmd(t, "update");
return maxx;
}
sizestr(n: int): string
{
if ((n / 1024) % 1024 == 0)
return string (n / (1024 * 1024)) + "M";
return string (n / 1024) + "K";
}
buf := array[8192] of byte;
update(mfd: ref Sys->FD): int
{
sys->seek(mfd, big 0, Sys->SEEKSTART);
n := sys->read(mfd, buf, len buf);
if(n <= 0)
exit;
(nil, l) := sys->tokenize(string buf[0:n], "\n");
i := 0;
while(l != nil) {
s := hd l;
a[i].size = int s[0:];
a[i].hw = int s[24:];
a[i].allocs = int s[3*12:];
a[i].frees = int s[4*12:];
a[i].exts = int s[5*12:];
a[i++].chunk = int s[6*12:];
l = tl l;
}
return i;
}
getmem(mfd: ref Sys->FD): int
{
n := sys->read(mfd, buf, len buf);
if(n <= 0)
exit;
(nil, l) := sys->tokenize(string buf[0:n], "\n");
i := 0;
while(l != nil) {
s := hd l;
a[i].size = int s[0:];
a[i].limit = int s[12:];
a[i].hw = int s[2*12:];
a[i].allocs = int s[3*12:];
a[i].frees = int s[4*12:];
a[i].exts = int s[5*12:];
a[i].chunk = int s[6*12:];
a[i].name = s[7*12:];
i++;
l = tl l;
}
return i;
}
s2r(s: string): Rect
{
(n, toks) := sys->tokenize(s, " ");
if (n != 4) {
sys->print("'%s' is not a rectangle!\n", s);
raise "bad conversion";
}
r: Rect;
(r.min.x, toks) = (int hd toks, tl toks);
(r.min.y, toks) = (int hd toks, tl toks);
(r.max.x, toks) = (int hd toks, tl toks);
(r.max.y, toks) = (int hd toks, tl toks);
return r;
}
kill(pid: int)
{
fd := sys->open("#p/"+string pid+"/ctl", sys->OWRITE);
if(fd != nil)
sys->fprint(fd, "kill");
}
cmd(top: ref Tk->Toplevel, s: string): string
{
e := tk->cmd(top, s);
if (e != nil && e[0] == '!')
sys->print("memory: tk error on '%s': %s\n", s, e);
return e;
}