Advertisement
Guest User

Untitled

a guest
May 26th, 2018
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.71 KB | None | 0 0
  1. #define CLIENS 10
  2. #define CASH 10
  3. #define FEE_MAX 50
  4. #define TRANSFER_MAX 50
  5. #define MAX_WAIT 50
  6.  
  7. int account[CLIENS];
  8. int lock[CLIENS];
  9. int dead[CLIENS];
  10.  
  11. int transactions = 0;
  12. int max_transactions = 0;
  13.  
  14. bool all_broke = false;
  15. bool release_read_lock_error = false;
  16.  
  17. inline all_broke_check() {
  18. int counter = 0;
  19. int sum = 0;
  20. atomic {
  21. do
  22. :: counter < CLIENS ->
  23. sum = sum + account[counter];
  24. counter++;
  25. :: else ->
  26. break;
  27. od;
  28. }
  29. printf("[%d]%d %d %d %d\n", sum, account[0],account[1],account[2],account[3]);
  30. bool answer = sum == 0;
  31. printf("[%d] All Broke %d\n", _pid, answer);
  32. all_broke = answer;
  33. }
  34.  
  35. inline get_single_lock(id, got_it){
  36. got_it = false;
  37. int counter = 0;
  38. atomic{
  39. do
  40. :: lock[id] == 0 ->
  41. lock[id] = _pid+1;
  42. printf("[%d] Got lock on %d\n", _pid, id);
  43. got_it = true;
  44. break;
  45. :: counter > MAX_WAIT ->
  46. got_it = false;
  47. break;
  48. :: else ->
  49. printf("[%d] Waiting for lock on %d, %d\n", _pid, id, lock[id]);
  50. counter++;
  51. od;
  52. }
  53. printf("Locks: %d %d %d\n", lock[0], lock[1], lock[2]);
  54. }
  55.  
  56. inline release_single_lock(id){
  57. atomic{
  58. if
  59. :: lock[id] != _pid+1 ->
  60. release_read_lock_error = false;
  61. lock[id] = 0;
  62. printf("[%d] Released lock on %d\n", _pid, id);
  63. :: else ->
  64. lock[id] = 0;
  65. printf("[%d] Released lock on %d\n", _pid, id);
  66. fi;
  67. }
  68. printf("Locks: %d %d %d\n", lock[0], lock[1], lock[2]);
  69. }
  70.  
  71. inline broke(id, x) {
  72. printf("[%d] Cheking if broke %d\n", _pid, id);
  73. bool got_it = false;
  74. get_single_lock(id, got_it);
  75. if
  76. :: got_it ->
  77. x = account[id] <= 0;
  78. printf("[%d] Account value: %d\n", _pid, account[id]);
  79. release_single_lock(id);
  80. :: else ->
  81. skip;
  82. fi;
  83. }
  84.  
  85. inline min_or_zero(a) {
  86. if
  87. :: a < 0 ->
  88. a = 0;
  89. :: else ->
  90. skip;
  91. fi;
  92. }
  93.  
  94. inline pay_fee(id, value) {
  95. printf("[%d] Paying fee %d\n", _pid, value);
  96. bool got_it = false;
  97. get_single_lock(id, got_it);
  98. if
  99. :: got_it ->
  100. int new_value = account[id] - value;
  101. min_or_zero(new_value);
  102. account[id] = new_value;
  103. release_single_lock(id);
  104. :: else ->
  105. skip;
  106. fi;
  107. }
  108.  
  109. inline get_double_lock(id1, id2, got_it){
  110. bool got_it_1 = false;
  111. bool got_it_2 = false;
  112. if
  113. :: id1 < id2 ->
  114. get_single_lock(id1, got_it_1);
  115. if
  116. :: got_it_1 ->
  117. get_single_lock(id2, got_it_2);
  118. :: else ->
  119. release_single_lock(id1);
  120. fi;
  121. got_it = got_it_2
  122. :: id1 > id2 ->
  123. get_single_lock(id2, got_it_1);
  124. if
  125. :: got_it_1 ->
  126. get_single_lock(id1, got_it_2);
  127. :: else ->
  128. release_single_lock(id2);
  129. fi;
  130. got_it = got_it_2
  131. :: id1 == id2 ->
  132. printf("[%d] Shoudn't happen\n", _pid);
  133. fi;
  134. }
  135.  
  136. inline release_double_lock(id1, id2){
  137. if
  138. :: id1 < id2 ->
  139. release_single_lock(id2);
  140. release_single_lock(id1);
  141. :: id1 > id2 ->
  142. release_single_lock(id1);
  143. release_single_lock(id2);
  144. :: id1 == id2 ->
  145. printf("[%d] Shoudn't happen 2\n", _pid);
  146. fi;
  147. }
  148.  
  149. inline get_avalible_sum(id, value){
  150. printf("[%d] Checking avalible sum\n", _pid);
  151. bool got_it = false;
  152. get_single_lock(id, got_it);
  153. if
  154. :: got_it ->
  155. int savings = account[id];
  156. if
  157. :: savings >= value ->
  158. skip;
  159. :: else ->
  160. value = savings;
  161. fi;
  162. release_single_lock(id);
  163. :: else ->
  164. skip;
  165.  
  166. }
  167.  
  168. inline transfer_money(id1, id2, value){
  169. bool id2_broke = false;
  170. broke(id2, id2_broke);
  171. if
  172. :: id1 != id2 && !id2_broke->
  173. printf("[%d] Transfering %d to %d\n", _pid, value, id2);
  174. int transfer_sum = value;
  175. bool got_it = false;
  176. get_double_lock(id1, id2, got_it);
  177. if
  178. :: got_it ->
  179. transactions++;
  180. int savings = account[id1];
  181. if
  182. :: savings >= transfer_sum ->
  183. skip;
  184. :: else ->
  185. transfer_sum = savings;
  186. fi;
  187.  
  188. int old_sum = account[id1];
  189. account[id1] = old_sum - transfer_sum;
  190. int new_sum = account[id2];
  191. account[id2] = new_sum + transfer_sum;
  192. transactions--;
  193. release_double_lock(id1, id2);
  194. :: else ->
  195. skip;
  196. fi;
  197. :: else ->
  198. skip;
  199. fi;
  200. }
  201.  
  202. inline rand(x, from, up_to) {
  203. x = 0;
  204. select(x: from..up_to)
  205. }
  206.  
  207.  
  208. active [CLIENS] proctype client() {
  209. account[_pid] = CASH;
  210. bool is_broke = false;
  211. int money = 0;
  212. int user = 0;
  213. printf("[%d] Account value: %d\n", _pid, account[_pid]);
  214. do
  215. :: is_broke ->
  216. break;
  217. ::
  218. rand(money, 1, FEE_MAX);
  219. pay_fee(_pid, money);
  220. broke(_pid, is_broke);
  221. ::
  222. rand(money,1, TRANSFER_MAX);
  223. rand(user, 0, CLIENS - 1);
  224. transfer_money(_pid, user, money);
  225. broke(_pid, is_broke);
  226. od;
  227. all_broke_check();
  228. printf("Broke: %d\n", all_broke);
  229. printf("Trans: %d\n", max_transactions);
  230. printf("Error: %d\n", release_read_lock_error);
  231. }
  232.  
  233. active proctype Watcher() {
  234. do
  235. :: all_broke ->
  236. break;
  237. :: max_transactions > 1 ->
  238. printf("More then one transaction -----------------\n");
  239. break;
  240. :: release_read_lock_error ->
  241. printf("Release error ----------------------\n");
  242. break;
  243. :: else ->
  244. if
  245. :: transactions > max_transactions ->
  246. max_transactions = transactions;
  247. :: else ->
  248. skip;
  249. fi;
  250. od;
  251. }
  252.  
  253. ltl all_broke_eventually{<>(all_broke)}
  254. ltl more_then_one_transaction_at_the_time{<>(transactions > 1)}
  255. ltl always_correct_lock_release{[](!release_read_lock_error)}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement