iobuf.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include "all.h"
  2. #include "io.h"
  3. enum { DEBUG = 0 };
  4. extern long nhiob;
  5. extern Hiob *hiob;
  6. Iobuf*
  7. getbuf(Device *d, Off addr, int flag)
  8. {
  9. Iobuf *p, *s;
  10. Hiob *hp;
  11. Off h;
  12. if(DEBUG)
  13. print("getbuf %Z(%lld) f=%x\n", d, (Wideoff)addr, flag);
  14. h = addr + (Off)d*1009;
  15. if(h < 0)
  16. h = ~h;
  17. h %= nhiob;
  18. hp = &hiob[h];
  19. loop:
  20. lock(hp);
  21. /*
  22. * look for it in the active list
  23. */
  24. s = hp->link;
  25. for(p=s;;) {
  26. if(p->addr == addr && p->dev == d) {
  27. if(p != s) {
  28. p->back->fore = p->fore;
  29. p->fore->back = p->back;
  30. p->fore = s;
  31. p->back = s->back;
  32. s->back = p;
  33. p->back->fore = p;
  34. hp->link = p;
  35. }
  36. unlock(hp);
  37. qlock(p);
  38. if(p->addr != addr || p->dev != d || iobufmap(p) == 0) {
  39. qunlock(p);
  40. goto loop;
  41. }
  42. p->flags |= flag;
  43. return p;
  44. }
  45. p = p->fore;
  46. if(p == s)
  47. break;
  48. }
  49. if(flag & Bprobe) {
  50. unlock(hp);
  51. return 0;
  52. }
  53. /*
  54. * not found
  55. * take oldest unlocked entry in this queue
  56. */
  57. xloop:
  58. p = s->back;
  59. if(!canqlock(p)) {
  60. if(p == hp->link) {
  61. unlock(hp);
  62. print("iobuf all locked\n");
  63. goto loop;
  64. }
  65. s = p;
  66. goto xloop;
  67. }
  68. /*
  69. * its dangerous to flush the pseudo
  70. * devices since they recursively call
  71. * getbuf/putbuf. deadlock!
  72. */
  73. if(p->flags & Bres) {
  74. qunlock(p);
  75. if(p == hp->link) {
  76. unlock(hp);
  77. print("iobuf all reserved\n");
  78. goto loop;
  79. }
  80. s = p;
  81. goto xloop;
  82. }
  83. if(p->flags & Bmod) {
  84. unlock(hp);
  85. if(iobufmap(p)) {
  86. if(!devwrite(p->dev, p->addr, p->iobuf))
  87. p->flags &= ~(Bimm|Bmod);
  88. iobufunmap(p);
  89. }
  90. qunlock(p);
  91. goto loop;
  92. }
  93. hp->link = p;
  94. p->addr = addr;
  95. p->dev = d;
  96. p->flags = flag;
  97. // p->pc = getcallerpc(&d);
  98. unlock(hp);
  99. if(iobufmap(p))
  100. if(flag & Brd) {
  101. if(!devread(p->dev, p->addr, p->iobuf))
  102. return p;
  103. iobufunmap(p);
  104. } else
  105. return p;
  106. else
  107. print("iobuf cant map buffer\n");
  108. p->flags = 0;
  109. p->dev = devnone;
  110. p->addr = -1;
  111. qunlock(p);
  112. return 0;
  113. }
  114. /*
  115. * syncblock tries to put out a block per hashline
  116. * returns 0 all done,
  117. * returns 1 if it missed something
  118. */
  119. int
  120. syncblock(void)
  121. {
  122. Iobuf *p, *s, *q;
  123. Hiob *hp;
  124. long h;
  125. int flag;
  126. flag = 0;
  127. for(h=0; h<nhiob; h++) {
  128. q = 0;
  129. hp = &hiob[h];
  130. lock(hp);
  131. s = hp->link;
  132. for(p=s;;) {
  133. if(p->flags & Bmod) {
  134. if(q)
  135. flag = 1; /* more than 1 mod/line */
  136. q = p;
  137. }
  138. p = p->fore;
  139. if(p == s)
  140. break;
  141. }
  142. unlock(hp);
  143. if(q) {
  144. if(!canqlock(q)) {
  145. flag = 1; /* missed -- was locked */
  146. continue;
  147. }
  148. if(!(q->flags & Bmod)) {
  149. qunlock(q);
  150. continue;
  151. }
  152. if(iobufmap(q)) {
  153. if(!devwrite(q->dev, q->addr, q->iobuf))
  154. q->flags &= ~(Bmod|Bimm);
  155. iobufunmap(q);
  156. } else
  157. flag = 1;
  158. qunlock(q);
  159. }
  160. }
  161. return flag;
  162. }
  163. void
  164. sync(char *reason)
  165. {
  166. long i;
  167. print("sync: %s\n", reason);
  168. for(i=10*nhiob; i>0; i--)
  169. if(!syncblock())
  170. return;
  171. print("sync shorted\n");
  172. }
  173. void
  174. putbuf(Iobuf *p)
  175. {
  176. if(canqlock(p))
  177. print("buffer not locked %Z(%lld)\n", p->dev, (Wideoff)p->addr);
  178. if(p->flags & Bimm) {
  179. if(!(p->flags & Bmod))
  180. print("imm and no mod %Z(%lld)\n",
  181. p->dev, (Wideoff)p->addr);
  182. if(!devwrite(p->dev, p->addr, p->iobuf))
  183. p->flags &= ~(Bmod|Bimm);
  184. }
  185. iobufunmap(p);
  186. qunlock(p);
  187. }
  188. int
  189. checktag(Iobuf *p, int tag, Off qpath)
  190. {
  191. Tag *t;
  192. static Off lastaddr;
  193. t = (Tag*)(p->iobuf+BUFSIZE);
  194. if(t->tag != tag) {
  195. if(p->flags & Bmod) {
  196. print("\ttag = %d/%llud; expected %lld/%d -- not flushed\n",
  197. t->tag, (Wideoff)t->path, (Wideoff)qpath, tag);
  198. return 2;
  199. }
  200. if(p->dev != nil && p->dev->type == Devcw)
  201. cwfree(p->dev, p->addr);
  202. if(p->addr != lastaddr)
  203. print("\ttag = %G/%llud; expected %G/%lld -- flushed (%lld)\n",
  204. t->tag, (Wideoff)t->path, tag, (Wideoff)qpath,
  205. (Wideoff)p->addr);
  206. lastaddr = p->addr;
  207. p->dev = devnone;
  208. p->addr = -1;
  209. p->flags = 0;
  210. return 2;
  211. }
  212. if(qpath != QPNONE) {
  213. if((qpath ^ t->path) & ~QPDIR) {
  214. if(1 || CHAT(0))
  215. print("\ttag/path = %llud; expected %d/%llux\n",
  216. (Wideoff)t->path, tag, (Wideoff)qpath);
  217. return 0;
  218. }
  219. }
  220. return 0;
  221. }
  222. void
  223. settag(Iobuf *p, int tag, long qpath)
  224. {
  225. Tag *t;
  226. t = (Tag*)(p->iobuf+BUFSIZE);
  227. t->tag = tag;
  228. if(qpath != QPNONE)
  229. t->path = qpath & ~QPDIR;
  230. p->flags |= Bmod;
  231. }
  232. int
  233. qlmatch(QLock *q1, QLock *q2)
  234. {
  235. return q1 == q2;
  236. }
  237. int
  238. iobufql(QLock *q)
  239. {
  240. Iobuf *p, *s;
  241. Hiob *hp;
  242. Tag *t;
  243. long h;
  244. int tag;
  245. for(h=0; h<nhiob; h++) {
  246. hp = &hiob[h];
  247. lock(hp);
  248. s = hp->link;
  249. for(p=s;;) {
  250. if(qlmatch(q, p)) {
  251. t = (Tag*)(p->iobuf+BUFSIZE);
  252. tag = t->tag;
  253. if(tag < 0 || tag >= MAXTAG)
  254. tag = Tnone;
  255. print("\tIobuf %Z(%lld) t=%s\n",
  256. p->dev, (Wideoff)p->addr, tagnames[tag]);
  257. unlock(hp);
  258. return 1;
  259. }
  260. p = p->fore;
  261. if(p == s)
  262. break;
  263. }
  264. unlock(hp);
  265. }
  266. return 0;
  267. }