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, P, mainpid;
86 if T.state == Running then {
87 P = (Proc)T.proc;
88 mainpid = pid;
89 if mainpid != P.pid then setproc(P.pid);
90 stk = strace({});
91 if mainpid != P.pid then setproc(mainpid);
92 } else
93 stk = strace(label(T.sched));
95 stop = 0;
96 while stk && !stop do {
97 frame = head stk;
98 stk = tail stk;
99 pc = frame[2];
100 pc0 = frame[0];
101 file = pcfile(pc);
102 if !regexp("plan9/src/lib9/", file)
103 && !regexp("plan9/src/libthread/", file)
104 && match(file, stkignore)==-1 then
105 stop = 1;
107 file = pcfile(pc);
108 s = file+":"+itoa(pcline(pc), "%d");
109 if pc0 != 0 then
110 s = s + " "+fnname(pc0);
111 return s;
114 defn threadfmt(T){
115 complex Thread T;
116 local A, yes, i, P, s;
118 P = (Proc)T.proc;
119 s = "t=(Thread)"+itoa(T, "%-10x")+" // ";
121 if T.state == Running then
122 s = s + "Running ";
123 else if T.state == Ready then
124 s = s + "Ready ";
125 else if T.state == Rendezvous then
126 s = s + "Rendez ";
127 else
128 s = s + "Bad state "+itoa(T.state, "%x")+" ";
130 A = (Alt)T.alt;
131 if 1 then
132 s = s + threadstkline(T);
133 else if T.chan == Chanalt then
134 s = s + altfmt(T.alt);
135 else if T.chan == Chansend then
136 s = s + "send(Channel("+itoa(A.c, "%x")+"))";
137 else if T.chan == Chanrecv then
138 s = s + "recv(Channel("+itoa(A.c, "%x")+"))";
139 else
140 s = s + threadstkline(T);
142 if T.moribund == 1 then
143 s = s + " Moribund";
144 if T.cmdname != 0 then
145 s = s + " ["+*(T.cmdname\s)+"]";
146 return s;
149 defn thread(T){
150 print(threadfmt(T), "\n");
153 defn pthreads(P){
154 complex Proc P;
155 local T, Tq, mainpid;
157 mainpid = pid;
158 Tq = (Tqueue)P.threads;
159 T = (Thread)Tq.$head;
160 while T != 0 do{
161 print("\t");
162 thread(T);
163 T = (Thread)T.nextt;
167 defn threads(){
168 local P;
169 complex Pqueue _threadpq;
171 P = (Proc)_threadpq.$head;
172 while P != 0 do{
173 if P != (Proc)_threadpq.$head then print("\n");
174 lproc(P);
175 P = (Proc)P.next;
179 defn stacks(){
180 local P, mainpid;
181 complex Pqueue _threadpq;
183 stkprefix = "";
184 mainpid = pid;
185 P = (Proc)_threadpq.$head;
186 while P != 0 do{
187 proc(P);
188 if mainpid != P.pid then setproc(P.pid);
189 // setproc(P.pid);
190 // if P.thread==0 then{
191 // print("=== thread scheduler stack\n");
192 // stk();
193 // }
194 // print("threadstks(", P\X, ")\n");
195 threadstks(P);
196 if mainpid != P.pid then setproc(mainpid);
197 P = (Proc)P.next;
198 print("\n");
200 // setproc(mainpid);
203 defn stacksizes(){
204 local P, T, Tq, top, sp, mainpid;
205 complex Pqueue _threadpq;
207 mainpid = pid;
208 P = (Proc)_threadpq.$head;
209 while P != 0 do{
210 P = (Proc)P;
211 if mainpid != P.pid then setproc(P.pid);
212 Tq = (Tqueue)P.threads;
213 T = (Thread)Tq.$head;
214 while T != 0 do{
215 top = T.stk+T.stksize;
216 if T.state==Running then {
217 sp = *SP;
218 }else{
219 sp = T.sched.sp;
221 print(top-sp\D, " of ", T.stksize\D, " - 0x", top\X, " 0x", sp\X, " ", *T.stk\X, "\n");
222 T = (Thread)T.nextt;
224 if mainpid != P.pid then setproc(mainpid);
225 P = P.next;
227 // setproc(mainpid);
230 defn lproc(P){
231 proc(P);
232 pthreads(P);
235 threadstkignore = {
236 "plan9/src/libthread/",
237 "plan9/src/lib9/",
238 "plan9/src/lib9/(fmt|utf)/",
239 };
240 defn threadstks(P){
241 complex Proc P;
242 local T, Tq, mainpid, pref, ign;
244 mainpid = pid;
245 pref = stkprefix;
246 stkprefix = pref+"\t\t";
247 ign = stkignore;
248 stkignore = threadstkignore;
249 // setproc(P.pid);
250 Tq = (Tqueue)P.threads;
251 T = (Thread)Tq.$head;
252 while T != 0 do{
253 // print("=============================\n");
254 // print(" thread(", T\X, ")\n");
255 print("\t");
256 thread(T);
257 threadstk(T);
258 T = (Thread)T.nextt;
259 print("\n");
261 // setproc(mainpid);
262 stkprefix = pref;
263 stkignore = ign;
266 defn proc(P){
267 complex Proc P;
269 print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");
270 if P.thread==0 then
271 print(" Sched");
272 else
273 print(" Running");
274 print("\n");
277 defn procs(){
278 local P;
279 complex Pqueue _threadpq;
281 P = (Proc)_threadpq.$head;
282 while P != 0 do{
283 proc(P);
284 P = P.next;
288 defn threadlstk(T){
289 complex Thread T;
290 local P, mainpid;
292 P = (Proc)T.proc;
293 // mainpid = pid;
294 // setproc(P.pid);
296 if T.state == Running then{
297 lstk();
298 } else {
299 lablstk(T.sched);
301 // setproc(mainpid);
304 defn threadstk(T){
305 complex Thread T;
306 local P, mainpid;
308 P = (Proc)T.proc;
309 mainpid = pid;
310 // setproc(P.pid);
312 if T.state == Running then{
313 if P.pid != mainpid then
314 setproc(P.pid);
315 stk();
316 if P.pid != mainpid then
317 setproc(mainpid);
318 } else {
319 labstk(T.sched);
321 // setproc(mainpid);
324 defn tqueue(Q) {
325 complex Tqueue Q;
327 while Q != 0 do {
328 print(Q.$head\X, " ");
329 Q = *(Q.$tail);
332 print("#\n");
335 defn channel(C) {
336 complex Channel C;
337 local i, p;
339 print("channel ", C\X);
340 if C.freed then {
341 print(" (moribund)");
343 print("\n");
344 print("\telementsize=", C.e\D, " buffersize=", C.s, "\n");
345 if C.s then {
346 print("\t", C.n\D, " values in channel:\n");
347 print("\t");
348 p = C.v+C.e*(C.f%C.s);
349 loop 1,C.n do {
350 if C.e==4 then {
351 print((*p)\X, " ");
352 }else {
353 print("data(", (*p)\X, ") ");
355 p = p+C.e;
356 if p == C.v+C.s*C.e then {
357 p = C.v;
361 print("\n");
362 print(C.nentry\D, " queue slots:\n");
363 i=0;
364 loop 1,C.nentry do {
365 if C.qentry[i] then
366 print("\t", altfmt(C.qentry[i]), "\n");
367 else
368 print("\t<empty>\n");
369 i=i+1;
373 defn polling() {
374 local i, c, t, p, pf;
376 p=(Poll)polls; pf=(struct_pollfd)pfd; loop 1,*npoll do {
377 print("\tfd ", pf.fd\D, " ");
378 if pf.events & 1 then
379 print("r");
380 else if pf.events & 2 then
381 print("w");
382 else
383 print(pf.events\D);
384 print(" chan Channel(", p.c\X, ")\n");
385 p = (Poll)(p+sizeofPoll);
386 pf = (struct_pollfd)(pf+sizeofstruct_pollfd);
389 c=sleepchan; t=sleeptime; loop 1,*nsleep do {
390 print("\tsleep ", *t\D, " Channel(", *c\X, ")\n");
391 c++;
392 t++;
396 print(acidfile);