19a747e4fSDavid du Colombierinclude("/sys/src/libthread/sched.acid"); 27dd7cddfSDavid du Colombier 36ff5e913SDavid du Colombierdefn labpc(l) 47dd7cddfSDavid du Colombier{ 57dd7cddfSDavid du Colombier if objtype == "386" then 66ff5e913SDavid du Colombier return longjmp; 76ff5e913SDavid du Colombier return *(l+4); 86ff5e913SDavid du Colombier} 96ff5e913SDavid du Colombier 106ff5e913SDavid du Colombierdefn labsp(l) 116ff5e913SDavid du Colombier{ 126ff5e913SDavid du Colombier return *l; 136ff5e913SDavid du Colombier} 146ff5e913SDavid du Colombier 156ff5e913SDavid du Colombierdefn labstk(l) 166ff5e913SDavid du Colombier{ 176ff5e913SDavid du Colombier _stk(labpc(l), labsp(l), 0, 0); 187dd7cddfSDavid du Colombier} 197dd7cddfSDavid du Colombier 207dd7cddfSDavid du Colombierdefn lablstk(l) 217dd7cddfSDavid du Colombier{ 226ff5e913SDavid du Colombier _stk(labpc(l), labsp(l), 0, 1); 237dd7cddfSDavid du Colombier} 247dd7cddfSDavid du Colombier 259a747e4fSDavid du Colombierdefn altfmt(A){ 269a747e4fSDavid du Colombier local i, s, yes; 279a747e4fSDavid du Colombier complex Alt A; 289a747e4fSDavid du Colombier 299a747e4fSDavid du Colombier s = "alt("; 306ff5e913SDavid du Colombier s = s + "tag(*" + itoa(A.tag, "%x") + "=" + itoa(*A.tag, "%x") + ") "; 319a747e4fSDavid du Colombier i = 0; 329a747e4fSDavid du Colombier yes = 0; 339a747e4fSDavid du Colombier while A.op != CHANEND && A.op != CHANNOBLK do{ 349a747e4fSDavid du Colombier if A.op != CHANNOP then{ 356ff5e913SDavid du Colombier if yes then s = s + " "; 366ff5e913SDavid du Colombier s = s + itoa(i, "%d"); 379a747e4fSDavid du Colombier s = s + ":"; 389a747e4fSDavid du Colombier if A.op == CHANSND then s = s + "send"; 399a747e4fSDavid du Colombier if A.op == CHANRCV then s = s + "recv"; 409a747e4fSDavid du Colombier s = s + "(channel("; 416ff5e913SDavid du Colombier s = s + itoa(A.c, "%x"); 429a747e4fSDavid du Colombier s = s + "))"; 439a747e4fSDavid du Colombier yes = 1; 449a747e4fSDavid du Colombier } 459a747e4fSDavid du Colombier i = i + 1; 469a747e4fSDavid du Colombier A = (Alt)(A + sizeofAlt); 479a747e4fSDavid du Colombier } 489a747e4fSDavid du Colombier if A.op==CHANNOBLK then{ 496ff5e913SDavid du Colombier if yes then s = s + " "; 509a747e4fSDavid du Colombier s = s + "noblock"; 519a747e4fSDavid du Colombier } 529a747e4fSDavid du Colombier s = s + ")"; 539a747e4fSDavid du Colombier return s; 549a747e4fSDavid du Colombier} 559a747e4fSDavid du Colombier 569a747e4fSDavid du Colombierdefn alt(A){ 579a747e4fSDavid du Colombier print(altfmt(A), "\n"); 589a747e4fSDavid du Colombier} 599a747e4fSDavid du Colombier 606ff5e913SDavid du Colombierthreadignsrc = { 616ff5e913SDavid du Colombier "^/sys/src/libc", 626ff5e913SDavid du Colombier "^/sys/src/libthread", 636ff5e913SDavid du Colombier}; 646ff5e913SDavid du Colombier 656ff5e913SDavid du Colombierdefn fnname(a){ 666ff5e913SDavid du Colombier local sym, s; 676ff5e913SDavid du Colombier 686ff5e913SDavid du Colombier s = symbols; 696ff5e913SDavid du Colombier while s do { 706ff5e913SDavid du Colombier sym = head s; 716ff5e913SDavid du Colombier if sym[2] == a then 726ff5e913SDavid du Colombier return sym[0]; 736ff5e913SDavid du Colombier s = tail s; 746ff5e913SDavid du Colombier } 755ab4dd4cSDavid du Colombier if a == {} then 765ab4dd4cSDavid du Colombier return "{}"; 775ab4dd4cSDavid du Colombier return itoa(a\X, "%x"); 786ff5e913SDavid du Colombier} 796ff5e913SDavid du Colombier 8067031067SDavid du Colombierstkignorelist = {}; 8167031067SDavid du Colombier 8267031067SDavid du Colombierdefn stkignore(s){ 8367031067SDavid du Colombier append stkignorelist, s; 8467031067SDavid du Colombier} 8567031067SDavid du Colombier 866ff5e913SDavid du Colombierdefn threadstkline(T){ 875ab4dd4cSDavid du Colombier local ostk, stk, frame, pc, pc0, file, lastpc0, s, sym, i, stop; 886ff5e913SDavid du Colombier 896ff5e913SDavid du Colombier if T.state == Running then{ 906ff5e913SDavid du Colombier pc = *PC; 916ff5e913SDavid du Colombier stk = strace(*PC, *SP, linkreg(0)); 926ff5e913SDavid du Colombier }else{ 936ff5e913SDavid du Colombier pc = labpc(T.sched); 946ff5e913SDavid du Colombier stk = strace(labpc(T.sched), labsp(T.sched), 0); 956ff5e913SDavid du Colombier } 965ab4dd4cSDavid du Colombier firstpc = pc; 976ff5e913SDavid du Colombier lastpc0 = 0; 986ff5e913SDavid du Colombier pc0 = 0; 996ff5e913SDavid du Colombier stop = 0; 1005ab4dd4cSDavid du Colombier ostk = stk; 1016ff5e913SDavid du Colombier while stk && !stop do { 1026ff5e913SDavid du Colombier file = pcfile(pc); 1036ff5e913SDavid du Colombier if !regexp("^/sys/src/libc/", file) 10467031067SDavid du Colombier && !regexp("^/sys/src/libthread/", file) 10567031067SDavid du Colombier && match(file, stkignore)==-1 then 1066ff5e913SDavid du Colombier stop = 1; 1075ab4dd4cSDavid du Colombier else if stk[0][1] == 0xfefefefe then { 1085ab4dd4cSDavid du Colombier pc = ostk[0][1]; 1095ab4dd4cSDavid du Colombier pc0 = ostk[1][0]; 1105ab4dd4cSDavid du Colombier stop = 1; 1115ab4dd4cSDavid du Colombier }else{ 1126ff5e913SDavid du Colombier lastpc0 = pc0; 1136ff5e913SDavid du Colombier frame = head stk; 1146ff5e913SDavid du Colombier stk = tail stk; 11567031067SDavid du Colombier nextframe = head stk; 1166ff5e913SDavid du Colombier pc = frame[1]; 11767031067SDavid du Colombier pc0 = nextframe[0]; 1186ff5e913SDavid du Colombier } 1196ff5e913SDavid du Colombier } 1206ff5e913SDavid du Colombier file = pcfile(pc); 1216ff5e913SDavid du Colombier s = file+":"+itoa(pcline(pc), "%d"); 1226ff5e913SDavid du Colombier if pc0 != 0 then 1236ff5e913SDavid du Colombier s = s + " "+fnname(pc0); 1246ff5e913SDavid du Colombier return s; 1256ff5e913SDavid du Colombier} 1266ff5e913SDavid du Colombier 1276ff5e913SDavid du Colombierdefn threadfmt(T){ 1287dd7cddfSDavid du Colombier complex Thread T; 1296ff5e913SDavid du Colombier local A, yes, i, P, s; 1307dd7cddfSDavid du Colombier 1317dd7cddfSDavid du Colombier P = (Proc)T.proc; 1326ff5e913SDavid du Colombier s = "t=(Thread)"+itoa(T, "%-10x")+" "; 1336ff5e913SDavid du Colombier 1346ff5e913SDavid du Colombier if T.state == Running then 1356ff5e913SDavid du Colombier s = s + "Running "; 1366ff5e913SDavid du Colombier else if T.state == Ready then 1376ff5e913SDavid du Colombier s = s + "Ready "; 1386ff5e913SDavid du Colombier else if T.state == Rendezvous then 1396ff5e913SDavid du Colombier s = s + "Rendez "; 1406ff5e913SDavid du Colombier else 1416ff5e913SDavid du Colombier s = s + "Bad state "+itoa(T.state, "%x")+" "; 1426ff5e913SDavid du Colombier 1439a747e4fSDavid du Colombier A = (Alt)T.alt; 1446ff5e913SDavid du Colombier if 1 then 1456ff5e913SDavid du Colombier s = s + threadstkline(T); 1466ff5e913SDavid du Colombier else if T.chan == Chanalt then 1476ff5e913SDavid du Colombier s = s + altfmt(T.alt); 1486ff5e913SDavid du Colombier else if T.chan == Chansend then 1496ff5e913SDavid du Colombier s = s + "send(Channel("+itoa(A.c, "%x")+"))"; 1506ff5e913SDavid du Colombier else if T.chan == Chanrecv then 1516ff5e913SDavid du Colombier s = s + "recv(Channel("+itoa(A.c, "%x")+"))"; 1526ff5e913SDavid du Colombier else 1536ff5e913SDavid du Colombier s = s + threadstkline(T); 1546ff5e913SDavid du Colombier 1556ff5e913SDavid du Colombier if T.moribund == 1 then 1566ff5e913SDavid du Colombier s = s + " Moribund"; 1576ff5e913SDavid du Colombier if T.cmdname != 0 then 1586ff5e913SDavid du Colombier s = s + " ["+*(T.cmdname\s)+"]"; 1596ff5e913SDavid du Colombier return s; 1609a747e4fSDavid du Colombier} 1616ff5e913SDavid du Colombier 1626ff5e913SDavid du Colombierdefn thread(T){ 1636ff5e913SDavid du Colombier print(threadfmt(T), "\n"); 1647dd7cddfSDavid du Colombier} 1657dd7cddfSDavid du Colombier 1667dd7cddfSDavid du Colombierdefn pthreads(P){ 1677dd7cddfSDavid du Colombier complex Proc P; 1686ff5e913SDavid du Colombier local T, Tq, mainpid; 1697dd7cddfSDavid du Colombier 1707dd7cddfSDavid du Colombier mainpid = pid; 1717dd7cddfSDavid du Colombier setproc(P.pid); 1727dd7cddfSDavid du Colombier Tq = (Tqueue)P.threads; 1737dd7cddfSDavid du Colombier T = (Thread)Tq.$head; 1747dd7cddfSDavid du Colombier while T != 0 do{ 1756ff5e913SDavid du Colombier print("\t"); 1767dd7cddfSDavid du Colombier thread(T); 1777dd7cddfSDavid du Colombier T = T.nextt; 1787dd7cddfSDavid du Colombier } 1797dd7cddfSDavid du Colombier setproc(mainpid); 1807dd7cddfSDavid du Colombier} 1817dd7cddfSDavid du Colombier 1827dd7cddfSDavid du Colombierdefn threads(){ 1837dd7cddfSDavid du Colombier local P; 1847dd7cddfSDavid du Colombier 1859a747e4fSDavid du Colombier P = (Proc)_threadpq.$head; 1867dd7cddfSDavid du Colombier while P != 0 do{ 1879a747e4fSDavid du Colombier if P != (Proc)_threadpq.$head then print("\n"); 1887dd7cddfSDavid du Colombier lproc(P); 1897dd7cddfSDavid du Colombier P = P.next; 1907dd7cddfSDavid du Colombier } 1917dd7cddfSDavid du Colombier} 1927dd7cddfSDavid du Colombier 1937dd7cddfSDavid du Colombierdefn stacks(){ 1946ff5e913SDavid du Colombier local P, mainpid; 1957dd7cddfSDavid du Colombier 1969a747e4fSDavid du Colombier mainpid = pid; 1979a747e4fSDavid du Colombier P = (Proc)_threadpq.$head; 1987dd7cddfSDavid du Colombier while P != 0 do{ 1997dd7cddfSDavid du Colombier proc(P); 2006ff5e913SDavid du Colombier // setproc(P.pid); 2016ff5e913SDavid du Colombier // if P.thread==0 then{ 2026ff5e913SDavid du Colombier // print("=== thread scheduler stack\n"); 2036ff5e913SDavid du Colombier // stk(); 2046ff5e913SDavid du Colombier // } 2056ff5e913SDavid du Colombier // print("threadstks(", P\X, ")\n"); 2067dd7cddfSDavid du Colombier threadstks(P); 2077dd7cddfSDavid du Colombier P = P.next; 2086ff5e913SDavid du Colombier print("\n"); 2097dd7cddfSDavid du Colombier } 2109a747e4fSDavid du Colombier setproc(mainpid); 2119a747e4fSDavid du Colombier} 2129a747e4fSDavid du Colombier 2139a747e4fSDavid du Colombierdefn stacksizes(){ 2146ff5e913SDavid du Colombier local P, T, Tq, top, sp, mainpid; 2159a747e4fSDavid du Colombier 2169a747e4fSDavid du Colombier mainpid = pid; 2179a747e4fSDavid du Colombier P = (Proc)_threadpq.$head; 2189a747e4fSDavid du Colombier while P != 0 do{ 2199a747e4fSDavid du Colombier P = (Proc)P; 2209a747e4fSDavid du Colombier Tq = (Tqueue)P.threads; 2219a747e4fSDavid du Colombier T = (Thread)Tq.$head; 2229a747e4fSDavid du Colombier while T != 0 do{ 2239a747e4fSDavid du Colombier top = T.stk+T.stksize; 2249a747e4fSDavid du Colombier if T.state==Running then { 2259a747e4fSDavid du Colombier sp = *SP; 2269a747e4fSDavid du Colombier }else{ 2279a747e4fSDavid du Colombier sp = *(T.sched); 2289a747e4fSDavid du Colombier } 2299a747e4fSDavid du Colombier sp = *(T.sched); 230*3c2ddefeSDavid du Colombier print(top-sp\D, " / ", T.stksize\D, "\n"); 2319a747e4fSDavid du Colombier T = T.nextt; 2329a747e4fSDavid du Colombier } 2339a747e4fSDavid du Colombier P = P.next; 2349a747e4fSDavid du Colombier } 2359a747e4fSDavid du Colombier setproc(mainpid); 2367dd7cddfSDavid du Colombier} 2377dd7cddfSDavid du Colombier 2387dd7cddfSDavid du Colombierdefn lproc(P){ 2397dd7cddfSDavid du Colombier proc(P); 2407dd7cddfSDavid du Colombier pthreads(P); 2417dd7cddfSDavid du Colombier} 2427dd7cddfSDavid du Colombier 2437dd7cddfSDavid du Colombierdefn threadstks(P){ 2447dd7cddfSDavid du Colombier complex Proc P; 2456ff5e913SDavid du Colombier local T, Tq, mainpid, pref, ign; 2467dd7cddfSDavid du Colombier 2477dd7cddfSDavid du Colombier mainpid = pid; 2486ff5e913SDavid du Colombier pref = stkprefix; 2496ff5e913SDavid du Colombier stkprefix = pref+"\t\t"; 2506ff5e913SDavid du Colombier ign = stkignore; 2516ff5e913SDavid du Colombier stkignore = { 2526ff5e913SDavid du Colombier "^/sys/src/libthread/", 2536ff5e913SDavid du Colombier "^/sys/src/libc/(386|arm|alpha|sparc|power|mips)/" 2546ff5e913SDavid du Colombier }; 2557dd7cddfSDavid du Colombier setproc(P.pid); 2567dd7cddfSDavid du Colombier Tq = (Tqueue)P.threads; 2577dd7cddfSDavid du Colombier T = (Thread)Tq.$head; 2587dd7cddfSDavid du Colombier while T != 0 do{ 2596ff5e913SDavid du Colombier // print("=============================\n"); 2606ff5e913SDavid du Colombier // print(" thread(", T\X, ")\n"); 2616ff5e913SDavid du Colombier print("\t"); 2627dd7cddfSDavid du Colombier thread(T); 2637dd7cddfSDavid du Colombier threadstk(T); 2647dd7cddfSDavid du Colombier T = T.nextt; 2656ff5e913SDavid du Colombier print("\n"); 2667dd7cddfSDavid du Colombier } 2677dd7cddfSDavid du Colombier setproc(mainpid); 2686ff5e913SDavid du Colombier stkprefix = pref; 2696ff5e913SDavid du Colombier stkignore = ign; 2707dd7cddfSDavid du Colombier} 2717dd7cddfSDavid du Colombier 2727dd7cddfSDavid du Colombierdefn proc(P){ 2737dd7cddfSDavid du Colombier complex Proc P; 2747dd7cddfSDavid du Colombier 2756ff5e913SDavid du Colombier print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " "); 2766ff5e913SDavid du Colombier if P.thread==0 then 2776ff5e913SDavid du Colombier print(" Sched"); 2786ff5e913SDavid du Colombier else 2796ff5e913SDavid du Colombier print(" Running"); 2807dd7cddfSDavid du Colombier print("\n"); 2817dd7cddfSDavid du Colombier} 2827dd7cddfSDavid du Colombier 2837dd7cddfSDavid du Colombierdefn procs(){ 2847dd7cddfSDavid du Colombier local P; 2857dd7cddfSDavid du Colombier 2869a747e4fSDavid du Colombier P = (Proc)_threadpq.$head; 2877dd7cddfSDavid du Colombier while P != 0 do{ 2887dd7cddfSDavid du Colombier proc(P); 2897dd7cddfSDavid du Colombier P = P.next; 2907dd7cddfSDavid du Colombier } 2917dd7cddfSDavid du Colombier} 2927dd7cddfSDavid du Colombier 2937dd7cddfSDavid du Colombierdefn threadlstk(T){ 2947dd7cddfSDavid du Colombier complex Thread T; 2957dd7cddfSDavid du Colombier local P, mainpid; 2967dd7cddfSDavid du Colombier 2977dd7cddfSDavid du Colombier P = (Proc)T.proc; 2987dd7cddfSDavid du Colombier mainpid = pid; 2997dd7cddfSDavid du Colombier setproc(P.pid); 3007dd7cddfSDavid du Colombier 3017dd7cddfSDavid du Colombier if T.state == Running then{ 3027dd7cddfSDavid du Colombier lstk(); 3037dd7cddfSDavid du Colombier } else { 3049a747e4fSDavid du Colombier lablstk(T.sched); 3057dd7cddfSDavid du Colombier } 3067dd7cddfSDavid du Colombier setproc(mainpid); 3077dd7cddfSDavid du Colombier} 3087dd7cddfSDavid du Colombier 3097dd7cddfSDavid du Colombierdefn threadstk(T){ 3107dd7cddfSDavid du Colombier complex Thread T; 3117dd7cddfSDavid du Colombier local P, mainpid; 3127dd7cddfSDavid du Colombier 3137dd7cddfSDavid du Colombier P = (Proc)T.proc; 3147dd7cddfSDavid du Colombier mainpid = pid; 3157dd7cddfSDavid du Colombier setproc(P.pid); 3167dd7cddfSDavid du Colombier 3177dd7cddfSDavid du Colombier if T.state == Running then{ 3187dd7cddfSDavid du Colombier stk(); 3197dd7cddfSDavid du Colombier } else { 3209a747e4fSDavid du Colombier labstk(T.sched); 3217dd7cddfSDavid du Colombier } 3227dd7cddfSDavid du Colombier setproc(mainpid); 3237dd7cddfSDavid du Colombier} 3247dd7cddfSDavid du Colombier 3259a747e4fSDavid du Colombierdefn tqueue(Q) { 3269a747e4fSDavid du Colombier complex Tqueue Q; 3279a747e4fSDavid du Colombier 3289a747e4fSDavid du Colombier while Q != 0 do { 3299a747e4fSDavid du Colombier print(Q.$head\X, " "); 3309a747e4fSDavid du Colombier Q = *(Q.$tail); 3319a747e4fSDavid du Colombier 3329a747e4fSDavid du Colombier } 3339a747e4fSDavid du Colombier print("#\n"); 3349a747e4fSDavid du Colombier} 3359a747e4fSDavid du Colombier 3367dd7cddfSDavid du Colombierdefn channel(C) { 3377dd7cddfSDavid du Colombier complex Channel C; 3389a747e4fSDavid du Colombier local i, p; 3397dd7cddfSDavid du Colombier 3409a747e4fSDavid du Colombier print("channel ", C\X); 3419a747e4fSDavid du Colombier if C.freed then { 3429a747e4fSDavid du Colombier print(" (moribund)"); 3439a747e4fSDavid du Colombier } 3449a747e4fSDavid du Colombier print("\n"); 3459a747e4fSDavid du Colombier print("\telementsize=", C.e\D, " buffersize=", C.s, "\n"); 3469a747e4fSDavid du Colombier if C.s then { 3479a747e4fSDavid du Colombier print("\t", C.n\D, " values in channel:\n"); 3489a747e4fSDavid du Colombier print("\t"); 3499a747e4fSDavid du Colombier p = C.v+C.e*(C.f%C.s); 3509a747e4fSDavid du Colombier loop 1,C.n do { 3519a747e4fSDavid du Colombier if C.e==4 then { 3529a747e4fSDavid du Colombier print((*p)\X, " "); 3539a747e4fSDavid du Colombier }else { 3549a747e4fSDavid du Colombier print("data(", (*p)\X, ") "); 3559a747e4fSDavid du Colombier } 3569a747e4fSDavid du Colombier p = p+C.e; 3579a747e4fSDavid du Colombier if p == C.v+C.s*C.e then { 3589a747e4fSDavid du Colombier p = C.v; 3599a747e4fSDavid du Colombier } 3609a747e4fSDavid du Colombier } 3619a747e4fSDavid du Colombier } 3629a747e4fSDavid du Colombier print("\n"); 3639a747e4fSDavid du Colombier print(C.nentry\D, " queue slots:\n"); 3649a747e4fSDavid du Colombier i=0; 3659a747e4fSDavid du Colombier loop 1,C.nentry do { 3669a747e4fSDavid du Colombier if C.qentry[i] then 3679a747e4fSDavid du Colombier print("\t", altfmt(C.qentry[i]), "\n"); 3689a747e4fSDavid du Colombier else 3699a747e4fSDavid du Colombier print("\t<empty>\n"); 3709a747e4fSDavid du Colombier i=i+1; 3719a747e4fSDavid du Colombier } 3727dd7cddfSDavid du Colombier} 3737dd7cddfSDavid du Colombier 3747dd7cddfSDavid du Colombierprint("/sys/lib/acid/thread"); 375