thread (5091B)
1 // 2 // pthread-specific access functions 3 // avoid complicated libthread_db interface 4 // 5 6 include("pthread-"+systype+"-"+objtype); 7 8 // pick apart system mcontext_t structures 9 defn mcontext(m) 10 { 11 complex mcontext_t m; 12 13 if systype == "linux" then { 14 m = m\X; 15 return {"PC", m[14], "SP", m[7], "BP", m[6]}; 16 } else if systype == "freebsd" then { 17 return {"PC", m.mc_eip, "SP", m.mc_esp, "BP", m.mc_ebp}; 18 } else 19 error("do not know how to read mcontext_t on system "+systype); 20 } 21 22 // 23 // plan 9 thread library support 24 // 25 defn context(c) 26 { 27 c = (Context)c; 28 return mcontext(c.uc.uc_mcontext); 29 } 30 31 defn contextstk(c) 32 { 33 _stk(context(c), 0); 34 } 35 36 defn contextlstk(c) 37 { 38 _stk(context(c), 1); 39 } 40 41 defn altfmt(A){ 42 local i, s, yes; 43 complex Alt A; 44 45 s = "alt("; 46 s = s + "tag(*" + itoa(A.tag, "%#x") + "=" + itoa(*A.tag, "%#x") + ") "; 47 i = 0; 48 yes = 0; 49 while A.op != CHANEND && A.op != CHANNOBLK do{ 50 if A.op != CHANNOP then{ 51 if yes then s = s + " "; 52 s = s + itoa(i, "%d"); 53 s = s + ":"; 54 if A.op == CHANSND then s = s + "send"; 55 if A.op == CHANRCV then s = s + "recv"; 56 s = s + "(channel("; 57 s = s + itoa(A.c, "%#x"); 58 s = s + "))"; 59 yes = 1; 60 } 61 i = i + 1; 62 A = (Alt)(A + sizeofAlt); 63 } 64 if A.op==CHANNOBLK then{ 65 if yes then s = s + " "; 66 s = s + "noblock"; 67 } 68 s = s + ")"; 69 return s; 70 } 71 72 defn alt(A){ 73 print(altfmt(A), "\n"); 74 } 75 76 defn channel(C) { 77 complex Channel C; 78 local i, p; 79 80 print("channel ", C\X, " // ", *(C.name\s)); 81 if C.freed then { 82 print(" (moribund)"); 83 } 84 print("\n"); 85 print("\telemsize=", C.elemsize\D, " bufsize=", C.bufsize, "\n"); 86 if C.bufsize then { 87 print("\t", C.nbuf\D, " values in channel:\n"); 88 print("\t"); 89 p = C.buf+C.off*C.elemsize; 90 loop 1,C.nbuf do { 91 if C.elemsize==4 then { 92 print(*p\X, " "); 93 }else { 94 print("data(", p\X, ") "); 95 } 96 p = p+C.elemsize; 97 if p == C.buf+C.bufsize*C.elemsize then { 98 p = C.buf; 99 } 100 } 101 } 102 print("\n"); 103 print(" senders:\n"); 104 _altarray(C.asend); 105 print(" recvers:\n"); 106 _altarray(C.arecv); 107 } 108 109 defn _altarray(aa) 110 { 111 local i, a, t; 112 113 i = 0; 114 aa = (_Altarray)aa; 115 while i < aa.n do { 116 a = (Alt)aa.a[i]; 117 print("\t"+threadstkline(a.thread)+"\n"); 118 i++; 119 } 120 } 121 122 defn fnname(a){ 123 local sym, s; 124 125 s = symbols; 126 while s do { 127 sym = head s; 128 if sym[2] == a then 129 return sym[0]; 130 s = tail s; 131 } 132 return itoa(a, "%#x"); 133 } 134 135 stkignorelist = {}; 136 defn stkignore(s){ 137 append stkignorelist, s; 138 } 139 140 defn threadstkline(T){ 141 local stk, frame, pc, pc0, file, s, sym, i, stop, P, mainpid; 142 143 T = (_Thread)T; 144 P = (Proc)T.proc; 145 if P.thread == T then { 146 mainpid = pid; 147 setproc(pthread2tid(P.osprocid)); 148 stk = strace({}); 149 setproc(mainpid); 150 } else 151 stk = strace(context(T.context)); 152 153 stop = 0; 154 while stk && !stop do { 155 frame = head stk; 156 stk = tail stk; 157 pc = frame[2]; 158 pc0 = frame[0]; 159 file = pcfile(pc); 160 if !regexp("plan9/src/lib9/", file) 161 && !regexp("plan9/src/libthread/", file) 162 && file != "?file?" 163 && match(file, stkignore)==-1 then 164 stop = 1; 165 } 166 file = pcfile(pc); 167 s = file+":"+itoa(pcline(pc), "%d"); 168 if pc0 != 0 then 169 s = s + " "+fnname(pc0); 170 return s; 171 } 172 173 defn threadfmt(T){ 174 complex _Thread T; 175 local P, s, name; 176 177 P = (Proc)T.proc; 178 s = "t=(_Thread)"+itoa(T, "%#-10x")+" // "; 179 180 if P.thread == T then 181 s = s + "Running "; 182 else 183 s = s + "Sleeping "; 184 s = s + threadstkline(T); 185 186 name = T+392; // T+offsetof(_Thread, name); 187 if *(name\b) != 0 then 188 s = s + " ["+*(name\s)+"]"; 189 return s; 190 } 191 192 defn thread(T){ 193 print(threadfmt(T), "\n"); 194 } 195 196 defn procthreads(P){ 197 complex Proc P; 198 local T; 199 200 T = (_Thread)P.allthreads.$head; 201 while T != 0 do{ 202 print("\t"); 203 thread(T); 204 T = (_Thread)T.allnext; 205 } 206 } 207 208 defn prociter(x) { 209 local P; 210 211 P = (Proc)*_threadprocs; 212 while P != 0 do{ 213 if P != (Proc)*_threadprocs then print("\n"); 214 proc(P); 215 if x == 1 then 216 procthreads(P); 217 if x == 2 then 218 threadstks(P); 219 P = (Proc)P.next; 220 } 221 } 222 223 defn procs() { 224 prociter(0); 225 } 226 227 defn threads() { 228 prociter(1); 229 } 230 231 defn stacks() { 232 prociter(2); 233 } 234 235 threadstkignore = { 236 "plan9/src/libthread/", 237 "plan9/src/lib9/", 238 "plan9/src/lib9/(fmt|utf)/", 239 }; 240 defn threadstks(P){ 241 complex Proc P; 242 local T, mainpid, pref, ign; 243 244 pref = stkprefix; 245 stkprefix = pref+"\t\t"; 246 ign = stkignore; 247 stkignore = threadstkignore; 248 T = (_Thread)P.allthreads.$head; 249 while T != 0 do{ 250 print("\t"); 251 thread(T); 252 threadstk(T); 253 T = (_Thread)T.allnext; 254 print("\n"); 255 } 256 stkprefix = pref; 257 stkignore = ign; 258 } 259 260 defn proc(P){ 261 complex Proc P; 262 263 print("p=(Proc)", itoa(P, "%#-10x"), " // pthread ", P.osprocid\X, " pid ", pthread2tid(P.osprocid)\D, " "); 264 if P.thread==0 then 265 print(" Sched"); 266 else 267 print(" Running"); 268 print("\n"); 269 } 270 271 defn threadlstk(T){ 272 complex _Thread T; 273 local P, mainpid; 274 275 P = (Proc)T.proc; 276 mainpid = pid; 277 setproc(pthread2tid(P.osprocid)); 278 279 if P.thread == T then 280 lstk(); 281 else 282 contextlstk(T.context); 283 setproc(mainpid); 284 } 285 286 defn threadstk(T){ 287 complex _Thread T; 288 local P, mainpid; 289 290 P = (Proc)T.proc; 291 mainpid = pid; 292 setproc(pthread2tid(P.osprocid)); 293 294 if P.thread == T then 295 stk(); 296 else 297 contextstk(T.context); 298 299 setproc(mainpid); 300 } 301 302 print(acidfile);