mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
391 lines
6.4 KiB
Text
391 lines
6.4 KiB
Text
|
|
defn labpc(l)
|
|
{
|
|
complex Label l;
|
|
|
|
return l.pc;
|
|
}
|
|
|
|
defn label(l)
|
|
{
|
|
complex Label l;
|
|
|
|
if objtype == "386" then
|
|
return {"PC", l.pc, "BX", l.bx, "SP", l.sp, "BP", l.bp, "SI", l.si, "DI", l.di};
|
|
return {};
|
|
}
|
|
|
|
|
|
defn labstk(l)
|
|
{
|
|
_stk(label(l), 0);
|
|
}
|
|
|
|
defn lablstk(l)
|
|
{
|
|
_stk(label(l), 1);
|
|
}
|
|
|
|
defn altfmt(A){
|
|
local i, s, yes;
|
|
complex Alt A;
|
|
|
|
s = "alt(";
|
|
s = s + "tag(*" + itoa(A.tag, "%x") + "=" + itoa(*A.tag, "%x") + ") ";
|
|
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(";
|
|
s = s + itoa(A.c, "%x");
|
|
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");
|
|
}
|
|
|
|
threadignsrc = {
|
|
"plan9/src/libc",
|
|
"plan9/src/libthread",
|
|
};
|
|
|
|
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;
|
|
}
|
|
return itoa(a, "%x");
|
|
}
|
|
|
|
stkignorelist = {};
|
|
|
|
defn stkignore(s){
|
|
append stkignorelist, s;
|
|
}
|
|
|
|
defn threadstkline(T){
|
|
local stk, frame, pc, pc0, file, s, sym, i, stop;
|
|
|
|
if T.state == Running then
|
|
stk = strace({});
|
|
else
|
|
stk = strace(label(T.sched));
|
|
|
|
stop = 0;
|
|
while stk && !stop do {
|
|
frame = head stk;
|
|
stk = tail stk;
|
|
pc = frame[2];
|
|
pc0 = frame[0];
|
|
file = pcfile(pc);
|
|
if !regexp("plan9/src/libc/", file)
|
|
&& !regexp("plan9/src/libthread/", file)
|
|
&& 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){
|
|
complex Thread T;
|
|
local A, yes, i, P, s;
|
|
|
|
P = (Proc)T.proc;
|
|
s = "t=(Thread)"+itoa(T, "%-10x")+" ";
|
|
|
|
if T.state == Running 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")+" ";
|
|
|
|
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)+"]";
|
|
return s;
|
|
}
|
|
|
|
defn thread(T){
|
|
print(threadfmt(T), "\n");
|
|
}
|
|
|
|
defn pthreads(P){
|
|
complex Proc P;
|
|
local T, Tq, mainpid;
|
|
|
|
mainpid = pid;
|
|
setproc(P.pid);
|
|
Tq = (Tqueue)P.threads;
|
|
T = (Thread)Tq.$head;
|
|
while T != 0 do{
|
|
print("\t");
|
|
thread(T);
|
|
T = (Thread)T.nextt;
|
|
}
|
|
setproc(mainpid);
|
|
}
|
|
|
|
defn threads(){
|
|
local P;
|
|
complex Pqueue _threadpq;
|
|
|
|
P = (Proc)_threadpq.$head;
|
|
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{
|
|
proc(P);
|
|
// setproc(P.pid);
|
|
// if P.thread==0 then{
|
|
// print("=== thread scheduler stack\n");
|
|
// stk();
|
|
// }
|
|
// print("threadstks(", P\X, ")\n");
|
|
threadstks(P);
|
|
P = (Proc)P.next;
|
|
print("\n");
|
|
}
|
|
setproc(mainpid);
|
|
}
|
|
|
|
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;
|
|
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 = *(T.sched);
|
|
print(top-sp\D, "\n");
|
|
T = (Thread)T.nextt;
|
|
}
|
|
P = P.next;
|
|
}
|
|
setproc(mainpid);
|
|
}
|
|
|
|
defn lproc(P){
|
|
proc(P);
|
|
pthreads(P);
|
|
}
|
|
|
|
threadstkignore = {
|
|
"plan9/src/libthread/",
|
|
"plan9/src/libc/(386|arm|alpha|sparc|power|mips)/"
|
|
};
|
|
defn threadstks(P){
|
|
complex Proc P;
|
|
local T, Tq, mainpid, pref, ign;
|
|
|
|
mainpid = pid;
|
|
pref = stkprefix;
|
|
stkprefix = pref+"\t\t";
|
|
ign = stkignore;
|
|
stkignore = threadstkignore;
|
|
setproc(P.pid);
|
|
Tq = (Tqueue)P.threads;
|
|
T = (Thread)Tq.$head;
|
|
while T != 0 do{
|
|
// print("=============================\n");
|
|
// print(" thread(", T\X, ")\n");
|
|
print("\t");
|
|
thread(T);
|
|
threadstk(T);
|
|
T = (Thread)T.nextt;
|
|
print("\n");
|
|
}
|
|
setproc(mainpid);
|
|
stkprefix = pref;
|
|
stkignore = ign;
|
|
}
|
|
|
|
defn proc(P){
|
|
complex Proc P;
|
|
|
|
print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");
|
|
if P.thread==0 then
|
|
print(" Sched");
|
|
else
|
|
print(" Running");
|
|
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;
|
|
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;
|
|
|
|
P = (Proc)T.proc;
|
|
mainpid = pid;
|
|
setproc(P.pid);
|
|
|
|
if T.state == Running then{
|
|
stk();
|
|
} else {
|
|
labstk(T.sched);
|
|
}
|
|
setproc(mainpid);
|
|
}
|
|
|
|
defn tqueue(Q) {
|
|
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);
|