rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 1 | // |
| 2 | // pthread-specific access functions |
| 3 | // avoid complicated libthread_db interface |
| 4 | // |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 5 | |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 6 | include("pthread-"+systype+"-"+objtype); |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 7 | |
| 8 | // pick apart system mcontext_t structures |
| 9 | defn mcontext(m) |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 10 | { |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 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); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 39 | } |
| 40 | |
| 41 | defn altfmt(A){ |
| 42 | local i, s, yes; |
| 43 | complex Alt A; |
| 44 | |
| 45 | s = "alt("; |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 46 | s = s + "tag(*" + itoa(A.tag, "%#x") + "=" + itoa(*A.tag, "%#x") + ") "; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 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("; |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 57 | s = s + itoa(A.c, "%#x"); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 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 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 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 | |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 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 | } |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 132 | return itoa(a, "%#x"); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 133 | } |
| 134 | |
| 135 | stkignorelist = {}; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 136 | defn stkignore(s){ |
| 137 | append stkignorelist, s; |
| 138 | } |
| 139 | |
| 140 | defn threadstkline(T){ |
rsc | c9896e2 | 2004-05-23 00:58:00 +0000 | [diff] [blame] | 141 | local stk, frame, pc, pc0, file, s, sym, i, stop, P, mainpid; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 142 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 143 | T = (_Thread)T; |
| 144 | P = (Proc)T.proc; |
| 145 | if P.thread == T then { |
rsc | c9896e2 | 2004-05-23 00:58:00 +0000 | [diff] [blame] | 146 | mainpid = pid; |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 147 | setproc(pthread2tid(P.osprocid)); |
rsc | 7284df1 | 2004-04-19 18:52:34 +0000 | [diff] [blame] | 148 | stk = strace({}); |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 149 | setproc(mainpid); |
rsc | c9896e2 | 2004-05-23 00:58:00 +0000 | [diff] [blame] | 150 | } else |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 151 | stk = strace(context(T.context)); |
rsc | 7284df1 | 2004-04-19 18:52:34 +0000 | [diff] [blame] | 152 | |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 153 | stop = 0; |
| 154 | while stk && !stop do { |
rsc | 7284df1 | 2004-04-19 18:52:34 +0000 | [diff] [blame] | 155 | frame = head stk; |
| 156 | stk = tail stk; |
| 157 | pc = frame[2]; |
| 158 | pc0 = frame[0]; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 159 | file = pcfile(pc); |
rsc | 2e965b3 | 2004-05-05 04:22:16 +0000 | [diff] [blame] | 160 | if !regexp("plan9/src/lib9/", file) |
rsc | 7284df1 | 2004-04-19 18:52:34 +0000 | [diff] [blame] | 161 | && !regexp("plan9/src/libthread/", file) |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 162 | && file != "?file?" |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 163 | && match(file, stkignore)==-1 then |
| 164 | stop = 1; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 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){ |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 174 | complex _Thread T; |
| 175 | local P, s, name; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 176 | |
| 177 | P = (Proc)T.proc; |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 178 | s = "t=(_Thread)"+itoa(T, "%#-10x")+" // "; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 179 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 180 | if P.thread == T then |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 181 | s = s + "Running "; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 182 | else |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 183 | s = s + "Sleeping "; |
| 184 | s = s + threadstkline(T); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 185 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 186 | name = T+392; // T+offsetof(_Thread, name); |
| 187 | if *(name\b) != 0 then |
| 188 | s = s + " ["+*(name\s)+"]"; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 189 | return s; |
| 190 | } |
| 191 | |
| 192 | defn thread(T){ |
| 193 | print(threadfmt(T), "\n"); |
| 194 | } |
| 195 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 196 | defn procthreads(P){ |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 197 | complex Proc P; |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 198 | local T; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 199 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 200 | T = (_Thread)P.allthreads.$head; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 201 | while T != 0 do{ |
| 202 | print("\t"); |
| 203 | thread(T); |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 204 | T = (_Thread)T.allnext; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 205 | } |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 206 | } |
| 207 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 208 | defn prociter(x) { |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 209 | local P; |
rsc | c73e7cf | 2004-04-20 05:05:38 +0000 | [diff] [blame] | 210 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 211 | P = (Proc)*_threadprocs; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 212 | while P != 0 do{ |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 213 | if P != (Proc)*_threadprocs then print("\n"); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 214 | proc(P); |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 215 | if x == 1 then |
| 216 | procthreads(P); |
| 217 | if x == 2 then |
| 218 | threadstks(P); |
rsc | 7284df1 | 2004-04-19 18:52:34 +0000 | [diff] [blame] | 219 | P = (Proc)P.next; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 220 | } |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 221 | } |
| 222 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 223 | defn procs() { |
| 224 | prociter(0); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 225 | } |
| 226 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 227 | defn threads() { |
| 228 | prociter(1); |
| 229 | } |
| 230 | |
| 231 | defn stacks() { |
| 232 | prociter(2); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 233 | } |
| 234 | |
rsc | c73e7cf | 2004-04-20 05:05:38 +0000 | [diff] [blame] | 235 | threadstkignore = { |
| 236 | "plan9/src/libthread/", |
rsc | 2e965b3 | 2004-05-05 04:22:16 +0000 | [diff] [blame] | 237 | "plan9/src/lib9/", |
| 238 | "plan9/src/lib9/(fmt|utf)/", |
rsc | c73e7cf | 2004-04-20 05:05:38 +0000 | [diff] [blame] | 239 | }; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 240 | defn threadstks(P){ |
| 241 | complex Proc P; |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 242 | local T, mainpid, pref, ign; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 243 | |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 244 | pref = stkprefix; |
| 245 | stkprefix = pref+"\t\t"; |
| 246 | ign = stkignore; |
rsc | c73e7cf | 2004-04-20 05:05:38 +0000 | [diff] [blame] | 247 | stkignore = threadstkignore; |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 248 | T = (_Thread)P.allthreads.$head; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 249 | while T != 0 do{ |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 250 | print("\t"); |
| 251 | thread(T); |
| 252 | threadstk(T); |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 253 | T = (_Thread)T.allnext; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 254 | print("\n"); |
| 255 | } |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 256 | stkprefix = pref; |
| 257 | stkignore = ign; |
| 258 | } |
| 259 | |
| 260 | defn proc(P){ |
| 261 | complex Proc P; |
| 262 | |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 263 | print("p=(Proc)", itoa(P, "%#-10x"), " // pthread ", P.osprocid\X, " pid ", pthread2tid(P.osprocid)\D, " "); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 264 | if P.thread==0 then |
| 265 | print(" Sched"); |
| 266 | else |
| 267 | print(" Running"); |
| 268 | print("\n"); |
| 269 | } |
| 270 | |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 271 | defn threadlstk(T){ |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 272 | complex _Thread T; |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 273 | local P, mainpid; |
| 274 | |
| 275 | P = (Proc)T.proc; |
| 276 | mainpid = pid; |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 277 | setproc(pthread2tid(P.osprocid)); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 278 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 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; |
rsc | 2a931b7 | 2005-02-11 16:51:43 +0000 | [diff] [blame] | 292 | setproc(pthread2tid(P.osprocid)); |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 293 | |
| 294 | if P.thread == T then |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 295 | stk(); |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 296 | else |
| 297 | contextstk(T.context); |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 298 | |
rsc | d89ce51 | 2005-02-11 02:14:59 +0000 | [diff] [blame] | 299 | setproc(mainpid); |
rsc | c73e7cf | 2004-04-20 05:05:38 +0000 | [diff] [blame] | 300 | } |
| 301 | |
rsc | 0a61c07 | 2004-04-19 18:18:37 +0000 | [diff] [blame] | 302 | print(acidfile); |