different pthread support

This commit is contained in:
rsc 2005-02-11 02:14:59 +00:00
parent ed9fe82834
commit d89ce51a3b
2 changed files with 201 additions and 230 deletions

View file

@ -84,7 +84,7 @@ defn _stkign(frame)
// only print the last one. // only print the last one.
defn _stk(regs, dolocals) defn _stk(regs, dolocals)
{ {
local stk, pc, fn, callerpc, paramlist, locallist; local stk, pc, fn, done, callerpc, paramlist, locallist;
stk = strace(regs); stk = strace(regs);
if stkignore then { if stkignore then {
@ -93,7 +93,8 @@ defn _stk(regs, dolocals)
} }
callerpc = 0; callerpc = 0;
while stk do { done = 0;
while stk && !done do {
frame = head stk; frame = head stk;
stk = tail stk; stk = tail stk;
fn = frame[0]; fn = frame[0];
@ -111,9 +112,15 @@ defn _stk(regs, dolocals)
pfl(pc); pfl(pc);
if dolocals then if dolocals then
locals(locallist); 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'), " "); print(stkprefix, fmt(callerpc, 'a'), " ");
pfl(callerpc); pfl(callerpc);
} }

View file

@ -1,29 +1,96 @@
//
// pthread-specific access functions
// avoid complicated libthread_db interface
//
defn labpc(l) // Linux NPTL 2.3.2
{ complex list_head {
complex Label l; '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
complex Label l; //
defn pthreadlibrary() {
if objtype == "386" then if var("_pthreadlibrary") == {} then {
return {"PC", l.pc, "BX", l.bx, "SP", l.sp, "BP", l.bp, "SI", l.si, "DI", l.di}; if isnptl() then
return {}; _pthreadlibrary = "nptl";
else
_pthreadlibrary = "unknown";
}
return _pthreadlibrary;
} }
defn id2tid(id) {
defn labstk(l) if pthreadlibrary() == "nptl" then
{ return nptl2tid(id);
_stk(label(l), 0); error("unknown pthread library: "+pthreadlibrary);
} }
defn lablstk(l) defn pthreadlist() {
if pthreadlibrary() == "nptl" then
return nptlpthreadlist(id);
error("unknown pthread library: "+pthreadlibrary);
}
// pick apart system mcontext_t structures
defn mcontext(m)
{ {
_stk(label(l), 1); complex mcontext_t m;
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 contextstk(c)
{
_stk(context(c), 0);
}
defn contextlstk(c)
{
_stk(context(c), 1);
} }
defn altfmt(A){ defn altfmt(A){
@ -61,6 +128,52 @@ defn alt(A){
print(altfmt(A), "\n"); 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){ defn fnname(a){
local sym, s; local sym, s;
@ -75,7 +188,6 @@ defn fnname(a){
} }
stkignorelist = {}; stkignorelist = {};
defn stkignore(s){ defn stkignore(s){
append stkignorelist, s; append stkignorelist, s;
} }
@ -83,14 +195,15 @@ defn stkignore(s){
defn threadstkline(T){ defn threadstkline(T){
local stk, frame, pc, pc0, file, s, sym, i, stop, P, mainpid; local stk, frame, pc, pc0, file, s, sym, i, stop, P, mainpid;
if T.state == Running then { T = (_Thread)T;
P = (Proc)T.proc; P = (Proc)T.proc;
if P.thread == T then {
mainpid = pid; mainpid = pid;
if mainpid != P.pid then setproc(P.pid); setproc(id2tid(P.osprocid));
stk = strace({}); stk = strace({});
if mainpid != P.pid then setproc(mainpid); setproc(mainpid);
} else } else
stk = strace(label(T.sched)); stk = strace(context(T.context));
stop = 0; stop = 0;
while stk && !stop do { while stk && !stop do {
@ -101,6 +214,7 @@ defn threadstkline(T){
file = pcfile(pc); file = pcfile(pc);
if !regexp("plan9/src/lib9/", file) if !regexp("plan9/src/lib9/", file)
&& !regexp("plan9/src/libthread/", file) && !regexp("plan9/src/libthread/", file)
&& file != "?file?"
&& match(file, stkignore)==-1 then && match(file, stkignore)==-1 then
stop = 1; stop = 1;
} }
@ -112,37 +226,21 @@ defn threadstkline(T){
} }
defn threadfmt(T){ defn threadfmt(T){
complex Thread T; complex _Thread T;
local A, yes, i, P, s; local P, s, name;
P = (Proc)T.proc; 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 "; s = s + "Running ";
else if T.state == Ready then
s = s + "Ready ";
else if T.state == Rendezvous then
s = s + "Rendez ";
else else
s = s + "Bad state "+itoa(T.state, "%x")+" "; s = s + "Sleeping ";
s = s + threadstkline(T);
A = (Alt)T.alt; name = T+392; // T+offsetof(_Thread, name);
if 1 then if *(name\b) != 0 then
s = s + threadstkline(T); s = s + " ["+*(name\s)+"]";
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)+"]";
return s; return s;
} }
@ -150,86 +248,43 @@ defn thread(T){
print(threadfmt(T), "\n"); print(threadfmt(T), "\n");
} }
defn pthreads(P){ defn procthreads(P){
complex Proc P; complex Proc P;
local T, Tq, mainpid; local T;
mainpid = pid; T = (_Thread)P.allthreads.$head;
Tq = (Tqueue)P.threads;
T = (Thread)Tq.$head;
while T != 0 do{ while T != 0 do{
print("\t"); print("\t");
thread(T); thread(T);
T = (Thread)T.nextt; T = (_Thread)T.allnext;
} }
} }
defn threads(){ defn prociter(x) {
local P; 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);
P = (Proc)P.next;
}
}
defn stacks(){
local P, mainpid;
complex Pqueue _threadpq;
stkprefix = "";
mainpid = pid;
P = (Proc)_threadpq.$head;
while P != 0 do{ while P != 0 do{
if P != (Proc)*_threadprocs then print("\n");
proc(P); proc(P);
if mainpid != P.pid then setproc(P.pid); if x == 1 then
// setproc(P.pid); procthreads(P);
// if P.thread==0 then{ if x == 2 then
// print("=== thread scheduler stack\n"); threadstks(P);
// stk();
// }
// print("threadstks(", P\X, ")\n");
threadstks(P);
if mainpid != P.pid then setproc(mainpid);
P = (Proc)P.next; P = (Proc)P.next;
print("\n");
} }
// setproc(mainpid);
} }
defn stacksizes(){ defn procs() {
local P, T, Tq, top, sp, mainpid; prociter(0);
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 lproc(P){ defn threads() {
proc(P); prociter(1);
pthreads(P); }
defn stacks() {
prociter(2);
} }
threadstkignore = { threadstkignore = {
@ -239,23 +294,20 @@ threadstkignore = {
}; };
defn threadstks(P){ defn threadstks(P){
complex Proc P; complex Proc P;
local T, Tq, mainpid, pref, ign; local T, mainpid, pref, ign;
mainpid = pid; // mainpid = pid;
pref = stkprefix; pref = stkprefix;
stkprefix = pref+"\t\t"; stkprefix = pref+"\t\t";
ign = stkignore; ign = stkignore;
stkignore = threadstkignore; stkignore = threadstkignore;
// setproc(P.pid); // setproc(P.pid);
Tq = (Tqueue)P.threads; T = (_Thread)P.allthreads.$head;
T = (Thread)Tq.$head;
while T != 0 do{ while T != 0 do{
// print("=============================\n");
// print(" thread(", T\X, ")\n");
print("\t"); print("\t");
thread(T); thread(T);
threadstk(T); threadstk(T);
T = (Thread)T.nextt; T = (_Thread)T.allnext;
print("\n"); print("\n");
} }
// setproc(mainpid); // setproc(mainpid);
@ -266,7 +318,7 @@ defn threadstks(P){
defn proc(P){ defn proc(P){
complex 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 if P.thread==0 then
print(" Sched"); print(" Sched");
else else
@ -274,123 +326,35 @@ defn proc(P){
print("\n"); 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){ defn threadlstk(T){
complex Thread T; complex _Thread T;
local P, mainpid;
P = (Proc)T.proc;
// mainpid = pid;
// setproc(P.pid);
if T.state == Running then{
lstk();
} else {
lablstk(T.sched);
}
// setproc(mainpid);
}
defn threadstk(T){
complex Thread T;
local P, mainpid; local P, mainpid;
P = (Proc)T.proc; P = (Proc)T.proc;
mainpid = pid; mainpid = pid;
// setproc(P.pid); setproc(id2tid(P.osprocid));
if T.state == Running then{ if P.thread == T then
if P.pid != mainpid then lstk();
setproc(P.pid); else
contextlstk(T.context);
setproc(mainpid);
}
defn threadstk(T){
complex _Thread T;
local P, mainpid;
P = (Proc)T.proc;
mainpid = pid;
setproc(id2tid(P.osprocid));
if P.thread == T then
stk(); stk();
if P.pid != mainpid then else
setproc(mainpid); contextstk(T.context);
} else {
labstk(T.sched);
}
// setproc(mainpid);
}
defn tqueue(Q) { setproc(mainpid);
complex Tqueue Q;
while Q != 0 do {
print(Q.$head\X, " ");
Q = *(Q.$tail);
}
print("#\n");
}
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<empty>\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); print(acidfile);