374 lines · 6.0 KB · Text
RawDownload
include("/sys/src/libthread/sched.acid" + objchar); 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;	}	if a == {} then		return "{}";	return itoa(a\X, "%x");} stkignorelist = {}; defn stkignore(s){	append stkignorelist, s;} defn threadstkline(T){	local ostk, 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);	}	firstpc = pc;	lastpc0 = 0;	pc0 = 0;	stop = 0;	ostk = stk;	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 if stk[0][1] == 0xfefefefe then {			pc = ostk[0][1];			pc0 = ostk[1][0];			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, " / ", T.stksize\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<empty>\n");		i=i+1;	}} print("/sys/lib/acid/thread");