xref: /plan9/sys/lib/acid/thread (revision 3c2ddefeebfd7a80eaebf272955335c2cf163bd5)
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