1implement WmMemory; 2 3include "sys.m"; 4 sys: Sys; 5 6include "draw.m"; 7 draw: Draw; 8 Display, Image, Rect: import draw; 9 10include "tk.m"; 11 tk: Tk; 12 t: ref Tk->Toplevel; 13 14include "tkclient.m"; 15 tkclient: Tkclient; 16 17WmMemory: module 18{ 19 init: fn(ctxt: ref Draw->Context, argv: list of string); 20}; 21 22Arena: adt 23{ 24 name: string; 25 limit: int; 26 size: int; 27 hw: int; 28 allocs: int; 29 frees: int; 30 exts: int; 31 chunk: int; 32 y: int; 33 tag: string; 34 tagsz: string; 35 taghw: string; 36 tagiu: string; 37}; 38a := array[10] of Arena; 39 40mem_cfg := array[] of { 41 "canvas .c -width 240 -height 45", 42 "pack .c", 43 "update", 44}; 45 46init(ctxt: ref Draw->Context, nil: list of string) 47{ 48 spawn realinit(ctxt); 49} 50 51realinit(ctxt: ref Draw->Context) 52{ 53 sys = load Sys Sys->PATH; 54 if (ctxt == nil) { 55 sys->fprint(sys->fildes(2), "memory: no window context\n"); 56 raise "fail:bad context"; 57 } 58 draw = load Draw Draw->PATH; 59 tk = load Tk Tk->PATH; 60 tkclient = load Tkclient Tkclient->PATH; 61 sys->pctl(Sys->NEWPGRP, nil); 62 tkclient->init(); 63 64 menubut := chan of string; 65 (t, menubut) = tkclient->toplevel(ctxt, "", "Memory", 0); 66 for(j := 0; j < len mem_cfg; j++) 67 cmd(t, mem_cfg[j]); 68 tkclient->startinput(t, "ptr"::nil); 69 tkclient->onscreen(t, nil); 70 71 tick := chan of int; 72 spawn ticker(tick); 73 74 mfd := sys->open("/dev/memory", sys->OREAD); 75 76 n := getmem(mfd); 77 maxx := initdraw(n); 78 79 pid: int; 80 for(;;) alt { 81 s := <-t.ctxt.ptr => 82 tk->pointer(t, *s); 83 s := <-t.ctxt.ctl or 84 s = <-t.wreq or 85 s = <-menubut => 86 if(s == "exit"){ 87 kill(pid); 88 return; 89 } 90 tkclient->wmctl(t, s); 91 pid = <-tick => 92 update(mfd); 93 for(i := 0; i < n; i++) { 94 if(a[i].limit <= 0) 95 continue; 96 x := int ((big a[i].size * big (230-maxx)) / big a[i].limit); 97 s := sys->sprint(".c coords %s %d %d %d %d", 98 a[i].tag, 99 maxx, 100 a[i].y + 4, 101 maxx + x, 102 a[i].y + 8); 103 cmd(t, s); 104 x = int ((big a[i].hw * big (230-maxx)) / big a[i].limit); 105 s = sys->sprint(".c coords %s %d %d %d %d", 106 a[i].taghw, 107 maxx, 108 a[i].y + 4, 109 maxx+x, 110 a[i].y + 8); 111 cmd(t, s); 112 s = sys->sprint(".c itemconfigure %s -text '%s", a[i].tagsz, string a[i].size); 113 cmd(t, s); 114 s = sys->sprint(".c itemconfigure %s -text '%d", a[i].tagiu, a[i].allocs-a[i].frees); 115 cmd(t, s); 116 } 117 cmd(t, "update"); 118 } 119} 120 121ticker(c: chan of int) 122{ 123 pid := sys->pctl(0, nil); 124 for(;;) { 125 c <-= pid; 126 sys->sleep(1000); 127 } 128} 129 130initdraw(n: int): int 131{ 132 y := 15; 133 maxx := 0; 134 for (i := 0; i < n; i++) { 135 id := cmd(t, ".c create text 5 "+string y+" -anchor w -text "+a[i].name); 136 r := s2r(cmd(t, ".c bbox " + id)); 137 if (r.max.x > maxx) 138 maxx = r.max.x; 139 y += 20; 140 } 141 maxx += 5; 142 y = 15; 143 for(i = 0; i < n; i++) { 144 s := sys->sprint(".c create rectangle %d %d 230 %d -fill white", maxx, y+4, y+8); 145 cmd(t, s); 146 s = sys->sprint(".c create rectangle %d %d 230 %d -fill white", maxx, y+4, y+8); 147 a[i].taghw = cmd(t, s); 148 s = sys->sprint(".c create rectangle %d %d 230 %d -fill red", maxx, y+4, y+8); 149 a[i].tag = cmd(t, s); 150 s = sys->sprint(".c create text 230 %d -anchor e -text '%s", y - 2, sizestr(a[i].limit)); 151 cmd(t, s); 152 s = sys->sprint(".c create text %d %d -anchor w -text '%s", maxx, y - 2, string a[i].size); 153 a[i].tagsz = cmd(t, s); 154 s = sys->sprint(".c create text 120 %d -fill red -anchor w -text '%d", y - 2, a[i].allocs-a[i].frees); 155 a[i].tagiu = cmd(t, s); 156 a[i].y = y; 157 y += 20; 158 } 159 cmd(t, ".c configure -height "+string y); 160 cmd(t, "update"); 161 return maxx; 162} 163 164sizestr(n: int): string 165{ 166 if ((n / 1024) % 1024 == 0) 167 return string (n / (1024 * 1024)) + "M"; 168 return string (n / 1024) + "K"; 169} 170 171buf := array[8192] of byte; 172 173update(mfd: ref Sys->FD): int 174{ 175 sys->seek(mfd, big 0, Sys->SEEKSTART); 176 n := sys->read(mfd, buf, len buf); 177 if(n <= 0) 178 exit; 179 (nil, l) := sys->tokenize(string buf[0:n], "\n"); 180 i := 0; 181 while(l != nil) { 182 s := hd l; 183 a[i].size = int s[0:]; 184 a[i].hw = int s[24:]; 185 a[i].allocs = int s[3*12:]; 186 a[i].frees = int s[4*12:]; 187 a[i].exts = int s[5*12:]; 188 a[i++].chunk = int s[6*12:]; 189 l = tl l; 190 } 191 return i; 192} 193 194getmem(mfd: ref Sys->FD): int 195{ 196 n := sys->read(mfd, buf, len buf); 197 if(n <= 0) 198 exit; 199 (nil, l) := sys->tokenize(string buf[0:n], "\n"); 200 i := 0; 201 while(l != nil) { 202 s := hd l; 203 a[i].size = int s[0:]; 204 a[i].limit = int s[12:]; 205 a[i].hw = int s[2*12:]; 206 a[i].allocs = int s[3*12:]; 207 a[i].frees = int s[4*12:]; 208 a[i].exts = int s[5*12:]; 209 a[i].chunk = int s[6*12:]; 210 a[i].name = s[7*12:]; 211 i++; 212 l = tl l; 213 } 214 return i; 215} 216 217s2r(s: string): Rect 218{ 219 (n, toks) := sys->tokenize(s, " "); 220 if (n != 4) { 221 sys->print("'%s' is not a rectangle!\n", s); 222 raise "bad conversion"; 223 } 224 r: Rect; 225 (r.min.x, toks) = (int hd toks, tl toks); 226 (r.min.y, toks) = (int hd toks, tl toks); 227 (r.max.x, toks) = (int hd toks, tl toks); 228 (r.max.y, toks) = (int hd toks, tl toks); 229 return r; 230} 231 232kill(pid: int) 233{ 234 fd := sys->open("#p/"+string pid+"/ctl", sys->OWRITE); 235 if(fd != nil) 236 sys->fprint(fd, "kill"); 237} 238 239 240cmd(top: ref Tk->Toplevel, s: string): string 241{ 242 e := tk->cmd(top, s); 243 if (e != nil && e[0] == '!') 244 sys->print("memory: tk error on '%s': %s\n", s, e); 245 return e; 246} 247