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;86 if T.state == Running then87 stk = strace({});88 else89 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 then101 stop = 1;102 }103 file = pcfile(pc);104 s = file+":"+itoa(pcline(pc), "%d");105 if pc0 != 0 then106 s = s + " "+fnname(pc0);107 return s;108 }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 then118 s = s + "Running ";119 else if T.state == Ready then120 s = s + "Ready ";121 else if T.state == Rendezvous then122 s = s + "Rendez ";123 else124 s = s + "Bad state "+itoa(T.state, "%x")+" ";126 A = (Alt)T.alt;127 if 1 then128 s = s + threadstkline(T);129 else if T.chan == Chanalt then130 s = s + altfmt(T.alt);131 else if T.chan == Chansend then132 s = s + "send(Channel("+itoa(A.c, "%x")+"))";133 else if T.chan == Chanrecv then134 s = s + "recv(Channel("+itoa(A.c, "%x")+"))";135 else136 s = s + threadstkline(T);138 if T.moribund == 1 then139 s = s + " Moribund";140 if T.cmdname != 0 then141 s = s + " ["+*(T.cmdname\s)+"]";142 return s;143 }145 defn thread(T){146 print(threadfmt(T), "\n");147 }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;161 }162 // setproc(mainpid);163 }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;174 }175 }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");195 }196 // setproc(mainpid);197 }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);215 }216 sp = *(T.sched);217 print(top-sp\D, "\n");218 T = (Thread)T.nextt;219 }220 P = P.next;221 }222 // setproc(mainpid);223 }225 defn lproc(P){226 proc(P);227 pthreads(P);228 }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");255 }256 // setproc(mainpid);257 stkprefix = pref;258 stkignore = ign;259 }261 defn proc(P){262 complex Proc P;264 print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");265 if P.thread==0 then266 print(" Sched");267 else268 print(" Running");269 print("\n");270 }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;280 }281 }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);295 }296 // setproc(mainpid);297 }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);311 }312 // setproc(mainpid);313 }315 defn tqueue(Q) {316 complex Tqueue Q;318 while Q != 0 do {319 print(Q.$head\X, " ");320 Q = *(Q.$tail);322 }323 print("#\n");324 }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)");333 }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, ") ");345 }346 p = p+C.e;347 if p == C.v+C.s*C.e then {348 p = C.v;349 }350 }351 }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] then357 print("\t", altfmt(C.qentry[i]), "\n");358 else359 print("\t<empty>\n");360 i=i+1;361 }362 }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 then370 print("r");371 else if pf.events & 2 then372 print("w");373 else374 print(pf.events\D);375 print(" chan Channel(", p.c\X, ")\n");376 p = (Poll)(p+sizeofPoll);377 pf = (struct_pollfd)(pf+sizeofstruct_pollfd);378 }380 c=sleepchan; t=sleeptime; loop 1,*nsleep do {381 print("\tsleep ", *t\D, " Channel(", *c\X, ")\n");382 c++;383 t++;384 }385 }387 print(acidfile);