xref: /inferno-os/appl/wm/memory.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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