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" then14 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 then71 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 } else93 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 then105 stop = 1;106 }107 file = pcfile(pc);108 s = file+":"+itoa(pcline(pc), "%d");109 if pc0 != 0 then110 s = s + " "+fnname(pc0);111 return s;112 }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 then122 s = s + "Running ";123 else if T.state == Ready then124 s = s + "Ready ";125 else if T.state == Rendezvous then126 s = s + "Rendez ";127 else128 s = s + "Bad state "+itoa(T.state, "%x")+" ";130 A = (Alt)T.alt;131 if 1 then132 s = s + threadstkline(T);133 else if T.chan == Chanalt then134 s = s + altfmt(T.alt);135 else if T.chan == Chansend then136 s = s + "send(Channel("+itoa(A.c, "%x")+"))";137 else if T.chan == Chanrecv then138 s = s + "recv(Channel("+itoa(A.c, "%x")+"))";139 else140 s = s + threadstkline(T);142 if T.moribund == 1 then143 s = s + " Moribund";144 if T.cmdname != 0 then145 s = s + " ["+*(T.cmdname\s)+"]";146 return s;147 }149 defn thread(T){150 print(threadfmt(T), "\n");151 }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;164 }165 }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;176 }177 }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 // setproc(P.pid);189 // if P.thread==0 then{190 // print("=== thread scheduler stack\n");191 // stk();192 // }193 // print("threadstks(", P\X, ")\n");194 threadstks(P);195 P = (Proc)P.next;196 print("\n");197 }198 // setproc(mainpid);199 }201 defn stacksizes(){202 local P, T, Tq, top, sp, mainpid;203 complex Pqueue _threadpq;205 mainpid = pid;206 P = (Proc)_threadpq.$head;207 while P != 0 do{208 P = (Proc)P;209 Tq = (Tqueue)P.threads;210 T = (Thread)Tq.$head;211 while T != 0 do{212 top = T.stk+T.stksize;213 if T.state==Running then {214 sp = *SP;215 }else{216 sp = *(T.sched);217 }218 sp = *(T.sched);219 print(top-sp\D, "\n");220 T = (Thread)T.nextt;221 }222 P = P.next;223 }224 // setproc(mainpid);225 }227 defn lproc(P){228 proc(P);229 pthreads(P);230 }232 threadstkignore = {233 "plan9/src/libthread/",234 "plan9/src/lib9/",235 "plan9/src/lib9/(fmt|utf)/",236 };237 defn threadstks(P){238 complex Proc P;239 local T, Tq, mainpid, pref, ign;241 mainpid = pid;242 pref = stkprefix;243 stkprefix = pref+"\t\t";244 ign = stkignore;245 stkignore = threadstkignore;246 // setproc(P.pid);247 Tq = (Tqueue)P.threads;248 T = (Thread)Tq.$head;249 while T != 0 do{250 // print("=============================\n");251 // print(" thread(", T\X, ")\n");252 print("\t");253 thread(T);254 threadstk(T);255 T = (Thread)T.nextt;256 print("\n");257 }258 // setproc(mainpid);259 stkprefix = pref;260 stkignore = ign;261 }263 defn proc(P){264 complex Proc P;266 print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");267 if P.thread==0 then268 print(" Sched");269 else270 print(" Running");271 print("\n");272 }274 defn procs(){275 local P;276 complex Pqueue _threadpq;278 P = (Proc)_threadpq.$head;279 while P != 0 do{280 proc(P);281 P = P.next;282 }283 }285 defn threadlstk(T){286 complex Thread T;287 local P, mainpid;289 P = (Proc)T.proc;290 // mainpid = pid;291 // setproc(P.pid);293 if T.state == Running then{294 lstk();295 } else {296 lablstk(T.sched);297 }298 // setproc(mainpid);299 }301 defn threadstk(T){302 complex Thread T;303 local P, mainpid;305 P = (Proc)T.proc;306 mainpid = pid;307 // setproc(P.pid);309 if T.state == Running then{310 if P.pid != mainpid then311 setproc(P.pid);312 stk();313 if P.pid != mainpid then314 setproc(mainpid);315 } else {316 labstk(T.sched);317 }318 // setproc(mainpid);319 }321 defn tqueue(Q) {322 complex Tqueue Q;324 while Q != 0 do {325 print(Q.$head\X, " ");326 Q = *(Q.$tail);328 }329 print("#\n");330 }332 defn channel(C) {333 complex Channel C;334 local i, p;336 print("channel ", C\X);337 if C.freed then {338 print(" (moribund)");339 }340 print("\n");341 print("\telementsize=", C.e\D, " buffersize=", C.s, "\n");342 if C.s then {343 print("\t", C.n\D, " values in channel:\n");344 print("\t");345 p = C.v+C.e*(C.f%C.s);346 loop 1,C.n do {347 if C.e==4 then {348 print((*p)\X, " ");349 }else {350 print("data(", (*p)\X, ") ");351 }352 p = p+C.e;353 if p == C.v+C.s*C.e then {354 p = C.v;355 }356 }357 }358 print("\n");359 print(C.nentry\D, " queue slots:\n");360 i=0;361 loop 1,C.nentry do {362 if C.qentry[i] then363 print("\t", altfmt(C.qentry[i]), "\n");364 else365 print("\t<empty>\n");366 i=i+1;367 }368 }370 defn polling() {371 local i, c, t, p, pf;373 p=(Poll)polls; pf=(struct_pollfd)pfd; loop 1,*npoll do {374 print("\tfd ", pf.fd\D, " ");375 if pf.events & 1 then376 print("r");377 else if pf.events & 2 then378 print("w");379 else380 print(pf.events\D);381 print(" chan Channel(", p.c\X, ")\n");382 p = (Poll)(p+sizeofPoll);383 pf = (struct_pollfd)(pf+sizeofstruct_pollfd);384 }386 c=sleepchan; t=sleeptime; loop 1,*nsleep do {387 print("\tsleep ", *t\D, " Channel(", *c\X, ")\n");388 c++;389 t++;390 }391 }393 print(acidfile);