1include("/sys/src/libthread/sched.acid"); 2 3defn labpc(l) 4{ 5 if objtype == "386" then 6 return longjmp; 7 return *(l+4); 8} 9 10defn labsp(l) 11{ 12 return *l; 13} 14 15defn labstk(l) 16{ 17 _stk(labpc(l), labsp(l), 0, 0); 18} 19 20defn lablstk(l) 21{ 22 _stk(labpc(l), labsp(l), 0, 1); 23} 24 25defn altfmt(A){ 26 local i, s, yes; 27 complex Alt A; 28 29 s = "alt("; 30 s = s + "tag(*" + itoa(A.tag, "%x") + "=" + itoa(*A.tag, "%x") + ") "; 31 i = 0; 32 yes = 0; 33 while A.op != CHANEND && A.op != CHANNOBLK do{ 34 if A.op != CHANNOP then{ 35 if yes then s = s + " "; 36 s = s + itoa(i, "%d"); 37 s = s + ":"; 38 if A.op == CHANSND then s = s + "send"; 39 if A.op == CHANRCV then s = s + "recv"; 40 s = s + "(channel("; 41 s = s + itoa(A.c, "%x"); 42 s = s + "))"; 43 yes = 1; 44 } 45 i = i + 1; 46 A = (Alt)(A + sizeofAlt); 47 } 48 if A.op==CHANNOBLK then{ 49 if yes then s = s + " "; 50 s = s + "noblock"; 51 } 52 s = s + ")"; 53 return s; 54} 55 56defn alt(A){ 57 print(altfmt(A), "\n"); 58} 59 60threadignsrc = { 61 "^/sys/src/libc", 62 "^/sys/src/libthread", 63}; 64 65defn fnname(a){ 66 local sym, s; 67 68 s = symbols; 69 while s do { 70 sym = head s; 71 if sym[2] == a then 72 return sym[0]; 73 s = tail s; 74 } 75 if a == {} then 76 return "{}"; 77 return itoa(a\X, "%x"); 78} 79 80stkignorelist = {}; 81 82defn stkignore(s){ 83 append stkignorelist, s; 84} 85 86defn threadstkline(T){ 87 local ostk, stk, frame, pc, pc0, file, lastpc0, s, sym, i, stop; 88 89 if T.state == Running then{ 90 pc = *PC; 91 stk = strace(*PC, *SP, linkreg(0)); 92 }else{ 93 pc = labpc(T.sched); 94 stk = strace(labpc(T.sched), labsp(T.sched), 0); 95 } 96 firstpc = pc; 97 lastpc0 = 0; 98 pc0 = 0; 99 stop = 0; 100 ostk = stk; 101 while stk && !stop do { 102 file = pcfile(pc); 103 if !regexp("^/sys/src/libc/", file) 104 && !regexp("^/sys/src/libthread/", file) 105 && match(file, stkignore)==-1 then 106 stop = 1; 107 else if stk[0][1] == 0xfefefefe then { 108 pc = ostk[0][1]; 109 pc0 = ostk[1][0]; 110 stop = 1; 111 }else{ 112 lastpc0 = pc0; 113 frame = head stk; 114 stk = tail stk; 115 nextframe = head stk; 116 pc = frame[1]; 117 pc0 = nextframe[0]; 118 } 119 } 120 file = pcfile(pc); 121 s = file+":"+itoa(pcline(pc), "%d"); 122 if pc0 != 0 then 123 s = s + " "+fnname(pc0); 124 return s; 125} 126 127defn threadfmt(T){ 128 complex Thread T; 129 local A, yes, i, P, s; 130 131 P = (Proc)T.proc; 132 s = "t=(Thread)"+itoa(T, "%-10x")+" "; 133 134 if T.state == Running then 135 s = s + "Running "; 136 else if T.state == Ready then 137 s = s + "Ready "; 138 else if T.state == Rendezvous then 139 s = s + "Rendez "; 140 else 141 s = s + "Bad state "+itoa(T.state, "%x")+" "; 142 143 A = (Alt)T.alt; 144 if 1 then 145 s = s + threadstkline(T); 146 else if T.chan == Chanalt then 147 s = s + altfmt(T.alt); 148 else if T.chan == Chansend then 149 s = s + "send(Channel("+itoa(A.c, "%x")+"))"; 150 else if T.chan == Chanrecv then 151 s = s + "recv(Channel("+itoa(A.c, "%x")+"))"; 152 else 153 s = s + threadstkline(T); 154 155 if T.moribund == 1 then 156 s = s + " Moribund"; 157 if T.cmdname != 0 then 158 s = s + " ["+*(T.cmdname\s)+"]"; 159 return s; 160} 161 162defn thread(T){ 163 print(threadfmt(T), "\n"); 164} 165 166defn pthreads(P){ 167 complex Proc P; 168 local T, Tq, mainpid; 169 170 mainpid = pid; 171 setproc(P.pid); 172 Tq = (Tqueue)P.threads; 173 T = (Thread)Tq.$head; 174 while T != 0 do{ 175 print("\t"); 176 thread(T); 177 T = T.nextt; 178 } 179 setproc(mainpid); 180} 181 182defn threads(){ 183 local P; 184 185 P = (Proc)_threadpq.$head; 186 while P != 0 do{ 187 if P != (Proc)_threadpq.$head then print("\n"); 188 lproc(P); 189 P = P.next; 190 } 191} 192 193defn stacks(){ 194 local P, mainpid; 195 196 mainpid = pid; 197 P = (Proc)_threadpq.$head; 198 while P != 0 do{ 199 proc(P); 200 // setproc(P.pid); 201 // if P.thread==0 then{ 202 // print("=== thread scheduler stack\n"); 203 // stk(); 204 // } 205 // print("threadstks(", P\X, ")\n"); 206 threadstks(P); 207 P = P.next; 208 print("\n"); 209 } 210 setproc(mainpid); 211} 212 213defn stacksizes(){ 214 local P, T, Tq, top, sp, mainpid; 215 216 mainpid = pid; 217 P = (Proc)_threadpq.$head; 218 while P != 0 do{ 219 P = (Proc)P; 220 Tq = (Tqueue)P.threads; 221 T = (Thread)Tq.$head; 222 while T != 0 do{ 223 top = T.stk+T.stksize; 224 if T.state==Running then { 225 sp = *SP; 226 }else{ 227 sp = *(T.sched); 228 } 229 sp = *(T.sched); 230 print(top-sp\D, " / ", T.stksize\D, "\n"); 231 T = T.nextt; 232 } 233 P = P.next; 234 } 235 setproc(mainpid); 236} 237 238defn lproc(P){ 239 proc(P); 240 pthreads(P); 241} 242 243defn threadstks(P){ 244 complex Proc P; 245 local T, Tq, mainpid, pref, ign; 246 247 mainpid = pid; 248 pref = stkprefix; 249 stkprefix = pref+"\t\t"; 250 ign = stkignore; 251 stkignore = { 252 "^/sys/src/libthread/", 253 "^/sys/src/libc/(386|arm|alpha|sparc|power|mips)/" 254 }; 255 setproc(P.pid); 256 Tq = (Tqueue)P.threads; 257 T = (Thread)Tq.$head; 258 while T != 0 do{ 259 // print("=============================\n"); 260 // print(" thread(", T\X, ")\n"); 261 print("\t"); 262 thread(T); 263 threadstk(T); 264 T = T.nextt; 265 print("\n"); 266 } 267 setproc(mainpid); 268 stkprefix = pref; 269 stkignore = ign; 270} 271 272defn proc(P){ 273 complex Proc P; 274 275 print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " "); 276 if P.thread==0 then 277 print(" Sched"); 278 else 279 print(" Running"); 280 print("\n"); 281} 282 283defn procs(){ 284 local P; 285 286 P = (Proc)_threadpq.$head; 287 while P != 0 do{ 288 proc(P); 289 P = P.next; 290 } 291} 292 293defn threadlstk(T){ 294 complex Thread T; 295 local P, mainpid; 296 297 P = (Proc)T.proc; 298 mainpid = pid; 299 setproc(P.pid); 300 301 if T.state == Running then{ 302 lstk(); 303 } else { 304 lablstk(T.sched); 305 } 306 setproc(mainpid); 307} 308 309defn threadstk(T){ 310 complex Thread T; 311 local P, mainpid; 312 313 P = (Proc)T.proc; 314 mainpid = pid; 315 setproc(P.pid); 316 317 if T.state == Running then{ 318 stk(); 319 } else { 320 labstk(T.sched); 321 } 322 setproc(mainpid); 323} 324 325defn tqueue(Q) { 326 complex Tqueue Q; 327 328 while Q != 0 do { 329 print(Q.$head\X, " "); 330 Q = *(Q.$tail); 331 332 } 333 print("#\n"); 334} 335 336defn channel(C) { 337 complex Channel C; 338 local i, p; 339 340 print("channel ", C\X); 341 if C.freed then { 342 print(" (moribund)"); 343 } 344 print("\n"); 345 print("\telementsize=", C.e\D, " buffersize=", C.s, "\n"); 346 if C.s then { 347 print("\t", C.n\D, " values in channel:\n"); 348 print("\t"); 349 p = C.v+C.e*(C.f%C.s); 350 loop 1,C.n do { 351 if C.e==4 then { 352 print((*p)\X, " "); 353 }else { 354 print("data(", (*p)\X, ") "); 355 } 356 p = p+C.e; 357 if p == C.v+C.s*C.e then { 358 p = C.v; 359 } 360 } 361 } 362 print("\n"); 363 print(C.nentry\D, " queue slots:\n"); 364 i=0; 365 loop 1,C.nentry do { 366 if C.qentry[i] then 367 print("\t", altfmt(C.qentry[i]), "\n"); 368 else 369 print("\t<empty>\n"); 370 i=i+1; 371 } 372} 373 374print("/sys/lib/acid/thread"); 375