plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

thread (5091B)


      1 //
      2 // pthread-specific access functions
      3 // avoid complicated libthread_db interface
      4 //
      5 
      6 include("pthread-"+systype+"-"+objtype);
      7 
      8 // pick apart system mcontext_t structures
      9 defn mcontext(m)
     10 {
     11 	complex mcontext_t m;
     12 
     13 	if systype == "linux" then {
     14 		m = m\X;
     15 		return {"PC", m[14], "SP", m[7], "BP", m[6]};
     16 	} else if systype == "freebsd" then {
     17 		return {"PC", m.mc_eip, "SP", m.mc_esp, "BP", m.mc_ebp};
     18 	} else
     19 		error("do not know how to read mcontext_t on system "+systype);
     20 }
     21 
     22 //
     23 // plan 9 thread library support
     24 // 
     25 defn context(c)
     26 {
     27 	c = (Context)c;
     28 	return mcontext(c.uc.uc_mcontext);
     29 }
     30 
     31 defn contextstk(c)
     32 {
     33 	_stk(context(c), 0);
     34 }
     35 
     36 defn contextlstk(c)
     37 {
     38 	_stk(context(c), 1);
     39 }
     40 
     41 defn altfmt(A){
     42 	local i, s, yes;
     43 	complex Alt A;
     44 
     45 	s = "alt(";
     46 	s = s + "tag(*" + itoa(A.tag, "%#x") + "=" + itoa(*A.tag, "%#x") + ") ";
     47 	i = 0;
     48 	yes = 0;
     49 	while A.op != CHANEND && A.op != CHANNOBLK do{
     50 		if A.op != CHANNOP then{
     51 			if yes then s = s + " ";
     52 			s = s + itoa(i, "%d");
     53 			s = s + ":";
     54 			if A.op == CHANSND then s = s + "send";
     55 			if A.op == CHANRCV then s = s + "recv";
     56 			s = s + "(channel(";
     57 			s = s + itoa(A.c, "%#x");
     58 			s = s + "))";
     59 			yes = 1;
     60 		}
     61 		i = i + 1;
     62 		A = (Alt)(A + sizeofAlt);
     63 	}
     64 	if A.op==CHANNOBLK then{
     65 		if yes then s = s + " ";
     66 		s = s + "noblock";
     67 	}
     68 	s = s + ")";
     69 	return s;
     70 }
     71 
     72 defn alt(A){
     73 	print(altfmt(A), "\n");
     74 }
     75 
     76 defn channel(C) {
     77 	complex Channel C;
     78 	local i, p;
     79 
     80 	print("channel ", C\X, " // ", *(C.name\s));
     81 	if C.freed then {
     82 		print(" (moribund)");
     83 	}
     84 	print("\n");
     85 	print("\telemsize=", C.elemsize\D, " bufsize=", C.bufsize, "\n");
     86 	if C.bufsize then {
     87 		print("\t", C.nbuf\D, " values in channel:\n");
     88 		print("\t");
     89 		p = C.buf+C.off*C.elemsize;
     90 		loop 1,C.nbuf do {
     91 			if C.elemsize==4 then {
     92 				print(*p\X, " ");
     93 			}else {
     94 				print("data(", p\X, ") ");
     95 			}
     96 			p = p+C.elemsize;
     97 			if p == C.buf+C.bufsize*C.elemsize then {
     98 				p = C.buf;
     99 			}
    100 		}
    101 	}
    102 	print("\n");
    103 	print(" senders:\n");
    104 	_altarray(C.asend);
    105 	print(" recvers:\n");
    106 	_altarray(C.arecv);
    107 }
    108 
    109 defn _altarray(aa)
    110 {
    111 	local i, a, t;
    112 
    113 	i = 0;
    114 	aa = (_Altarray)aa;
    115 	while i < aa.n do {
    116 		a = (Alt)aa.a[i];
    117 		print("\t"+threadstkline(a.thread)+"\n");
    118 		i++;
    119 	}
    120 }
    121 
    122 defn fnname(a){
    123 	local sym, s;
    124 
    125 	s = symbols;
    126 	while s do {
    127 		sym = head s;
    128 		if sym[2] == a then
    129 			return sym[0];
    130 		s = tail s;
    131 	}
    132 	return itoa(a, "%#x");
    133 }
    134 
    135 stkignorelist = {};
    136 defn stkignore(s){
    137 	append stkignorelist, s;
    138 }
    139 
    140 defn threadstkline(T){
    141 	local stk, frame, pc, pc0, file, s, sym, i, stop, P, mainpid;
    142 
    143 	T = (_Thread)T;
    144 	P = (Proc)T.proc;
    145 	if P.thread == T then {
    146 		mainpid = pid;
    147 		setproc(pthread2tid(P.osprocid));
    148 		stk = strace({});
    149 		setproc(mainpid);
    150 	} else
    151 		stk = strace(context(T.context));
    152 
    153 	stop = 0;
    154 	while stk && !stop do {
    155 		frame = head stk;
    156 		stk = tail stk;
    157 		pc = frame[2];
    158 		pc0 = frame[0];
    159 		file = pcfile(pc);
    160 		if !regexp("plan9/src/lib9/", file)
    161 		&& !regexp("plan9/src/libthread/", file) 
    162 		&& file != "?file?"
    163 		&& match(file, stkignore)==-1 then
    164 			stop = 1;
    165 	}
    166 	file = pcfile(pc);
    167 	s = file+":"+itoa(pcline(pc), "%d");
    168 	if pc0 != 0 then 
    169 		s = s + " "+fnname(pc0);
    170 	return s;
    171 }
    172 
    173 defn threadfmt(T){
    174 	complex _Thread T;
    175 	local P, s, name;
    176 
    177 	P = (Proc)T.proc;
    178 	s = "t=(_Thread)"+itoa(T, "%#-10x")+" // ";
    179 
    180 	if P.thread == T then
    181 		s = s + "Running    ";
    182 	else
    183 		s = s + "Sleeping   ";
    184 	s = s + threadstkline(T);
    185 
    186 	name = T+392;	// T+offsetof(_Thread, name);
    187 	if *(name\b) != 0 then
    188 		s = s + " ["+*(name\s)+"]";
    189 	return s;
    190 }
    191 
    192 defn thread(T){
    193 	print(threadfmt(T), "\n");
    194 }
    195 
    196 defn procthreads(P){
    197 	complex Proc P;
    198 	local T;
    199 
    200 	T = (_Thread)P.allthreads.$head;
    201 	while T != 0 do{
    202 		print("\t");
    203 		thread(T);
    204 		T = (_Thread)T.allnext;
    205 	}
    206 }
    207 
    208 defn prociter(x) {
    209 	local P;
    210 
    211 	P = (Proc)*_threadprocs;
    212 	while P != 0 do{
    213 		if P != (Proc)*_threadprocs then print("\n");
    214 		proc(P);
    215 		if x == 1 then 
    216 			procthreads(P);
    217 		if x == 2 then
    218 			threadstks(P);
    219 		P = (Proc)P.next;
    220 	}
    221 }
    222 
    223 defn procs() {
    224 	prociter(0);
    225 }
    226 
    227 defn threads() {
    228 	prociter(1);
    229 }
    230 
    231 defn stacks() {
    232 	prociter(2);
    233 }
    234 
    235 threadstkignore = {
    236 	"plan9/src/libthread/",
    237 	"plan9/src/lib9/",
    238 	"plan9/src/lib9/(fmt|utf)/",
    239 };
    240 defn threadstks(P){
    241 	complex Proc P;
    242 	local T,  mainpid, pref, ign;
    243 
    244 	pref = stkprefix;
    245 	stkprefix = pref+"\t\t";
    246 	ign = stkignore;
    247 	stkignore = threadstkignore;
    248 	T = (_Thread)P.allthreads.$head;
    249 	while T != 0 do{
    250 		print("\t");
    251 		thread(T);
    252 		threadstk(T);
    253 		T = (_Thread)T.allnext;
    254 		print("\n");
    255 	}
    256 	stkprefix = pref;
    257 	stkignore = ign;
    258 }
    259 
    260 defn proc(P){
    261 	complex Proc P;
    262 
    263 	print("p=(Proc)", itoa(P, "%#-10x"), "  // pthread ", P.osprocid\X, " pid ", pthread2tid(P.osprocid)\D, " ");
    264 	if P.thread==0 then
    265 		print(" Sched");
    266 	else
    267 		print(" Running");
    268 	print("\n");
    269 }
    270 
    271 defn threadlstk(T){
    272 	complex _Thread T;
    273 	local P, mainpid;
    274 
    275 	P = (Proc)T.proc;
    276 	mainpid = pid;
    277 	setproc(pthread2tid(P.osprocid));
    278 
    279 	if P.thread == T then
    280 		lstk();
    281 	else
    282 		contextlstk(T.context);
    283 	setproc(mainpid);
    284 }
    285 
    286 defn threadstk(T){
    287 	complex _Thread T;
    288 	local P, mainpid;
    289 
    290 	P = (Proc)T.proc;
    291 	mainpid = pid;
    292 	setproc(pthread2tid(P.osprocid));
    293 
    294 	if P.thread == T then
    295 		stk();
    296 	else 
    297 		contextstk(T.context);
    298 
    299 	setproc(mainpid);
    300 }
    301 
    302 print(acidfile);