From 0a61c07d591273b76da21fb8386b669989da3707 Mon Sep 17 00:00:00 2001 From: rsc Date: Mon, 19 Apr 2004 18:18:37 +0000 Subject: acid files --- acid/thread | 365 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 acid/thread (limited to 'acid/thread') diff --git a/acid/thread b/acid/thread new file mode 100644 index 00000000..ac4cce8a --- /dev/null +++ b/acid/thread @@ -0,0 +1,365 @@ + +defn labpc(l) +{ + if objtype == "386" then + return longjmp; + return *(l+4); +} + +defn labsp(l) +{ + return *l; +} + +defn labstk(l) +{ + _stk(labpc(l), labsp(l), 0, 0); +} + +defn lablstk(l) +{ + _stk(labpc(l), labsp(l), 0, 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 = { + "^/sys/src/libc", + "^/sys/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, lastpc0, s, sym, i, stop; + + if T.state == Running then{ + pc = *PC; + stk = strace(*PC, *SP, linkreg(0)); + }else{ + pc = labpc(T.sched); + stk = strace(labpc(T.sched), labsp(T.sched), 0); + } + lastpc0 = 0; + pc0 = 0; + stop = 0; + while stk && !stop do { + file = pcfile(pc); + if !regexp("^/sys/src/libc/", file) + && !regexp("^/sys/src/libthread/", file) + && match(file, stkignore)==-1 then + stop = 1; + else{ + lastpc0 = pc0; + frame = head stk; + stk = tail stk; + nextframe = head stk; + pc = frame[1]; + pc0 = nextframe[0]; + } + } + 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 = T.nextt; + } + setproc(mainpid); +} + +defn threads(){ + local P; + + P = (Proc)_threadpq.$head; + while P != 0 do{ + if P != (Proc)_threadpq.$head then print("\n"); + lproc(P); + P = P.next; + } +} + +defn stacks(){ + local P, mainpid; + + 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 = P.next; + print("\n"); + } + setproc(mainpid); +} + +defn stacksizes(){ + local P, T, Tq, top, sp, mainpid; + + 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 = T.nextt; + } + P = P.next; + } + setproc(mainpid); +} + +defn lproc(P){ + proc(P); + pthreads(P); +} + +defn threadstks(P){ + complex Proc P; + local T, Tq, mainpid, pref, ign; + + mainpid = pid; + pref = stkprefix; + stkprefix = pref+"\t\t"; + ign = stkignore; + stkignore = { + "^/sys/src/libthread/", + "^/sys/src/libc/(386|arm|alpha|sparc|power|mips)/" + }; + 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 = 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; + + 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\n"); + i=i+1; + } +} + +print(acidfile); -- cgit v1.2.3