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 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 then76 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 then92 stk = strace({});93 else94 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 then106 stop = 1;107 }108 file = pcfile(pc);109 s = file+":"+itoa(pcline(pc), "%d");110 if pc0 != 0 then111 s = s + " "+fnname(pc0);112 return s;113 }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 then123 s = s + "Running ";124 else if T.state == Ready then125 s = s + "Ready ";126 else if T.state == Rendezvous then127 s = s + "Rendez ";128 else129 s = s + "Bad state "+itoa(T.state, "%x")+" ";131 A = (Alt)T.alt;132 if 1 then133 s = s + threadstkline(T);134 else if T.chan == Chanalt then135 s = s + altfmt(T.alt);136 else if T.chan == Chansend then137 s = s + "send(Channel("+itoa(A.c, "%x")+"))";138 else if T.chan == Chanrecv then139 s = s + "recv(Channel("+itoa(A.c, "%x")+"))";140 else141 s = s + threadstkline(T);143 if T.moribund == 1 then144 s = s + " Moribund";145 if T.cmdname != 0 then146 s = s + " ["+*(T.cmdname\s)+"]";147 return s;148 }150 defn thread(T){151 print(threadfmt(T), "\n");152 }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;166 }167 setproc(mainpid);168 }170 defn threads(){171 local P;173 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 = P.next;179 }180 }182 defn stacks(){183 local P, mainpid;185 stkprefix = "";186 mainpid = pid;187 P = (Proc)_threadpq.$head;188 while P != 0 do{189 proc(P);190 // setproc(P.pid);191 // if P.thread==0 then{192 // print("=== thread scheduler stack\n");193 // stk();194 // }195 // print("threadstks(", P\X, ")\n");196 threadstks(P);197 P = (Proc)P.next;198 print("\n");199 }200 setproc(mainpid);201 }203 defn stacksizes(){204 local P, T, Tq, top, sp, mainpid;206 mainpid = pid;207 P = (Proc)_threadpq.$head;208 while P != 0 do{209 P = (Proc)P;210 Tq = (Tqueue)P.threads;211 T = (Thread)Tq.$head;212 while T != 0 do{213 top = T.stk+T.stksize;214 if T.state==Running then {215 sp = *SP;216 }else{217 sp = *(T.sched);218 }219 sp = *(T.sched);220 print(top-sp\D, "\n");221 T = (Thread)T.nextt;222 }223 P = P.next;224 }225 setproc(mainpid);226 }228 defn lproc(P){229 proc(P);230 pthreads(P);231 }233 defn threadstks(P){234 complex Proc P;235 local T, Tq, mainpid, pref, ign;237 mainpid = pid;238 pref = stkprefix;239 stkprefix = pref+"\t\t";240 ign = stkignore;241 stkignore = {242 "plan9/src/libthread/",243 "plan9/src/libc/(386|arm|alpha|sparc|power|mips)/"244 };245 setproc(P.pid);246 Tq = (Tqueue)P.threads;247 T = (Thread)Tq.$head;248 while T != 0 do{249 // print("=============================\n");250 // print(" thread(", T\X, ")\n");251 print("\t");252 thread(T);253 threadstk(T);254 T = (Thread)T.nextt;255 print("\n");256 }257 setproc(mainpid);258 stkprefix = pref;259 stkignore = ign;260 }262 defn proc(P){263 complex Proc P;265 print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");266 if P.thread==0 then267 print(" Sched");268 else269 print(" Running");270 print("\n");271 }273 defn procs(){274 local P;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 print(acidfile);