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; }