thread 5.8 KB

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