Blob


2 defn labpc(l)
3 {
4 complex Label l;
6 return l.pc;
7 }
9 defn label(l)
10 {
11 complex Label l;
13 if objtype == "386" then
14 return {"PC", l.pc, "BX", l.bx, "SP", l.sp, "BP", l.bp, "SI", l.si, "DI", l.di};
15 return {};
16 }
19 defn labstk(l)
20 {
21 _stk(label(l), 0);
22 }
24 defn lablstk(l)
25 {
26 _stk(label(l), 1);
27 }
29 defn altfmt(A){
30 local i, s, yes;
31 complex Alt A;
33 s = "alt(";
34 s = s + "tag(*" + itoa(A.tag, "%x") + "=" + itoa(*A.tag, "%x") + ") ";
35 i = 0;
36 yes = 0;
37 while A.op != CHANEND && A.op != CHANNOBLK do{
38 if A.op != CHANNOP then{
39 if yes then s = s + " ";
40 s = s + itoa(i, "%d");
41 s = s + ":";
42 if A.op == CHANSND then s = s + "send";
43 if A.op == CHANRCV then s = s + "recv";
44 s = s + "(channel(";
45 s = s + itoa(A.c, "%x");
46 s = s + "))";
47 yes = 1;
48 }
49 i = i + 1;
50 A = (Alt)(A + sizeofAlt);
51 }
52 if A.op==CHANNOBLK then{
53 if yes then s = s + " ";
54 s = s + "noblock";
55 }
56 s = s + ")";
57 return s;
58 }
60 defn alt(A){
61 print(altfmt(A), "\n");
62 }
64 defn fnname(a){
65 local sym, s;
67 s = symbols;
68 while s do {
69 sym = head s;
70 if sym[2] == a then
71 return sym[0];
72 s = tail s;
73 }
74 return itoa(a, "%x");
75 }
77 stkignorelist = {};
79 defn stkignore(s){
80 append stkignorelist, s;
81 }
83 defn threadstkline(T){
84 local stk, frame, pc, pc0, file, s, sym, i, stop;
86 if T.state == Running then
87 stk = strace({});
88 else
89 stk = strace(label(T.sched));
91 stop = 0;
92 while stk && !stop do {
93 frame = head stk;
94 stk = tail stk;
95 pc = frame[2];
96 pc0 = frame[0];
97 file = pcfile(pc);
98 if !regexp("plan9/src/lib9/", file)
99 && !regexp("plan9/src/libthread/", file)
100 && match(file, stkignore)==-1 then
101 stop = 1;
103 file = pcfile(pc);
104 s = file+":"+itoa(pcline(pc), "%d");
105 if pc0 != 0 then
106 s = s + " "+fnname(pc0);
107 return s;
110 defn threadfmt(T){
111 complex Thread T;
112 local A, yes, i, P, s;
114 P = (Proc)T.proc;
115 s = "t=(Thread)"+itoa(T, "%-10x")+" ";
117 if T.state == Running then
118 s = s + "Running ";
119 else if T.state == Ready then
120 s = s + "Ready ";
121 else if T.state == Rendezvous then
122 s = s + "Rendez ";
123 else
124 s = s + "Bad state "+itoa(T.state, "%x")+" ";
126 A = (Alt)T.alt;
127 if 1 then
128 s = s + threadstkline(T);
129 else if T.chan == Chanalt then
130 s = s + altfmt(T.alt);
131 else if T.chan == Chansend then
132 s = s + "send(Channel("+itoa(A.c, "%x")+"))";
133 else if T.chan == Chanrecv then
134 s = s + "recv(Channel("+itoa(A.c, "%x")+"))";
135 else
136 s = s + threadstkline(T);
138 if T.moribund == 1 then
139 s = s + " Moribund";
140 if T.cmdname != 0 then
141 s = s + " ["+*(T.cmdname\s)+"]";
142 return s;
145 defn thread(T){
146 print(threadfmt(T), "\n");
149 defn pthreads(P){
150 complex Proc P;
151 local T, Tq, mainpid;
153 mainpid = pid;
154 // setproc(P.pid);
155 Tq = (Tqueue)P.threads;
156 T = (Thread)Tq.$head;
157 while T != 0 do{
158 print("\t");
159 thread(T);
160 T = (Thread)T.nextt;
162 // setproc(mainpid);
165 defn threads(){
166 local P;
167 complex Pqueue _threadpq;
169 P = (Proc)_threadpq.$head;
170 while P != 0 do{
171 if P != (Proc)_threadpq.$head then print("\n");
172 lproc(P);
173 P = (Proc)P.next;
177 defn stacks(){
178 local P, mainpid;
179 complex Pqueue _threadpq;
181 stkprefix = "";
182 mainpid = pid;
183 P = (Proc)_threadpq.$head;
184 while P != 0 do{
185 proc(P);
186 // setproc(P.pid);
187 // if P.thread==0 then{
188 // print("=== thread scheduler stack\n");
189 // stk();
190 // }
191 // print("threadstks(", P\X, ")\n");
192 threadstks(P);
193 P = (Proc)P.next;
194 print("\n");
196 // setproc(mainpid);
199 defn stacksizes(){
200 local P, T, Tq, top, sp, mainpid;
201 complex Pqueue _threadpq;
203 mainpid = pid;
204 P = (Proc)_threadpq.$head;
205 while P != 0 do{
206 P = (Proc)P;
207 Tq = (Tqueue)P.threads;
208 T = (Thread)Tq.$head;
209 while T != 0 do{
210 top = T.stk+T.stksize;
211 if T.state==Running then {
212 sp = *SP;
213 }else{
214 sp = *(T.sched);
216 sp = *(T.sched);
217 print(top-sp\D, "\n");
218 T = (Thread)T.nextt;
220 P = P.next;
222 // setproc(mainpid);
225 defn lproc(P){
226 proc(P);
227 pthreads(P);
230 threadstkignore = {
231 "plan9/src/libthread/",
232 "plan9/src/lib9/",
233 "plan9/src/lib9/(fmt|utf)/",
234 };
235 defn threadstks(P){
236 complex Proc P;
237 local T, Tq, mainpid, pref, ign;
239 mainpid = pid;
240 pref = stkprefix;
241 stkprefix = pref+"\t\t";
242 ign = stkignore;
243 stkignore = threadstkignore;
244 // setproc(P.pid);
245 Tq = (Tqueue)P.threads;
246 T = (Thread)Tq.$head;
247 while T != 0 do{
248 // print("=============================\n");
249 // print(" thread(", T\X, ")\n");
250 print("\t");
251 thread(T);
252 threadstk(T);
253 T = (Thread)T.nextt;
254 print("\n");
256 // setproc(mainpid);
257 stkprefix = pref;
258 stkignore = ign;
261 defn proc(P){
262 complex Proc P;
264 print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");
265 if P.thread==0 then
266 print(" Sched");
267 else
268 print(" Running");
269 print("\n");
272 defn procs(){
273 local P;
274 complex Pqueue _threadpq;
276 P = (Proc)_threadpq.$head;
277 while P != 0 do{
278 proc(P);
279 P = P.next;
283 defn threadlstk(T){
284 complex Thread T;
285 local P, mainpid;
287 P = (Proc)T.proc;
288 // mainpid = pid;
289 // setproc(P.pid);
291 if T.state == Running then{
292 lstk();
293 } else {
294 lablstk(T.sched);
296 // setproc(mainpid);
299 defn threadstk(T){
300 complex Thread T;
301 local P, mainpid;
303 P = (Proc)T.proc;
304 mainpid = pid;
305 // setproc(P.pid);
307 if T.state == Running then{
308 stk();
309 } else {
310 labstk(T.sched);
312 // setproc(mainpid);
315 defn tqueue(Q) {
316 complex Tqueue Q;
318 while Q != 0 do {
319 print(Q.$head\X, " ");
320 Q = *(Q.$tail);
323 print("#\n");
326 defn channel(C) {
327 complex Channel C;
328 local i, p;
330 print("channel ", C\X);
331 if C.freed then {
332 print(" (moribund)");
334 print("\n");
335 print("\telementsize=", C.e\D, " buffersize=", C.s, "\n");
336 if C.s then {
337 print("\t", C.n\D, " values in channel:\n");
338 print("\t");
339 p = C.v+C.e*(C.f%C.s);
340 loop 1,C.n do {
341 if C.e==4 then {
342 print((*p)\X, " ");
343 }else {
344 print("data(", (*p)\X, ") ");
346 p = p+C.e;
347 if p == C.v+C.s*C.e then {
348 p = C.v;
352 print("\n");
353 print(C.nentry\D, " queue slots:\n");
354 i=0;
355 loop 1,C.nentry do {
356 if C.qentry[i] then
357 print("\t", altfmt(C.qentry[i]), "\n");
358 else
359 print("\t<empty>\n");
360 i=i+1;
364 defn polling() {
365 local i, c, t, p, pf;
367 p=(Poll)polls; pf=(struct_pollfd)pfd; loop 1,*npoll do {
368 print("\tfd ", pf.fd\D, " ");
369 if pf.events & 1 then
370 print("r");
371 else if pf.events & 2 then
372 print("w");
373 else
374 print(pf.events\D);
375 print(" chan Channel(", p.c\X, ")\n");
376 p = (Poll)(p+sizeofPoll);
377 pf = (struct_pollfd)(pf+sizeofstruct_pollfd);
380 c=sleepchan; t=sleeptime; loop 1,*nsleep do {
381 print("\tsleep ", *t\D, " Channel(", *c\X, ")\n");
382 c++;
383 t++;
387 print(acidfile);