2005-02-11 02:14:59 +00:00
|
|
|
//
|
|
|
|
// pthread-specific access functions
|
|
|
|
// avoid complicated libthread_db interface
|
|
|
|
//
|
|
|
|
|
2005-02-11 16:51:43 +00:00
|
|
|
include("pthread-"+systype+"-"+objtype);
|
2005-02-11 02:14:59 +00:00
|
|
|
|
|
|
|
// pick apart system mcontext_t structures
|
|
|
|
defn mcontext(m)
|
2004-04-19 18:18:37 +00:00
|
|
|
{
|
2005-02-11 02:14:59 +00:00
|
|
|
complex mcontext_t m;
|
2004-04-19 18:52:34 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
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);
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
//
|
|
|
|
// plan 9 thread library support
|
|
|
|
//
|
|
|
|
defn context(c)
|
|
|
|
{
|
|
|
|
c = (Context)c;
|
|
|
|
return mcontext(c.uc.uc_mcontext);
|
|
|
|
}
|
2004-04-19 18:52:34 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
defn contextstk(c)
|
2004-04-19 18:18:37 +00:00
|
|
|
{
|
2005-02-11 02:14:59 +00:00
|
|
|
_stk(context(c), 0);
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
defn contextlstk(c)
|
2004-04-19 18:18:37 +00:00
|
|
|
{
|
2005-02-11 02:14:59 +00:00
|
|
|
_stk(context(c), 1);
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
defn altfmt(A){
|
|
|
|
local i, s, yes;
|
|
|
|
complex Alt A;
|
|
|
|
|
|
|
|
s = "alt(";
|
2005-02-11 16:51:43 +00:00
|
|
|
s = s + "tag(*" + itoa(A.tag, "%#x") + "=" + itoa(*A.tag, "%#x") + ") ";
|
2004-04-19 18:18:37 +00:00
|
|
|
i = 0;
|
|
|
|
yes = 0;
|
|
|
|
while A.op != CHANEND && A.op != CHANNOBLK do{
|
|
|
|
if A.op != CHANNOP then{
|
|
|
|
if yes then s = s + " ";
|
|
|
|
s = s + itoa(i, "%d");
|
|
|
|
s = s + ":";
|
|
|
|
if A.op == CHANSND then s = s + "send";
|
|
|
|
if A.op == CHANRCV then s = s + "recv";
|
|
|
|
s = s + "(channel(";
|
2005-02-11 16:51:43 +00:00
|
|
|
s = s + itoa(A.c, "%#x");
|
2004-04-19 18:18:37 +00:00
|
|
|
s = s + "))";
|
|
|
|
yes = 1;
|
|
|
|
}
|
|
|
|
i = i + 1;
|
|
|
|
A = (Alt)(A + sizeofAlt);
|
|
|
|
}
|
|
|
|
if A.op==CHANNOBLK then{
|
|
|
|
if yes then s = s + " ";
|
|
|
|
s = s + "noblock";
|
|
|
|
}
|
|
|
|
s = s + ")";
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
defn alt(A){
|
|
|
|
print(altfmt(A), "\n");
|
|
|
|
}
|
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-04-19 18:18:37 +00:00
|
|
|
defn fnname(a){
|
|
|
|
local sym, s;
|
|
|
|
|
|
|
|
s = symbols;
|
|
|
|
while s do {
|
|
|
|
sym = head s;
|
|
|
|
if sym[2] == a then
|
|
|
|
return sym[0];
|
|
|
|
s = tail s;
|
|
|
|
}
|
2005-02-11 16:51:43 +00:00
|
|
|
return itoa(a, "%#x");
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
stkignorelist = {};
|
|
|
|
defn stkignore(s){
|
|
|
|
append stkignorelist, s;
|
|
|
|
}
|
|
|
|
|
|
|
|
defn threadstkline(T){
|
2004-05-23 00:58:00 +00:00
|
|
|
local stk, frame, pc, pc0, file, s, sym, i, stop, P, mainpid;
|
2004-04-19 18:52:34 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
T = (_Thread)T;
|
|
|
|
P = (Proc)T.proc;
|
|
|
|
if P.thread == T then {
|
2004-05-23 00:58:00 +00:00
|
|
|
mainpid = pid;
|
2005-02-11 16:51:43 +00:00
|
|
|
setproc(pthread2tid(P.osprocid));
|
2004-04-19 18:52:34 +00:00
|
|
|
stk = strace({});
|
2005-02-11 02:14:59 +00:00
|
|
|
setproc(mainpid);
|
2004-05-23 00:58:00 +00:00
|
|
|
} else
|
2005-02-11 02:14:59 +00:00
|
|
|
stk = strace(context(T.context));
|
2004-04-19 18:18:37 +00:00
|
|
|
|
|
|
|
stop = 0;
|
|
|
|
while stk && !stop do {
|
2004-04-19 18:52:34 +00:00
|
|
|
frame = head stk;
|
|
|
|
stk = tail stk;
|
|
|
|
pc = frame[2];
|
|
|
|
pc0 = frame[0];
|
2004-04-19 18:18:37 +00:00
|
|
|
file = pcfile(pc);
|
2004-05-05 04:22:16 +00:00
|
|
|
if !regexp("plan9/src/lib9/", file)
|
2004-04-19 18:52:34 +00:00
|
|
|
&& !regexp("plan9/src/libthread/", file)
|
2005-02-11 02:14:59 +00:00
|
|
|
&& file != "?file?"
|
2004-04-19 18:18:37 +00:00
|
|
|
&& match(file, stkignore)==-1 then
|
|
|
|
stop = 1;
|
|
|
|
}
|
|
|
|
file = pcfile(pc);
|
|
|
|
s = file+":"+itoa(pcline(pc), "%d");
|
|
|
|
if pc0 != 0 then
|
|
|
|
s = s + " "+fnname(pc0);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
defn threadfmt(T){
|
2005-02-11 02:14:59 +00:00
|
|
|
complex _Thread T;
|
|
|
|
local P, s, name;
|
2004-04-19 18:18:37 +00:00
|
|
|
|
|
|
|
P = (Proc)T.proc;
|
2005-02-11 16:51:43 +00:00
|
|
|
s = "t=(_Thread)"+itoa(T, "%#-10x")+" // ";
|
2004-04-19 18:18:37 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
if P.thread == T then
|
2004-04-19 18:18:37 +00:00
|
|
|
s = s + "Running ";
|
|
|
|
else
|
2005-02-11 02:14:59 +00:00
|
|
|
s = s + "Sleeping ";
|
|
|
|
s = s + threadstkline(T);
|
2004-04-19 18:18:37 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
name = T+392; // T+offsetof(_Thread, name);
|
|
|
|
if *(name\b) != 0 then
|
|
|
|
s = s + " ["+*(name\s)+"]";
|
2004-04-19 18:18:37 +00:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
defn thread(T){
|
|
|
|
print(threadfmt(T), "\n");
|
|
|
|
}
|
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
defn procthreads(P){
|
2004-04-19 18:18:37 +00:00
|
|
|
complex Proc P;
|
2005-02-11 02:14:59 +00:00
|
|
|
local T;
|
2004-04-19 18:18:37 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
T = (_Thread)P.allthreads.$head;
|
2004-04-19 18:18:37 +00:00
|
|
|
while T != 0 do{
|
|
|
|
print("\t");
|
|
|
|
thread(T);
|
2005-02-11 02:14:59 +00:00
|
|
|
T = (_Thread)T.allnext;
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
defn prociter(x) {
|
2004-04-19 18:18:37 +00:00
|
|
|
local P;
|
2004-04-20 05:05:38 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
P = (Proc)*_threadprocs;
|
2004-04-19 18:18:37 +00:00
|
|
|
while P != 0 do{
|
2005-02-11 02:14:59 +00:00
|
|
|
if P != (Proc)*_threadprocs then print("\n");
|
2004-04-19 18:18:37 +00:00
|
|
|
proc(P);
|
2005-02-11 02:14:59 +00:00
|
|
|
if x == 1 then
|
|
|
|
procthreads(P);
|
|
|
|
if x == 2 then
|
|
|
|
threadstks(P);
|
2004-04-19 18:52:34 +00:00
|
|
|
P = (Proc)P.next;
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
defn procs() {
|
|
|
|
prociter(0);
|
|
|
|
}
|
2004-04-19 18:18:37 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
defn threads() {
|
|
|
|
prociter(1);
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
defn stacks() {
|
|
|
|
prociter(2);
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
2004-04-20 05:05:38 +00:00
|
|
|
threadstkignore = {
|
|
|
|
"plan9/src/libthread/",
|
2004-05-05 04:22:16 +00:00
|
|
|
"plan9/src/lib9/",
|
|
|
|
"plan9/src/lib9/(fmt|utf)/",
|
2004-04-20 05:05:38 +00:00
|
|
|
};
|
2004-04-19 18:18:37 +00:00
|
|
|
defn threadstks(P){
|
|
|
|
complex Proc P;
|
2005-02-11 02:14:59 +00:00
|
|
|
local T, mainpid, pref, ign;
|
2004-04-19 18:18:37 +00:00
|
|
|
|
|
|
|
pref = stkprefix;
|
|
|
|
stkprefix = pref+"\t\t";
|
|
|
|
ign = stkignore;
|
2004-04-20 05:05:38 +00:00
|
|
|
stkignore = threadstkignore;
|
2005-02-11 02:14:59 +00:00
|
|
|
T = (_Thread)P.allthreads.$head;
|
2004-04-19 18:18:37 +00:00
|
|
|
while T != 0 do{
|
|
|
|
print("\t");
|
|
|
|
thread(T);
|
|
|
|
threadstk(T);
|
2005-02-11 02:14:59 +00:00
|
|
|
T = (_Thread)T.allnext;
|
2004-04-19 18:18:37 +00:00
|
|
|
print("\n");
|
|
|
|
}
|
|
|
|
stkprefix = pref;
|
|
|
|
stkignore = ign;
|
|
|
|
}
|
|
|
|
|
|
|
|
defn proc(P){
|
|
|
|
complex Proc P;
|
|
|
|
|
2005-02-11 16:51:43 +00:00
|
|
|
print("p=(Proc)", itoa(P, "%#-10x"), " // pthread ", P.osprocid\X, " pid ", pthread2tid(P.osprocid)\D, " ");
|
2004-04-19 18:18:37 +00:00
|
|
|
if P.thread==0 then
|
|
|
|
print(" Sched");
|
|
|
|
else
|
|
|
|
print(" Running");
|
|
|
|
print("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
defn threadlstk(T){
|
2005-02-11 02:14:59 +00:00
|
|
|
complex _Thread T;
|
2004-04-19 18:18:37 +00:00
|
|
|
local P, mainpid;
|
|
|
|
|
|
|
|
P = (Proc)T.proc;
|
2005-02-11 02:14:59 +00:00
|
|
|
mainpid = pid;
|
2005-02-11 16:51:43 +00:00
|
|
|
setproc(pthread2tid(P.osprocid));
|
2004-04-19 18:18:37 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
if P.thread == T then
|
2004-04-19 18:18:37 +00:00
|
|
|
lstk();
|
2005-02-11 02:14:59 +00:00
|
|
|
else
|
|
|
|
contextlstk(T.context);
|
|
|
|
setproc(mainpid);
|
2004-04-19 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
defn threadstk(T){
|
2005-02-11 02:14:59 +00:00
|
|
|
complex _Thread T;
|
2004-04-19 18:18:37 +00:00
|
|
|
local P, mainpid;
|
|
|
|
|
|
|
|
P = (Proc)T.proc;
|
|
|
|
mainpid = pid;
|
2005-02-11 16:51:43 +00:00
|
|
|
setproc(pthread2tid(P.osprocid));
|
2004-04-19 18:18:37 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
if P.thread == T then
|
2004-04-19 18:18:37 +00:00
|
|
|
stk();
|
2005-02-11 02:14:59 +00:00
|
|
|
else
|
|
|
|
contextstk(T.context);
|
2004-04-19 18:18:37 +00:00
|
|
|
|
2005-02-11 02:14:59 +00:00
|
|
|
setproc(mainpid);
|
2004-04-20 05:05:38 +00:00
|
|
|
}
|
|
|
|
|
2004-04-19 18:18:37 +00:00
|
|
|
print(acidfile);
|