]> git.lizzy.rs Git - plan9front.git/blob - sys/lib/acid/thread
ip/tftpd: add a syslog message about what error we return to the client on a NAK
[plan9front.git] / sys / lib / acid / thread
1 include("/sys/src/libthread/sched." + objtype + ".acid");
2
3 defn labpc(l)
4 {
5         if objtype == "386" || objtype == "amd64" then
6                 return longjmp;
7         return *(l+4);
8 }
9
10 defn labsp(l)
11 {
12         return *l;
13 }
14
15 defn labstk(l)
16 {
17         _stk(labpc(l), labsp(l), 0, 1);
18 }
19
20 defn lablstk(l)
21 {
22         _stk(labpc(l), labsp(l), 0, 1);
23 }
24
25 defn altfmt(A){
26         local i, s, yes;
27         complex Alt A;
28
29         s = "alt(";
30         s = s + "tag(*" + itoa(A.tag, "%x") + "=" + itoa(*A.tag, "%x") + ") ";
31         i = 0;
32         yes = 0;
33         while A.op != CHANEND && A.op != CHANNOBLK do{
34                 if A.op != CHANNOP then{
35                         if yes then s = s + " ";
36                         s = s + itoa(i, "%d");
37                         s = s + ":";
38                         if A.op == CHANSND then s = s + "send";
39                         if A.op == CHANRCV then s = s + "recv";
40                         s = s + "(channel(";
41                         s = s + itoa(A.c, "%x");
42                         s = s + "))";
43                         yes = 1;
44                 }
45                 i = i + 1;
46                 A = (Alt)(A + sizeofAlt);
47         }
48         if A.op==CHANNOBLK then{
49                 if yes then s = s + " ";
50                 s = s + "noblock";
51         }
52         s = s + ")";
53         return s;
54 }
55
56 defn alt(A){
57         print(altfmt(A), "\n");
58 }
59
60 threadignsrc = {
61         "^/sys/src/libc",
62         "^/sys/src/libthread",
63 };
64
65 defn fnname(a){
66         local sym, s;
67
68         s = symbols;
69         while s do {
70                 sym = head s;
71                 if sym[2] == a then
72                         return sym[0];
73                 s = tail s;
74         }
75         if a == {} then
76                 return "{}";
77         return itoa(a\X, "%x");
78 }
79
80 stkignorelist = {};
81
82 defn stkignore(s){
83         append stkignorelist, s;
84 }
85
86 defn threadstkline(T){
87         local ostk, stk, frame, pc, pc0, file, lastpc0, s, sym, i, stop;
88
89         if T.state == Running then{
90                 pc = *PC;
91                 stk = strace(*PC, *SP, linkreg(0));
92         }else{
93                 pc = labpc(T.sched);
94                 stk = strace(labpc(T.sched), labsp(T.sched), 0);
95         }
96         firstpc = pc;
97         lastpc0 = 0;
98         pc0 = 0;
99         stop = 0;
100         ostk = stk;
101         while stk && !stop do {
102                 file = pcfile(pc);
103                 if !regexp("^/sys/src/libc/", file)
104                 && !regexp("^/sys/src/libthread/", file) 
105                 && match(file, stkignore)==-1 then
106                         stop = 1;
107                 else if stk[0][1] == 0xfefefefe then {
108                         pc = ostk[0][1];
109                         pc0 = ostk[1][0];
110                         stop = 1;
111                 }else{
112                         lastpc0 = pc0;
113                         frame = head stk;
114                         stk = tail stk;
115                         nextframe = head stk;
116                         pc = frame[1];
117                         pc0 = nextframe[0];
118                 }
119         }
120         file = pcfile(pc);
121         s = file+":"+itoa(pcline(pc), "%d");
122         if pc0 != 0 then 
123                 s = s + " "+fnname(pc0);
124         return s;
125 }
126
127 defn threadfmt(T){
128         complex Thread T;
129         local A, yes, i, P, s;
130
131         P = (Proc)T.proc;
132         s = "t=(Thread)"+itoa(T, "%-10x")+" ";
133
134         if T.state == Running then
135                 s = s + "Running    ";
136         else if T.state == Ready then
137                 s = s + "Ready      ";
138         else if T.state == Rendezvous then
139                 s = s + "Rendez     ";
140         else
141                 s = s + "Bad state "+itoa(T.state, "%x")+" ";
142
143         A = (Alt)T.alt;
144         if 1 then
145                 s = s + threadstkline(T);
146         else if T.chan == Chanalt then
147                 s = s + altfmt(T.alt);
148         else if T.chan == Chansend then
149                 s = s + "send(Channel("+itoa(A.c, "%x")+"))";
150         else if T.chan == Chanrecv then
151                 s = s + "recv(Channel("+itoa(A.c, "%x")+"))";
152         else
153                 s = s + threadstkline(T);
154
155         if T.moribund == 1 then
156                 s = s + " Moribund";
157         if T.cmdname != 0 then
158                 s = s + " ["+*(T.cmdname\s)+"]";
159         return s;
160 }
161
162 defn thread(T){
163         print(threadfmt(T), "\n");
164 }
165
166 defn pthreads(P){
167         complex Proc P;
168         local T, Tq, mainpid;
169
170         mainpid = pid;
171         setproc(P.pid);
172         Tq = (Tqueue)P.threads;
173         T = (Thread)Tq.$head;
174         while T != 0 do{
175                 print("\t");
176                 thread(T);
177                 T = T.nextt;
178         }
179         setproc(mainpid);
180 }
181
182 defn threads(){
183         local P;
184
185         P = (Proc)_threadpq.$head;
186         while P != 0 do{
187                 if P != (Proc)_threadpq.$head then print("\n");
188                 lproc(P);
189                 P = P.next;
190         }
191 }
192
193 defn stacks(){
194         local P, mainpid;
195
196         mainpid = pid;
197         P = (Proc)_threadpq.$head;
198         while P != 0 do{
199                 proc(P);
200         //      setproc(P.pid);
201         //      if P.thread==0 then{
202         //              print("=== thread scheduler stack\n");
203         //              stk();
204         //      }
205         //      print("threadstks(", P\X, ")\n");
206                 threadstks(P);
207                 P = P.next;
208                 print("\n");
209         }
210         setproc(mainpid);
211 }
212
213 defn stacksizes(){
214         local P, T, Tq, top, sp, mainpid;
215
216         mainpid = pid;
217         P = (Proc)_threadpq.$head;
218         while P != 0 do{
219                 P = (Proc)P;
220                 Tq = (Tqueue)P.threads;
221                 T = (Thread)Tq.$head;
222                 while T != 0 do{
223                         top = T.stk+T.stksize;
224                         if T.state==Running then {
225                                 sp = *SP;
226                         }else{
227                                 sp = *(T.sched);
228                         }
229                         sp = *(T.sched);
230                         print(top-sp\D, " / ", T.stksize\D, "\n");
231                         T = T.nextt;
232                 }
233                 P = P.next;
234         }
235         setproc(mainpid);
236 }
237
238 defn lproc(P){
239         proc(P);
240         pthreads(P);
241 }
242
243 defn threadstks(P){
244         complex Proc P;
245         local T, Tq, mainpid, pref, ign;
246
247         mainpid = pid;
248         pref = stkprefix;
249         stkprefix = pref+"\t\t";
250         ign = stkignore;
251         stkignore = {
252                 "^/sys/src/libthread/",
253                 "^/sys/src/libc/(386|arm|sparc|power|mips)/"
254         };
255         setproc(P.pid);
256         Tq = (Tqueue)P.threads;
257         T = (Thread)Tq.$head;
258         while T != 0 do{
259         //      print("=============================\n");
260         //      print("  thread(", T\X, ")\n");
261                 print("\t");
262                 thread(T);
263                 threadstk(T);
264                 T = T.nextt;
265                 print("\n");
266         }
267         setproc(mainpid);
268         stkprefix = pref;
269         stkignore = ign;
270 }
271
272 defn proc(P){
273         complex Proc P;
274
275         print("p=(Proc)", itoa(P, "%-10x"), " pid ", P.pid\D, " ");
276         if P.thread==0 then
277                 print(" Sched");
278         else
279                 print(" Running");
280         print("\n");
281 }
282
283 defn procs(){
284         local P;
285
286         P = (Proc)_threadpq.$head;
287         while P != 0 do{
288                 proc(P);
289                 P = P.next;
290         }
291 }
292
293 defn threadlstk(T){
294         complex Thread T;
295         local P, mainpid;
296
297         P = (Proc)T.proc;
298         mainpid = pid;
299         setproc(P.pid);
300
301         if T.state == Running then{
302                 lstk();
303         } else {
304                 lablstk(T.sched);
305         }
306         setproc(mainpid);
307 }
308
309 defn threadstk(T){
310         complex Thread T;
311         local P, mainpid;
312
313         P = (Proc)T.proc;
314         mainpid = pid;
315         setproc(P.pid);
316
317         if T.state == Running then{
318                 lstk();
319         } else {
320                 labstk(T.sched);
321         }
322         setproc(mainpid);
323 }
324
325 defn tqueue(Q) {
326         complex Tqueue Q;
327
328         while Q != 0 do {
329                 print(Q.$head\X, " ");
330                 Q = *(Q.$tail);
331         
332         }
333         print("#\n");
334 }
335
336 defn channel(C) {
337         complex Channel C;
338         local i, p;
339
340         print("channel ", C\X);
341         if C.freed then {
342                 print(" (moribund)");
343         }
344         print("\n");
345         print("\telementsize=", C.e\D, " buffersize=", C.s, "\n");
346         if C.s then {
347                 print("\t", C.n\D, " values in channel:\n");
348                 print("\t");
349                 p = C.v+C.e*(C.f%C.s);
350                 loop 1,C.n do {
351                         if C.e==4 then {
352                                 print((*p)\X, " ");
353                         }else {
354                                 print("data(", (*p)\X, ") ");
355                         }
356                         p = p+C.e;
357                         if p == C.v+C.s*C.e then {
358                                 p = C.v;
359                         }
360                 }
361         }
362         print("\n");
363         print(C.nentry\D, " queue slots:\n");
364         i=0;
365         loop 1,C.nentry do {
366                 if C.qentry[i] then
367                         print("\t", altfmt(C.qentry[i]), "\n");
368                 else
369                         print("\t<empty>\n");
370                 i=i+1;
371         }
372 }
373
374 print("/sys/lib/acid/thread");