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;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;179 }180 }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");200 }201 setproc(mainpid);202 }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);220 }221 sp = *(T.sched);222 print(top-sp\D, "\n");223 T = (Thread)T.nextt;224 }225 P = P.next;226 }227 setproc(mainpid);228 }230 defn lproc(P){231 proc(P);232 pthreads(P);233 }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");259 }260 setproc(mainpid);261 stkprefix = pref;262 stkignore = ign;263 }265 defn proc(P){266 complex Proc P;268 print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");269 if P.thread==0 then270 print(" Sched");271 else272 print(" Running");273 print("\n");274 }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;284 }285 }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);299 }300 setproc(mainpid);301 }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);315 }316 setproc(mainpid);317 }319 defn tqueue(Q) {320 complex Tqueue Q;322 while Q != 0 do {323 print(Q.$head\X, " ");324 Q = *(Q.$tail);326 }327 print("#\n");328 }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)");337 }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, ") ");349 }350 p = p+C.e;351 if p == C.v+C.s*C.e then {352 p = C.v;353 }354 }355 }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] then361 print("\t", altfmt(C.qentry[i]), "\n");362 else363 print("\t<empty>\n");364 i=i+1;365 }366 }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 then374 print("r");375 else if pf.events & 2 then376 print("w");377 else378 print(pf.events\D);379 print(" chan Channel(", p.c\X, ")\n");380 p = (Poll)(p+sizeofPoll);381 pf = (struct_pollfd)(pf+sizeofstruct_pollfd);382 }384 c=sleepchan; t=sleeptime; loop 1,*nsleep do {385 print("\tsleep ", *t\D, " Channel(", *c\X, ")\n");386 c++;387 t++;388 }389 }391 print(acidfile);