thread 5.7 KB

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