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 threadignsrc = {
65 "plan9/src/libc",
66 "plan9/src/libthread",
67 };
69 defn fnname(a){
70 local sym, s;
72 s = symbols;
73 while s do {
74 sym = head s;
75 if sym[2] == a then
76 return sym[0];
77 s = tail s;
78 }
79 return itoa(a, "%x");
80 }
82 stkignorelist = {};
84 defn stkignore(s){
85 append stkignorelist, s;
86 }
88 defn threadstkline(T){
89 local stk, frame, pc, pc0, file, s, sym, i, stop;
91 if T.state == Running then
92 stk = strace({});
93 else
94 stk = strace(label(T.sched));
96 stop = 0;
97 while stk && !stop do {
98 frame = head stk;
99 stk = tail stk;
100 pc = frame[2];
101 pc0 = frame[0];
102 file = pcfile(pc);
103 if !regexp("plan9/src/libc/", file)
104 && !regexp("plan9/src/libthread/", file)
105 && match(file, stkignore)==-1 then
106 stop = 1;
108 file = pcfile(pc);
109 s = file+":"+itoa(pcline(pc), "%d");
110 if pc0 != 0 then
111 s = s + " "+fnname(pc0);
112 return s;
115 defn threadfmt(T){
116 complex Thread T;
117 local A, yes, i, P, s;
119 P = (Proc)T.proc;
120 s = "t=(Thread)"+itoa(T, "%-10x")+" ";
122 if T.state == Running then
123 s = s + "Running ";
124 else if T.state == Ready then
125 s = s + "Ready ";
126 else if T.state == Rendezvous then
127 s = s + "Rendez ";
128 else
129 s = s + "Bad state "+itoa(T.state, "%x")+" ";
131 A = (Alt)T.alt;
132 if 1 then
133 s = s + threadstkline(T);
134 else if T.chan == Chanalt then
135 s = s + altfmt(T.alt);
136 else if T.chan == Chansend then
137 s = s + "send(Channel("+itoa(A.c, "%x")+"))";
138 else if T.chan == Chanrecv then
139 s = s + "recv(Channel("+itoa(A.c, "%x")+"))";
140 else
141 s = s + threadstkline(T);
143 if T.moribund == 1 then
144 s = s + " Moribund";
145 if T.cmdname != 0 then
146 s = s + " ["+*(T.cmdname\s)+"]";
147 return s;
150 defn thread(T){
151 print(threadfmt(T), "\n");
154 defn pthreads(P){
155 complex Proc P;
156 local T, Tq, mainpid;
158 mainpid = pid;
159 setproc(P.pid);
160 Tq = (Tqueue)P.threads;
161 T = (Thread)Tq.$head;
162 while T != 0 do{
163 print("\t");
164 thread(T);
165 T = (Thread)T.nextt;
167 setproc(mainpid);
170 defn threads(){
171 local P;
172 complex Pqueue _threadpq;
174 P = (Proc)_threadpq.$head;
175 while P != 0 do{
176 if P != (Proc)_threadpq.$head then print("\n");
177 lproc(P);
178 P = (Proc)P.next;
182 defn stacks(){
183 local P, mainpid;
184 complex Pqueue _threadpq;
186 stkprefix = "";
187 mainpid = pid;
188 P = (Proc)_threadpq.$head;
189 while P != 0 do{
190 proc(P);
191 // setproc(P.pid);
192 // if P.thread==0 then{
193 // print("=== thread scheduler stack\n");
194 // stk();
195 // }
196 // print("threadstks(", P\X, ")\n");
197 threadstks(P);
198 P = (Proc)P.next;
199 print("\n");
201 setproc(mainpid);
204 defn stacksizes(){
205 local P, T, Tq, top, sp, mainpid;
206 complex Pqueue _threadpq;
208 mainpid = pid;
209 P = (Proc)_threadpq.$head;
210 while P != 0 do{
211 P = (Proc)P;
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);
221 sp = *(T.sched);
222 print(top-sp\D, "\n");
223 T = (Thread)T.nextt;
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/libc/(386|arm|alpha|sparc|power|mips)/"
238 };
239 defn threadstks(P){
240 complex Proc P;
241 local T, Tq, mainpid, pref, ign;
243 mainpid = pid;
244 pref = stkprefix;
245 stkprefix = pref+"\t\t";
246 ign = stkignore;
247 stkignore = threadstkignore;
248 setproc(P.pid);
249 Tq = (Tqueue)P.threads;
250 T = (Thread)Tq.$head;
251 while T != 0 do{
252 // print("=============================\n");
253 // print(" thread(", T\X, ")\n");
254 print("\t");
255 thread(T);
256 threadstk(T);
257 T = (Thread)T.nextt;
258 print("\n");
260 setproc(mainpid);
261 stkprefix = pref;
262 stkignore = ign;
265 defn proc(P){
266 complex Proc P;
268 print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");
269 if P.thread==0 then
270 print(" Sched");
271 else
272 print(" Running");
273 print("\n");
276 defn procs(){
277 local P;
278 complex Pqueue _threadpq;
280 P = (Proc)_threadpq.$head;
281 while P != 0 do{
282 proc(P);
283 P = P.next;
287 defn threadlstk(T){
288 complex Thread T;
289 local P, mainpid;
291 P = (Proc)T.proc;
292 mainpid = pid;
293 setproc(P.pid);
295 if T.state == Running then{
296 lstk();
297 } else {
298 lablstk(T.sched);
300 setproc(mainpid);
303 defn threadstk(T){
304 complex Thread T;
305 local P, mainpid;
307 P = (Proc)T.proc;
308 mainpid = pid;
309 setproc(P.pid);
311 if T.state == Running then{
312 stk();
313 } else {
314 labstk(T.sched);
316 setproc(mainpid);
319 defn tqueue(Q) {
320 complex Tqueue Q;
322 while Q != 0 do {
323 print(Q.$head\X, " ");
324 Q = *(Q.$tail);
327 print("#\n");
330 defn channel(C) {
331 complex Channel C;
332 local i, p;
334 print("channel ", C\X);
335 if C.freed then {
336 print(" (moribund)");
338 print("\n");
339 print("\telementsize=", C.e\D, " buffersize=", C.s, "\n");
340 if C.s then {
341 print("\t", C.n\D, " values in channel:\n");
342 print("\t");
343 p = C.v+C.e*(C.f%C.s);
344 loop 1,C.n do {
345 if C.e==4 then {
346 print((*p)\X, " ");
347 }else {
348 print("data(", (*p)\X, ") ");
350 p = p+C.e;
351 if p == C.v+C.s*C.e then {
352 p = C.v;
356 print("\n");
357 print(C.nentry\D, " queue slots:\n");
358 i=0;
359 loop 1,C.nentry do {
360 if C.qentry[i] then
361 print("\t", altfmt(C.qentry[i]), "\n");
362 else
363 print("\t<empty>\n");
364 i=i+1;
368 defn polling() {
369 local i, c, t, p, pf;
371 p=(Poll)polls; pf=(struct_pollfd)pfd; loop 1,*npoll do {
372 print("\tfd ", pf.fd\D, " ");
373 if pf.events & 1 then
374 print("r");
375 else if pf.events & 2 then
376 print("w");
377 else
378 print(pf.events\D);
379 print(" chan Channel(", p.c\X, ")\n");
380 p = (Poll)(p+sizeofPoll);
381 pf = (struct_pollfd)(pf+sizeofstruct_pollfd);
384 c=sleepchan; t=sleeptime; loop 1,*nsleep do {
385 print("\tsleep ", *t\D, " Channel(", *c\X, ")\n");
386 c++;
387 t++;
391 print(acidfile);