fossil-acid 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // pick up the common data structures
  2. rc("cd /sys/src/cmd/fossil; mk 9fsys.acid");
  3. include("/sys/src/cmd/fossil/9fsys.acid");
  4. rc("cd /sys/src/cmd/fossil; mk cache.acid");
  5. include("/sys/src/cmd/fossil/cache.acid");
  6. rc("cd /sys/src/cmd/fossil; mk disk.acid");
  7. include("/sys/src/cmd/fossil/disk.acid");
  8. rc("cd /sys/src/cmd/fossil; mk fs.acid");
  9. include("/sys/src/cmd/fossil/fs.acid");
  10. rc("cd /sys/src/liboventi; mk plan9-thread.acid");
  11. include("/sys/src/liboventi/plan9-thread.acid");
  12. // make a list of pids from a list of Thread structures
  13. defn _threadlist(t)
  14. {
  15. local l;
  16. l = {};
  17. while t do {
  18. t = (Thread)t;
  19. l = append l, t.pid;
  20. t = t.next;
  21. }
  22. return l;
  23. }
  24. // print info about a VtRendez
  25. defn vtrendez(r)
  26. {
  27. local l, t, w, q;
  28. r = (VtRendez)r;
  29. w = _threadlist(r.wfirst);
  30. if match(pid, w) >= 0 then
  31. print("\twaiting for wakeup\n");
  32. l = (VtLock)r.lk;
  33. q = _threadlist(l.qfirst);
  34. if match(pid, q) >= 0 then
  35. print("\tawakened; waiting for lock\n");
  36. print("\tr=(VtRendez)", r\X, "\n");
  37. print("\tl=(VtLock)", l\X, "\n");
  38. if l.writer != 0 then {
  39. t = (Thread)l.writer;
  40. print("\tvtLock is held by ", t.pid\D, "\n");
  41. }
  42. }
  43. // print info about a VtLock
  44. defn vtlock(l)
  45. {
  46. local t;
  47. l = (VtLock)l;
  48. print("\tl=(VtLock)", l\X, "\n");
  49. if l.writer then {
  50. t = (Thread)l.writer;
  51. print("\tvtLock is held by ", t.pid\D, "\n");
  52. } else if l.readers then
  53. print("\tvtLock is held by ", l.readers\D, " readers\n");
  54. else
  55. print("\tvtLock is not held!\n");
  56. }
  57. // try to say something intelligent about why a process is stuck.
  58. _pauses = {
  59. open,
  60. pread,
  61. pwrite,
  62. sleep,
  63. vtSleep,
  64. vtLock,
  65. vtRLock,
  66. };
  67. defn deadlocklist(l)
  68. {
  69. while l do {
  70. setproc(head l);
  71. deadlock();
  72. l = tail l;
  73. }
  74. }
  75. defn deadlock()
  76. {
  77. local stk, frame, name, stallframe, fossilframe, stallname;
  78. stk = strace(*PC, *SP, linkreg(0));
  79. print("setproc(", pid, ") // ", readfile("/proc/"+itoa(pid)+"/args"), "\n");
  80. stallframe = 0;
  81. stallname = "";
  82. fossilframe = 0;
  83. frame = {0};
  84. while stk do {
  85. lastframe = frame;
  86. frame = head stk;
  87. name = fmt(frame[0], 'a');
  88. if !stallframe && match(name, _pauses) >= 0 then {
  89. stallframe = frame;
  90. stallname = name;
  91. print("\t", fmt(frame[0], 'a'), "(");
  92. params(frame[2]);
  93. print(") ", pcfile(frame[0]), ":", pcline(frame[0]));
  94. print("\n\t\tcalled from ", fmt(frame[1], 'a'), " ");
  95. pfl(frame[1]);
  96. }
  97. if !fossilframe && regexp("^/sys/src/cmd/fossil/.*", pcfile(frame[0])) then {
  98. if !stallframe then {
  99. stallframe = lastframe;
  100. stallname = fmt(lastframe[0], 'a');
  101. print("\tunexpected stall: ", stallname, "\n");
  102. if match(stallname, _pauses) >= 0 then
  103. print("\t\t but it matches!\n");
  104. }
  105. fossilframe = frame;
  106. print("\t", fmt(frame[0], 'a'), "(");
  107. params(frame[2]);
  108. print(") ", pcfile(frame[0]), ":", pcline(frame[0]));
  109. print("\n\t\tcalled from ", fmt(frame[1], 'a'), " ");
  110. pfl(frame[1]);
  111. if name == cacheLocalLookup && stallname == vtLock then
  112. print("\twaiting to lock block b=(Block)", *cacheLocalLookup:b\X, "\n");
  113. if name == cacheLocal && stallname == vtSleep then
  114. print("\tsleeping on block b=(Block)", *cacheLocal:b\X, "\n");
  115. if name == blockWrite && stallname == vtSleep then
  116. print("\tsleeping on block b=(Block)", *blockFlush:b\X, "\n");
  117. }
  118. stk = tail stk;
  119. }
  120. if stallname == vtSleep then
  121. vtrendez(*vtSleep:q);
  122. if stallname == vtLock then
  123. vtlock(*vtLock:p);
  124. if !stallframe || !fossilframe then {
  125. print("\tconfused:");
  126. if !stallframe then print(" stallframe?");
  127. if !fossilframe then print(" fossilframe?");
  128. print("\n");
  129. }
  130. print("\n");
  131. }
  132. // fetch fsys
  133. defn
  134. fsysGet(name)
  135. {
  136. return fsysmain;
  137. }
  138. // dump information about the cache
  139. defn
  140. cacheDump(c)
  141. {
  142. local i, b, x;
  143. c = (Cache)c;
  144. x = c.blocks;
  145. i=0;
  146. loop 1,c.nblocks do {
  147. b = (Block)(x+i);
  148. print(b\X, " ", b.pc\X, " ", b.ref\D, "\n");
  149. i = i+sizeofBlock;
  150. }
  151. }
  152. // print block info
  153. defn
  154. printblist(bl)
  155. {
  156. bl = (BList)bl;
  157. while bl != 0 do {
  158. print("[", bl.part\D, " ", bl.addr\X, " ", bl.vers\D, "]");
  159. bl = bl.next;
  160. if bl != 0 then
  161. print(", ");
  162. }
  163. }
  164. defn
  165. block(b)
  166. {
  167. local i;
  168. b = (Block)b;
  169. print("b=(Block)", b\X, "\n");
  170. print("\tref ", b.ref\D, " nlock ", b.nlock\D, "\n");
  171. print("\tpav=[", b.part\D, " ", b.addr\X, " ", b.vers\D, "]\n");
  172. print("\tprior=");
  173. printblist(b.prior);
  174. print("\n");
  175. print("\tunlink=");
  176. printblist(b.uhead);
  177. print("\n");
  178. }