iobuf.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "all.h"
  10. #define DEBUG 0
  11. int32_t niob;
  12. int32_t nhiob;
  13. Hiob *hiob;
  14. Iobuf*
  15. getbuf(Device dev, int32_t addr, int flag)
  16. {
  17. Iobuf *p, *s;
  18. Hiob *hp;
  19. int32_t h;
  20. if(DEBUG)
  21. print("getbuf %D(%ld) f=%x\n", dev, addr, flag);
  22. h = addr +
  23. dev.type*1009L +
  24. dev.ctrl*10007L +
  25. dev.unit*100003L +
  26. dev.part*1000003L;
  27. if(h < 0)
  28. h = ~h;
  29. h %= nhiob;
  30. hp = &hiob[h];
  31. loop:
  32. lock(hp);
  33. /*
  34. * look for it in the active list
  35. */
  36. s = hp->link;
  37. for(p=s;;) {
  38. if(p->addr == addr && !devcmp(p->dev, dev)) {
  39. if(p != s) {
  40. p->back->fore = p->fore;
  41. p->fore->back = p->back;
  42. p->fore = s;
  43. p->back = s->back;
  44. s->back = p;
  45. p->back->fore = p;
  46. hp->link = p;
  47. }
  48. unlock(hp);
  49. qlock(p);
  50. if(p->addr != addr || devcmp(p->dev, dev)) {
  51. qunlock(p);
  52. goto loop;
  53. }
  54. p->flags |= flag;
  55. cons.bhit.count++;
  56. p->iobuf = p->xiobuf;
  57. return p;
  58. }
  59. p = p->fore;
  60. if(p == s)
  61. break;
  62. }
  63. if(flag & Bprobe) {
  64. unlock(hp);
  65. return 0;
  66. }
  67. /*
  68. * not found
  69. * take oldest unlocked entry in this queue
  70. */
  71. xloop:
  72. p = s->back;
  73. if(!canqlock(p)) {
  74. if(p == hp->link) {
  75. unlock(hp);
  76. print("iobuf all locked\n");
  77. goto loop;
  78. }
  79. s = p;
  80. goto xloop;
  81. }
  82. /*
  83. * its dangerous to flush the pseudo
  84. * devices since they recursively call
  85. * getbuf/putbuf. deadlock!
  86. */
  87. if(p->flags & Bres) {
  88. qunlock(p);
  89. if(p == hp->link) {
  90. unlock(hp);
  91. print("iobuf all resed\n");
  92. goto loop;
  93. }
  94. s = p;
  95. goto xloop;
  96. }
  97. if(p->flags & Bmod) {
  98. unlock(hp);
  99. if(!devwrite(p->dev, p->addr, p->xiobuf))
  100. p->flags &= ~(Bimm|Bmod);
  101. qunlock(p);
  102. goto loop;
  103. }
  104. hp->link = p;
  105. p->addr = addr;
  106. p->dev = dev;
  107. p->flags = flag;
  108. unlock(hp);
  109. p->iobuf = p->xiobuf;
  110. if(flag & Bread) {
  111. if(devread(p->dev, p->addr, p->iobuf)) {
  112. p->flags = 0;
  113. p->dev = devnone;
  114. p->addr = -1;
  115. p->iobuf = (char*)-1;
  116. qunlock(p);
  117. return 0;
  118. }
  119. cons.bread.count++;
  120. return p;
  121. }
  122. cons.binit.count++;
  123. return p;
  124. }
  125. /*
  126. * syncblock tries to put out a block per hashline
  127. * returns 0 all done,
  128. * returns 1 if it missed something
  129. */
  130. int
  131. syncblock(void)
  132. {
  133. Iobuf *p, *s, *q;
  134. Hiob *hp;
  135. int32_t h;
  136. int flag;
  137. flag = 0;
  138. for(h=0; h<nhiob; h++) {
  139. q = 0;
  140. hp = &hiob[h];
  141. lock(hp);
  142. s = hp->link;
  143. for(p=s;;) {
  144. if(p->flags & Bmod) {
  145. if(q)
  146. flag = 1; /* more than 1 mod/line */
  147. q = p;
  148. }
  149. p = p->fore;
  150. if(p == s)
  151. break;
  152. }
  153. unlock(hp);
  154. if(q) {
  155. if(!canqlock(q)) {
  156. flag = 1; /* missed -- was locked */
  157. continue;
  158. }
  159. if(!(q->flags & Bmod)) {
  160. qunlock(q);
  161. continue;
  162. }
  163. if(!devwrite(q->dev, q->addr, q->xiobuf))
  164. q->flags &= ~(Bmod|Bimm);
  165. qunlock(q);
  166. }
  167. }
  168. return flag;
  169. }
  170. void
  171. sync(char *reason)
  172. {
  173. int32_t i;
  174. print("sync: %s\n", reason);
  175. for(i=10*nhiob; i>0; i--)
  176. if(!syncblock())
  177. return;
  178. print("sync shorted\n");
  179. }
  180. void
  181. putbuf(Iobuf *p)
  182. {
  183. if(canqlock(p))
  184. print("buffer not locked %D(%ld)\n", p->dev, p->addr);
  185. if(p->flags & Bimm) {
  186. if(!(p->flags & Bmod))
  187. print("imm and no mod %D(%ld)\n", p->dev, p->addr);
  188. if(!devwrite(p->dev, p->addr, p->iobuf))
  189. p->flags &= ~(Bmod|Bimm);
  190. }
  191. p->iobuf = (char*)-1;
  192. qunlock(p);
  193. }
  194. int
  195. checktag(Iobuf *p, int tag, int32_t qpath)
  196. {
  197. Tag *t;
  198. t = (Tag*)(p->iobuf+BUFSIZE);
  199. if(t->tag != tag) {
  200. if(1 || CHAT(0))
  201. print(" tag = %G; expected %G; addr = %lu\n",
  202. t->tag, tag, p->addr);
  203. return 2;
  204. }
  205. if(qpath != QPNONE) {
  206. qpath &= ~QPDIR;
  207. if(qpath != t->path) {
  208. if(qpath == (t->path&~QPDIR)) /* old bug */
  209. return 0;
  210. if(1 || CHAT(0))
  211. print(" tag/path = %lx; expected %G/%lx\n",
  212. t->path, tag, qpath);
  213. return 1;
  214. }
  215. }
  216. return 0;
  217. }
  218. void
  219. settag(Iobuf *p, int tag, int32_t qpath)
  220. {
  221. Tag *t;
  222. t = (Tag*)(p->iobuf+BUFSIZE);
  223. t->tag = tag;
  224. if(qpath != QPNONE)
  225. t->path = qpath & ~QPDIR;
  226. p->flags |= Bmod;
  227. }