buf.prom 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #define NBUFS 2
  2. #define READMAX 2
  3. #define BUFSIZ 2*READMAX
  4. #define EOF 255
  5. #define TIMEOUT 254
  6. #define FILEMAXLEN 20
  7. byte n[NBUFS];
  8. byte ntotal[NBUFS];
  9. byte putnext[NBUFS];
  10. byte getnext[NBUFS];
  11. bool eof[NBUFS];
  12. bool roomwait[NBUFS];
  13. bool datawait[NBUFS];
  14. byte rwant;
  15. /* use one big data array to simulate 2-d array */
  16. #define bufstart(slot) (slot*BUFSIZ)
  17. #define bufend(slot) ((slot+1)*BUFSIZ)
  18. /* bit data[BUFSIZ*NBUFS]; */
  19. bool selwait;
  20. /* bool hastimeout; */
  21. #define get 0
  22. #define release 1
  23. chan lock = [0] of { bit };
  24. chan lockkill = [0] of { bit };
  25. chan sel = [0] of { byte };
  26. chan selcall = [0] of { byte };
  27. chan selans = [0] of { byte, byte };
  28. chan selkill = [0] of { bit };
  29. chan readcall = [0] of { byte, byte };
  30. chan readans = [0] of { byte };
  31. chan readkill = [0] of { bit };
  32. chan croom[NBUFS] = [0] of { bit };
  33. chan cdata[NBUFS] = [0] of { bit };
  34. proctype Lockrendez()
  35. {
  36. do
  37. :: lock!get -> lock?release
  38. :: lockkill?release -> break
  39. od
  40. }
  41. proctype Copy(byte fd)
  42. {
  43. byte num;
  44. bit b;
  45. do :: 1 ->
  46. /* make sure there's room */
  47. lock?get;
  48. if
  49. :: (BUFSIZ-putnext[fd]) < READMAX ->
  50. if
  51. :: getnext[fd] == putnext[fd] ->
  52. getnext[fd] = 0;
  53. putnext[fd] = 0;
  54. lock!release
  55. :: getnext[fd] != putnext[fd] ->
  56. roomwait[fd] = 1;
  57. lock!release;
  58. croom[fd]?b
  59. fi
  60. :: (BUFSIZ-putnext[fd]) >= READMAX ->
  61. lock!release
  62. fi;
  63. /* simulate read into data buf at putnext */
  64. if
  65. :: ntotal[fd] > FILEMAXLEN ->
  66. num = EOF
  67. :: ntotal[fd] <= FILEMAXLEN ->
  68. if
  69. :: num = 1
  70. :: num = READMAX
  71. :: num = EOF
  72. fi
  73. fi;
  74. /* here is where data transfer would happen */
  75. lock?get;
  76. if
  77. :: num == EOF ->
  78. eof[fd] = 1;
  79. /* printf("Copy %d got eof\n", fd);/**/
  80. if
  81. :: datawait[fd] ->
  82. datawait[fd] = 0;
  83. lock!release;
  84. cdata[fd]!1
  85. :: !datawait[fd] && (rwant & (1<<fd)) && selwait ->
  86. selwait = 0;
  87. lock!release;
  88. sel!fd
  89. :: !datawait[fd] && !((rwant & (1<<fd)) && selwait) ->
  90. lock!release
  91. fi;
  92. break
  93. :: num != EOF ->
  94. /* printf("Copy %d putting %d in; old putnext=%d, old n=%d\n", fd, num, putnext[fd], n[fd]); /* */
  95. putnext[fd] = putnext[fd] + num;
  96. n[fd] = n[fd] + num;
  97. ntotal[fd] = ntotal[fd] + num;
  98. assert(n[fd] > 0);
  99. if
  100. :: datawait[fd] ->
  101. datawait[fd] = 0;
  102. lock!release;
  103. cdata[fd]!1
  104. :: !datawait[fd] && (rwant & (1<<fd)) && selwait ->
  105. selwait = 0;
  106. lock!release;
  107. sel!fd
  108. :: !datawait[fd] && !((rwant & (1<<fd)) && selwait) ->
  109. lock!release
  110. fi
  111. fi;
  112. od
  113. }
  114. proctype Read()
  115. {
  116. byte ngot;
  117. byte fd;
  118. byte nwant;
  119. bit b;
  120. do
  121. :: readcall?fd,nwant ->
  122. if
  123. :: eof[fd] && n[fd] == 0 ->
  124. readans!EOF
  125. :: !(eof[fd] && n[fd] == 0) ->
  126. lock?get;
  127. ngot = putnext[fd] - getnext[fd];
  128. /* printf("Reading %d, want %d: ngot = %d - %d, n = %d\n", fd, nwant, putnext[fd], getnext[fd], n[fd]); /* */
  129. if
  130. :: ngot == 0 ->
  131. if
  132. :: eof[fd] ->
  133. skip
  134. :: !eof[fd] ->
  135. /* sleep until there's data */
  136. datawait[fd] = 1;
  137. /* printf("Read sleeping\n"); /* */
  138. lock!release;
  139. cdata[fd]?b;
  140. lock?get;
  141. ngot = putnext[fd] - getnext[fd];
  142. /* printf("Read awoke, ngot = %d\n", ngot); /**/
  143. fi
  144. :: ngot != 0 -> skip
  145. fi;
  146. if
  147. :: ngot > nwant -> ngot = nwant
  148. :: ngot <= nwant -> skip
  149. fi;
  150. /* here would take ngot elements from data, from getnext[fd] ... */
  151. getnext[fd] = getnext[fd] + ngot;
  152. assert(n[fd] >= ngot);
  153. n[fd] = n[fd] - ngot;
  154. if
  155. :: ngot == 0 ->
  156. assert(eof[fd]);
  157. ngot = EOF
  158. :: ngot != 0 -> skip
  159. fi;
  160. if
  161. :: getnext[fd] == putnext[fd] && roomwait[fd] ->
  162. getnext[fd] = 0;
  163. putnext[fd] = 0;
  164. roomwait[fd] = 0;
  165. lock!release;
  166. croom[fd]!0
  167. :: getnext[fd] != putnext[fd] || !roomwait[fd] ->
  168. lock!release
  169. fi;
  170. readans!ngot
  171. fi
  172. :: readkill?b -> break
  173. od
  174. }
  175. proctype Select()
  176. {
  177. byte num;
  178. byte i;
  179. byte fd;
  180. byte r;
  181. bit b;
  182. do
  183. :: selcall?r ->
  184. /* printf("Select called, r=%d\n", r); /**/
  185. i = 0;
  186. do
  187. :: i < NBUFS ->
  188. if
  189. :: r & (1<<i) ->
  190. if
  191. :: eof[i] && n[i] == 0 ->
  192. /* printf("Select got eof on %d\n", i);/**/
  193. num = EOF;
  194. r = i;
  195. goto donesel
  196. :: !eof[i] || n[i] != 0 -> skip
  197. fi
  198. :: !(r & (1<<i)) -> skip
  199. fi;
  200. i = i+1
  201. :: i >= NBUFS -> break
  202. od;
  203. num = 0;
  204. lock?get;
  205. rwant = 0;
  206. i = 0;
  207. do
  208. :: i < NBUFS ->
  209. if
  210. :: r & (1<<i) ->
  211. if
  212. :: n[i] > 0 || eof[i] ->
  213. /* printf("Select found %d has n==%d\n", i, n[i]); /**/
  214. num = num+1
  215. :: n[i] == 0 && !eof[i] ->
  216. /* printf("Select asks to wait for %d\n", i); /**/
  217. r = r &(~(1<<i));
  218. rwant = rwant | (1<<i)
  219. fi
  220. :: !(r & (1<<i)) -> skip
  221. fi;
  222. i = i+1
  223. :: i >= NBUFS -> break
  224. od;
  225. if
  226. :: num > 0 || rwant == 0 ->
  227. rwant = 0;
  228. lock!release;
  229. :: num == 0 && rwant != 0 ->
  230. selwait = 1;
  231. lock!release;
  232. /* printf("Select sleeps\n"); /**/
  233. sel?fd;
  234. /* printf("Select wakes up, fd=%d\n", fd); /**/
  235. if
  236. :: fd != TIMEOUT ->
  237. if
  238. :: (rwant & (1<<fd)) && (n[fd] > 0) ->
  239. r = r | (1<<fd);
  240. num = 1
  241. :: !(rwant & (1<<fd)) || (n[fd] == 0) ->
  242. num = 0
  243. fi
  244. :: fd == TIMEOUT -> skip
  245. fi;
  246. rwant = 0
  247. fi;
  248. donesel:
  249. selans!num,r
  250. :: selkill?b -> break
  251. od
  252. }
  253. /* This routine is written knowing NBUFS == 2 in several places */
  254. proctype User()
  255. {
  256. byte ndone;
  257. byte i;
  258. byte rw;
  259. byte num;
  260. byte nwant;
  261. byte fd;
  262. bool goteof[NBUFS];
  263. ndone = 0;
  264. do
  265. :: ndone == NBUFS -> break
  266. :: ndone < NBUFS ->
  267. if
  268. :: 1->
  269. /* maybe use Read */
  270. /* printf("User trying to read. Current goteofs: %d %d\n", goteof[0], goteof[1]); /**/
  271. /* randomly pick fd 0 or 1 from non-eof ones */
  272. if
  273. :: !goteof[0] -> fd = 0
  274. :: !goteof[1] -> fd = 1
  275. fi;
  276. if
  277. :: nwant = 1
  278. :: nwant = READMAX
  279. fi;
  280. readcall!fd,nwant;
  281. readans?num;
  282. if
  283. :: num == EOF ->
  284. goteof[fd] = 1;
  285. ndone = ndone + 1
  286. :: num != EOF -> assert(num != 0)
  287. fi
  288. :: 1->
  289. /* printf("User trying to select. Current goteofs: %d %d\n", goteof[0], goteof[1]); /**/
  290. /* maybe use Select, then Read */
  291. /* randomly set the "i want" bit for non-eof fds */
  292. if
  293. :: !goteof[0] && !goteof[1] -> rw = (1<<0) | (1<<1)
  294. :: !goteof[0] -> rw = (1<<0)
  295. :: !goteof[1] -> rw = (1<<1)
  296. fi;
  297. selcall!rw;
  298. selans?i,rw;
  299. if
  300. :: i == EOF ->
  301. goteof[rw] = 1;
  302. ndone = ndone + 1
  303. :: i != EOF ->
  304. /* this next statement knows NBUFS == 2 ! */
  305. if
  306. :: rw & (1<<0) -> fd = 0
  307. :: rw & (1<<1) -> fd = 1
  308. :: rw == 0 -> fd = EOF
  309. fi;
  310. if
  311. :: nwant = 1
  312. :: nwant = READMAX
  313. fi;
  314. if
  315. :: fd != EOF ->
  316. readcall!fd,nwant;
  317. readans?num;
  318. assert(num != 0)
  319. :: fd == EOF -> skip
  320. fi
  321. fi
  322. fi
  323. od;
  324. lockkill!release;
  325. selkill!release;
  326. readkill!release
  327. }
  328. init
  329. {
  330. byte i;
  331. atomic {
  332. run Lockrendez();
  333. i = 0;
  334. do
  335. :: i < NBUFS ->
  336. run Copy(i);
  337. i = i+1
  338. :: i >= NBUFS -> break
  339. od;
  340. run Select();
  341. run Read();
  342. run User()
  343. }
  344. }