iobuf.c 5.0 KB

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