Blob
1 //2 // pthread-specific access functions3 // avoid complicated libthread_db interface4 //6 include("pthread-"+systype+"-"+objtype);8 // pick apart system mcontext_t structures9 defn mcontext(m)10 {11 complex mcontext_t m;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 } else19 error("do not know how to read mcontext_t on system "+systype);20 }22 //23 // plan 9 thread library support24 //25 defn context(c)26 {27 c = (Context)c;28 return mcontext(c.uc.uc_mcontext);29 }31 defn contextstk(c)32 {33 _stk(context(c), 0);34 }36 defn contextlstk(c)37 {38 _stk(context(c), 1);39 }41 defn altfmt(A){42 local i, s, yes;43 complex Alt A;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 }72 defn alt(A){73 print(altfmt(A), "\n");74 }76 defn channel(C) {77 complex Channel C;78 local i, p;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 }109 defn _altarray(aa)110 {111 local i, a, t;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 }122 defn fnname(a){123 local sym, s;125 s = symbols;126 while s do {127 sym = head s;128 if sym[2] == a then129 return sym[0];130 s = tail s;131 }132 return itoa(a, "%#x");133 }135 stkignorelist = {};136 defn stkignore(s){137 append stkignorelist, s;138 }140 defn threadstkline(T){141 local stk, frame, pc, pc0, file, s, sym, i, stop, P, mainpid;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 } else151 stk = strace(context(T.context));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 then164 stop = 1;165 }166 file = pcfile(pc);167 s = file+":"+itoa(pcline(pc), "%d");168 if pc0 != 0 then169 s = s + " "+fnname(pc0);170 return s;171 }173 defn threadfmt(T){174 complex _Thread T;175 local P, s, name;177 P = (Proc)T.proc;178 s = "t=(_Thread)"+itoa(T, "%#-10x")+" // ";180 if P.thread == T then181 s = s + "Running ";182 else183 s = s + "Sleeping ";184 s = s + threadstkline(T);186 name = T+392; // T+offsetof(_Thread, name);187 if *(name\b) != 0 then188 s = s + " ["+*(name\s)+"]";189 return s;190 }192 defn thread(T){193 print(threadfmt(T), "\n");194 }196 defn procthreads(P){197 complex Proc P;198 local T;200 T = (_Thread)P.allthreads.$head;201 while T != 0 do{202 print("\t");203 thread(T);204 T = (_Thread)T.allnext;205 }206 }208 defn prociter(x) {209 local P;211 P = (Proc)*_threadprocs;212 while P != 0 do{213 if P != (Proc)*_threadprocs then print("\n");214 proc(P);215 if x == 1 then216 procthreads(P);217 if x == 2 then218 threadstks(P);219 P = (Proc)P.next;220 }221 }223 defn procs() {224 prociter(0);225 }227 defn threads() {228 prociter(1);229 }231 defn stacks() {232 prociter(2);233 }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;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 }260 defn proc(P){261 complex Proc P;263 print("p=(Proc)", itoa(P, "%#-10x"), " // pthread ", P.osprocid\X, " pid ", pthread2tid(P.osprocid)\D, " ");264 if P.thread==0 then265 print(" Sched");266 else267 print(" Running");268 print("\n");269 }271 defn threadlstk(T){272 complex _Thread T;273 local P, mainpid;275 P = (Proc)T.proc;276 mainpid = pid;277 setproc(pthread2tid(P.osprocid));279 if P.thread == T then280 lstk();281 else282 contextlstk(T.context);283 setproc(mainpid);284 }286 defn threadstk(T){287 complex _Thread T;288 local P, mainpid;290 P = (Proc)T.proc;291 mainpid = pid;292 setproc(pthread2tid(P.osprocid));294 if P.thread == T then295 stk();296 else297 contextstk(T.context);299 setproc(mainpid);300 }302 print(acidfile);