commit d89ce51a3b4be96d12066eadbcffc0587a2673a6 from: rsc date: Fri Feb 11 02:14:59 2005 UTC different pthread support commit - ed9fe82834e2546bff03bef38644de95ffbeaba0 commit + d89ce51a3b4be96d12066eadbcffc0587a2673a6 blob - 4e2741d1b6bfb27bf9c674cd160001b82c1d1e58 blob + 171a6494387ccdb7273ed6b046c1ab74d6326bad --- acid/port +++ acid/port @@ -84,7 +84,7 @@ defn _stkign(frame) // only print the last one. defn _stk(regs, dolocals) { - local stk, pc, fn, callerpc, paramlist, locallist; + local stk, pc, fn, done, callerpc, paramlist, locallist; stk = strace(regs); if stkignore then { @@ -93,7 +93,8 @@ defn _stk(regs, dolocals) } callerpc = 0; - while stk do { + done = 0; + while stk && !done do { frame = head stk; stk = tail stk; fn = frame[0]; @@ -111,9 +112,15 @@ defn _stk(regs, dolocals) pfl(pc); if dolocals then locals(locallist); + if fn == var("threadmain") || fn == var("p9main") then + done=1; + if fn == var("threadstart") || fn == var("scheduler") then + done=1; + if callerpc == 0 then + done=1; } - if callerpc then { + if callerpc && !done then { print(stkprefix, fmt(callerpc, 'a'), " "); pfl(callerpc); } blob - ba566b7ec54ea649c3d62e30e70f58dbc64a4299 blob + 4ec0b47a82a478c612cb52cc0d02ee783f544ffa --- acid/thread +++ acid/thread @@ -1,29 +1,96 @@ +// +// pthread-specific access functions +// avoid complicated libthread_db interface +// -defn labpc(l) -{ - complex Label l; +// Linux NPTL 2.3.2 +complex list_head { + 'X' 0 next; + 'X' 4 prev; +}; +complex nptl_pthread { + 'X' 0 loopback; + 'X' 0x48 tid; +}; +defn isnptl() { + return var("nptl_version") != {}; +} +defn nptl2tid(p) { + complex nptl_pthread p; + if p.loopback != p then + error("bad pthread "+itoa(p, "%x")); + return p.tid; +} +defn nptlpthreadlist() { + local all, p, n, l; - return l.pc; + all = {}; + l = (list_head)stack_used; + l = (list_head)l.next; + while l != stack_used do { + p = l - *_thread_db_pthread_list; + all = append all, p; + l = (list_head)l.next; + } + return all; } -defn label(l) +// +// Generic dispatch +// +defn pthreadlibrary() { + if var("_pthreadlibrary") == {} then { + if isnptl() then + _pthreadlibrary = "nptl"; + else + _pthreadlibrary = "unknown"; + } + return _pthreadlibrary; +} + +defn id2tid(id) { + if pthreadlibrary() == "nptl" then + return nptl2tid(id); + error("unknown pthread library: "+pthreadlibrary); +} + +defn pthreadlist() { + if pthreadlibrary() == "nptl" then + return nptlpthreadlist(id); + error("unknown pthread library: "+pthreadlibrary); +} + +// pick apart system mcontext_t structures +defn mcontext(m) { - complex Label l; + complex mcontext_t m; - if objtype == "386" then - return {"PC", l.pc, "BX", l.bx, "SP", l.sp, "BP", l.bp, "SI", l.si, "DI", l.di}; - return {}; + if systype == "linux" then { + m = m\X; + return {"PC", m[14], "SP", m[7], "BP", m[6]}; + } else if systype == "freebsd" then { + return {"PC", m.mc_eip, "SP", m.mc_esp, "BP", m.mc_ebp}; + } else + error("do not know how to read mcontext_t on system "+systype); } +// +// plan 9 thread library support +// +defn context(c) +{ + c = (Context)c; + return mcontext(c.uc.uc_mcontext); +} -defn labstk(l) +defn contextstk(c) { - _stk(label(l), 0); + _stk(context(c), 0); } -defn lablstk(l) +defn contextlstk(c) { - _stk(label(l), 1); + _stk(context(c), 1); } defn altfmt(A){ @@ -61,6 +128,52 @@ defn alt(A){ print(altfmt(A), "\n"); } +defn channel(C) { + complex Channel C; + local i, p; + + print("channel ", C\X, " // ", *(C.name\s)); + if C.freed then { + print(" (moribund)"); + } + print("\n"); + print("\telemsize=", C.elemsize\D, " bufsize=", C.bufsize, "\n"); + if C.bufsize then { + print("\t", C.nbuf\D, " values in channel:\n"); + print("\t"); + p = C.buf+C.off*C.elemsize; + loop 1,C.nbuf do { + if C.elemsize==4 then { + print(*p\X, " "); + }else { + print("data(", p\X, ") "); + } + p = p+C.elemsize; + if p == C.buf+C.bufsize*C.elemsize then { + p = C.buf; + } + } + } + print("\n"); + print(" senders:\n"); + _altarray(C.asend); + print(" recvers:\n"); + _altarray(C.arecv); +} + +defn _altarray(aa) +{ + local i, a, t; + + i = 0; + aa = (_Altarray)aa; + while i < aa.n do { + a = (Alt)aa.a[i]; + print("\t"+threadstkline(a.thread)+"\n"); + i++; + } +} + defn fnname(a){ local sym, s; @@ -75,7 +188,6 @@ defn fnname(a){ } stkignorelist = {}; - defn stkignore(s){ append stkignorelist, s; } @@ -83,14 +195,15 @@ defn stkignore(s){ defn threadstkline(T){ local stk, frame, pc, pc0, file, s, sym, i, stop, P, mainpid; - if T.state == Running then { - P = (Proc)T.proc; + T = (_Thread)T; + P = (Proc)T.proc; + if P.thread == T then { mainpid = pid; - if mainpid != P.pid then setproc(P.pid); + setproc(id2tid(P.osprocid)); stk = strace({}); - if mainpid != P.pid then setproc(mainpid); + setproc(mainpid); } else - stk = strace(label(T.sched)); + stk = strace(context(T.context)); stop = 0; while stk && !stop do { @@ -101,6 +214,7 @@ defn threadstkline(T){ file = pcfile(pc); if !regexp("plan9/src/lib9/", file) && !regexp("plan9/src/libthread/", file) + && file != "?file?" && match(file, stkignore)==-1 then stop = 1; } @@ -112,37 +226,21 @@ defn threadstkline(T){ } defn threadfmt(T){ - complex Thread T; - local A, yes, i, P, s; + complex _Thread T; + local P, s, name; P = (Proc)T.proc; - s = "t=(Thread)"+itoa(T, "%-10x")+" // "; + s = "t=(_Thread)"+itoa(T, "%-10x")+" // "; - if T.state == Running then + if P.thread == T then s = s + "Running "; - else if T.state == Ready then - s = s + "Ready "; - else if T.state == Rendezvous then - s = s + "Rendez "; else - s = s + "Bad state "+itoa(T.state, "%x")+" "; + s = s + "Sleeping "; + s = s + threadstkline(T); - A = (Alt)T.alt; - if 1 then - s = s + threadstkline(T); - else if T.chan == Chanalt then - s = s + altfmt(T.alt); - else if T.chan == Chansend then - s = s + "send(Channel("+itoa(A.c, "%x")+"))"; - else if T.chan == Chanrecv then - s = s + "recv(Channel("+itoa(A.c, "%x")+"))"; - else - s = s + threadstkline(T); - - if T.moribund == 1 then - s = s + " Moribund"; - if T.cmdname != 0 then - s = s + " ["+*(T.cmdname\s)+"]"; + name = T+392; // T+offsetof(_Thread, name); + if *(name\b) != 0 then + s = s + " ["+*(name\s)+"]"; return s; } @@ -150,86 +248,43 @@ defn thread(T){ print(threadfmt(T), "\n"); } -defn pthreads(P){ +defn procthreads(P){ complex Proc P; - local T, Tq, mainpid; + local T; - mainpid = pid; - Tq = (Tqueue)P.threads; - T = (Thread)Tq.$head; + T = (_Thread)P.allthreads.$head; while T != 0 do{ print("\t"); thread(T); - T = (Thread)T.nextt; + T = (_Thread)T.allnext; } } -defn threads(){ +defn prociter(x) { local P; - complex Pqueue _threadpq; - P = (Proc)_threadpq.$head; + P = (Proc)*_threadprocs; while P != 0 do{ - if P != (Proc)_threadpq.$head then print("\n"); - lproc(P); + if P != (Proc)*_threadprocs then print("\n"); + proc(P); + if x == 1 then + procthreads(P); + if x == 2 then + threadstks(P); P = (Proc)P.next; } } -defn stacks(){ - local P, mainpid; - complex Pqueue _threadpq; - - stkprefix = ""; - mainpid = pid; - P = (Proc)_threadpq.$head; - while P != 0 do{ - proc(P); - if mainpid != P.pid then setproc(P.pid); - // setproc(P.pid); - // if P.thread==0 then{ - // print("=== thread scheduler stack\n"); - // stk(); - // } - // print("threadstks(", P\X, ")\n"); - threadstks(P); - if mainpid != P.pid then setproc(mainpid); - P = (Proc)P.next; - print("\n"); - } - // setproc(mainpid); +defn procs() { + prociter(0); } -defn stacksizes(){ - local P, T, Tq, top, sp, mainpid; - complex Pqueue _threadpq; - - mainpid = pid; - P = (Proc)_threadpq.$head; - while P != 0 do{ - P = (Proc)P; - if mainpid != P.pid then setproc(P.pid); - Tq = (Tqueue)P.threads; - T = (Thread)Tq.$head; - while T != 0 do{ - top = T.stk+T.stksize; - if T.state==Running then { - sp = *SP; - }else{ - sp = T.sched.sp; - } - print(top-sp\D, " of ", T.stksize\D, " - 0x", top\X, " 0x", sp\X, " ", *T.stk\X, "\n"); - T = (Thread)T.nextt; - } - if mainpid != P.pid then setproc(mainpid); - P = P.next; - } - // setproc(mainpid); +defn threads() { + prociter(1); } -defn lproc(P){ - proc(P); - pthreads(P); +defn stacks() { + prociter(2); } threadstkignore = { @@ -239,23 +294,20 @@ threadstkignore = { }; defn threadstks(P){ complex Proc P; - local T, Tq, mainpid, pref, ign; + local T, mainpid, pref, ign; - mainpid = pid; + // mainpid = pid; pref = stkprefix; stkprefix = pref+"\t\t"; ign = stkignore; stkignore = threadstkignore; // setproc(P.pid); - Tq = (Tqueue)P.threads; - T = (Thread)Tq.$head; + T = (_Thread)P.allthreads.$head; while T != 0 do{ - // print("=============================\n"); - // print(" thread(", T\X, ")\n"); print("\t"); thread(T); threadstk(T); - T = (Thread)T.nextt; + T = (_Thread)T.allnext; print("\n"); } // setproc(mainpid); @@ -266,7 +318,7 @@ defn threadstks(P){ defn proc(P){ complex Proc P; - print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " "); + print("p=(Proc)", itoa(P, "%-10x"), " // pthread ", P.osprocid\X, " pid ", id2tid(P.osprocid)\D, " "); if P.thread==0 then print(" Sched"); else @@ -274,123 +326,35 @@ defn proc(P){ print("\n"); } -defn procs(){ - local P; - complex Pqueue _threadpq; - - P = (Proc)_threadpq.$head; - while P != 0 do{ - proc(P); - P = P.next; - } -} - defn threadlstk(T){ - complex Thread T; + complex _Thread T; local P, mainpid; P = (Proc)T.proc; - // mainpid = pid; - // setproc(P.pid); + mainpid = pid; + setproc(id2tid(P.osprocid)); - if T.state == Running then{ + if P.thread == T then lstk(); - } else { - lablstk(T.sched); - } - // setproc(mainpid); + else + contextlstk(T.context); + setproc(mainpid); } defn threadstk(T){ - complex Thread T; + complex _Thread T; local P, mainpid; P = (Proc)T.proc; mainpid = pid; - // setproc(P.pid); + setproc(id2tid(P.osprocid)); - if T.state == Running then{ - if P.pid != mainpid then - setproc(P.pid); + if P.thread == T then stk(); - if P.pid != mainpid then - setproc(mainpid); - } else { - labstk(T.sched); - } - // setproc(mainpid); -} + else + contextstk(T.context); -defn tqueue(Q) { - complex Tqueue Q; - - while Q != 0 do { - print(Q.$head\X, " "); - Q = *(Q.$tail); - - } - print("#\n"); + setproc(mainpid); } -defn channel(C) { - complex Channel C; - local i, p; - - print("channel ", C\X); - if C.freed then { - print(" (moribund)"); - } - print("\n"); - print("\telementsize=", C.e\D, " buffersize=", C.s, "\n"); - if C.s then { - print("\t", C.n\D, " values in channel:\n"); - print("\t"); - p = C.v+C.e*(C.f%C.s); - loop 1,C.n do { - if C.e==4 then { - print((*p)\X, " "); - }else { - print("data(", (*p)\X, ") "); - } - p = p+C.e; - if p == C.v+C.s*C.e then { - p = C.v; - } - } - } - print("\n"); - print(C.nentry\D, " queue slots:\n"); - i=0; - loop 1,C.nentry do { - if C.qentry[i] then - print("\t", altfmt(C.qentry[i]), "\n"); - else - print("\t\n"); - i=i+1; - } -} - -defn polling() { - local i, c, t, p, pf; - - p=(Poll)polls; pf=(struct_pollfd)pfd; loop 1,*npoll do { - print("\tfd ", pf.fd\D, " "); - if pf.events & 1 then - print("r"); - else if pf.events & 2 then - print("w"); - else - print(pf.events\D); - print(" chan Channel(", p.c\X, ")\n"); - p = (Poll)(p+sizeofPoll); - pf = (struct_pollfd)(pf+sizeofstruct_pollfd); - } - - c=sleepchan; t=sleeptime; loop 1,*nsleep do { - print("\tsleep ", *t\D, " Channel(", *c\X, ")\n"); - c++; - t++; - } -} - print(acidfile);