302 lines · 5.0 KB · Text
RawDownload
//// pthread-specific access functions// avoid complicated libthread_db interface// include("pthread-"+systype+"-"+objtype); // pick apart system mcontext_t structuresdefn mcontext(m){	complex mcontext_t m; 	if systype == "linux" then {		m = m\X;		return {"PC", m[14], "SP", m[7], "BP", m[6]};	} else if systype == "freebsd" then {		return {"PC", m.mc_eip, "SP", m.mc_esp, "BP", m.mc_ebp};	} else		error("do not know how to read mcontext_t on system "+systype);} //// plan 9 thread library support// defn context(c){	c = (Context)c;	return mcontext(c.uc.uc_mcontext);} defn contextstk(c){	_stk(context(c), 0);} defn contextlstk(c){	_stk(context(c), 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");} defn channel(C) {	complex Channel C;	local i, p; 	print("channel ", C\X, " // ", *(C.name\s));	if C.freed then {		print(" (moribund)");	}	print("\n");	print("\telemsize=", C.elemsize\D, " bufsize=", C.bufsize, "\n");	if C.bufsize then {		print("\t", C.nbuf\D, " values in channel:\n");		print("\t");		p = C.buf+C.off*C.elemsize;		loop 1,C.nbuf do {			if C.elemsize==4 then {				print(*p\X, " ");			}else {				print("data(", p\X, ") ");			}			p = p+C.elemsize;			if p == C.buf+C.bufsize*C.elemsize then {				p = C.buf;			}		}	}	print("\n");	print(" senders:\n");	_altarray(C.asend);	print(" recvers:\n");	_altarray(C.arecv);} defn _altarray(aa){	local i, a, t; 	i = 0;	aa = (_Altarray)aa;	while i < aa.n do {		a = (Alt)aa.a[i];		print("\t"+threadstkline(a.thread)+"\n");		i++;	}} 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, P, mainpid; 	T = (_Thread)T;	P = (Proc)T.proc;	if P.thread == T then {		mainpid = pid;		setproc(pthread2tid(P.osprocid));		stk = strace({});		setproc(mainpid);	} else		stk = strace(context(T.context)); 	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/lib9/", file)		&& !regexp("plan9/src/libthread/", file) 		&& file != "?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 P, s, name; 	P = (Proc)T.proc;	s = "t=(_Thread)"+itoa(T, "%#-10x")+" // "; 	if P.thread == T then		s = s + "Running    ";	else		s = s + "Sleeping   ";	s = s + threadstkline(T); 	name = T+392;	// T+offsetof(_Thread, name);	if *(name\b) != 0 then		s = s + " ["+*(name\s)+"]";	return s;} defn thread(T){	print(threadfmt(T), "\n");} defn procthreads(P){	complex Proc P;	local T; 	T = (_Thread)P.allthreads.$head;	while T != 0 do{		print("\t");		thread(T);		T = (_Thread)T.allnext;	}} defn prociter(x) {	local P; 	P = (Proc)*_threadprocs;	while P != 0 do{		if P != (Proc)*_threadprocs then print("\n");		proc(P);		if x == 1 then 			procthreads(P);		if x == 2 then			threadstks(P);		P = (Proc)P.next;	}} defn procs() {	prociter(0);} defn threads() {	prociter(1);} defn stacks() {	prociter(2);} threadstkignore = {	"plan9/src/libthread/",	"plan9/src/lib9/",	"plan9/src/lib9/(fmt|utf)/",};defn threadstks(P){	complex Proc P;	local T,  mainpid, pref, ign; 	pref = stkprefix;	stkprefix = pref+"\t\t";	ign = stkignore;	stkignore = threadstkignore;	T = (_Thread)P.allthreads.$head;	while T != 0 do{		print("\t");		thread(T);		threadstk(T);		T = (_Thread)T.allnext;		print("\n");	}	stkprefix = pref;	stkignore = ign;} defn proc(P){	complex Proc P; 	print("p=(Proc)", itoa(P, "%#-10x"), "  // pthread ", P.osprocid\X, " pid ", pthread2tid(P.osprocid)\D, " ");	if P.thread==0 then		print(" Sched");	else		print(" Running");	print("\n");} defn threadlstk(T){	complex _Thread T;	local P, mainpid; 	P = (Proc)T.proc;	mainpid = pid;	setproc(pthread2tid(P.osprocid)); 	if P.thread == T then		lstk();	else		contextlstk(T.context);	setproc(mainpid);} defn threadstk(T){	complex _Thread T;	local P, mainpid; 	P = (Proc)T.proc;	mainpid = pid;	setproc(pthread2tid(P.osprocid)); 	if P.thread == T then		stk();	else 		contextstk(T.context); 	setproc(mainpid);} print(acidfile);