thread 6.0 KB

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