source: CIVL/examples/concurrency/bank.cvl@ 23207c6

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 23207c6 was 24ca21c, checked in by Manchun Zheng <zmanchun@…>, 13 years ago

improve output. Add atomic to some examples.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@391 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 5.1 KB
Line 
1/* bank.cil
2
3simple exercise in multitasking verification using CIVL.
4
5*/
6#include<civlc.h>
7
8/* ========================================================================
9 constants
10 */
11#define NUM_ACCOUNTS 3
12
13#define true 1
14#define false 0
15
16
17/* ========================================================================
18 prototypes
19 */
20void init();
21int withdraw( int account_num, int amount );
22int deposit( int account_num, int amount );
23int balance( int account_num );
24int transfer( int to_account_num, int from_account_num, int amount );
25void lock_account( int account_num );
26void unlock_account( int account_num );
27
28/* ========================================================================
29 global variables
30 */
31int account_balance[ NUM_ACCOUNTS ];
32int account_locked[ NUM_ACCOUNTS ];
33
34/* ======================================================================== */
35void init ()
36{{
37 int acct_num;
38 for ( acct_num= 0; acct_num < NUM_ACCOUNTS; acct_num++ ) {
39 account_balance[acct_num]= 0;
40 account_locked[acct_num]= false;
41 }
42}}
43
44/* ======================================================================== */
45int withdraw( int account_num, int amount )
46/* Return value: false if success, true if an error occurred
47 */
48{{
49 $assume 0 <= account_num;
50 $assume account_num <= NUM_ACCOUNTS;
51 $assume amount >= 0;
52
53 int result;
54
55 // begin transaction
56 lock_account( account_num );
57
58 if ( account_balance[account_num] >= amount ) {
59 account_balance[account_num]= account_balance[account_num]- amount;
60 result= false;
61 } else {
62 result= true;
63 }
64
65 // end transaction
66 unlock_account( account_num );
67
68 return result;
69}}
70
71/* ======================================================================== */
72int deposit( int account_num, int amount )
73/* Return value: false if success, true if an error occurred
74 */
75{{
76 $assume 0 <= account_num;
77 $assume account_num <= NUM_ACCOUNTS;
78 $assume amount >= 0;
79
80 // begin transaction
81 lock_account( account_num );
82
83 account_balance[account_num]= account_balance[account_num]+ amount;
84
85 // end transaction
86 unlock_account( account_num );
87
88 return false;
89}}
90
91/* ======================================================================== */
92int balance( int account_num )
93/* Return value: the balance of the indicated account
94 */
95{{
96 $assume 0 <= account_num;
97 $assume account_num <= NUM_ACCOUNTS;
98
99 int balance= 0;
100
101 // begin transaction
102 lock_account( account_num );
103
104 balance= account_balance[account_num];
105
106 // end transaction
107 unlock_account( account_num );
108
109 return account_balance[account_num];
110}}
111
112/* ======================================================================== */
113int transfer( int to_account_num, int from_account_num, int amount )
114/* Return value: false if success, true if an error occurred
115 */
116{{
117 $assume 0 <= to_account_num;
118 $assume to_account_num <= NUM_ACCOUNTS;
119 $assume 0 <= from_account_num;
120 $assume from_account_num <= NUM_ACCOUNTS;
121 $assume from_account_num != to_account_num;
122 $assume amount >= 0;
123
124 int result= false;
125
126 // begin transaction
127 if ( from_account_num < to_account_num ) {
128 lock_account( from_account_num );
129 lock_account( to_account_num );
130 } else {
131 lock_account( to_account_num );
132 lock_account( from_account_num );
133 }
134
135 if ( account_balance[from_account_num] >= amount ) {
136 account_balance[from_account_num]-= amount;
137 account_balance[to_account_num]+= amount;
138 result= false;
139 } else {
140 result= true;
141 }
142
143 // end transaction
144 if ( from_account_num < to_account_num ) {
145 unlock_account( to_account_num );
146 unlock_account( from_account_num );
147 } else {
148 unlock_account( from_account_num );
149 unlock_account( to_account_num );
150 }
151
152 return result;
153}}
154
155/* ======================================================================== */
156/* main() and its helper ftns
157 */
158void main_a()
159{{
160 $atomic{
161 withdraw( 0, 50 );
162 transfer( 0, 1, 50 );
163 deposit( 2, 100 );}
164}}
165
166void main_b()
167{{
168 $atomic{
169 deposit( 1, 10 );
170 withdraw( 2, 50 );
171 transfer( 2, 0, 20 );}
172}}
173
174void main()
175{{
176 int acct_num = 0;
177
178 $proc proc_a;
179 $proc proc_b;
180
181 $atomic{
182 init();
183
184 /* give all accounts some money */
185 for ( acct_num= 0; acct_num < NUM_ACCOUNTS; acct_num++ ) {
186 deposit( acct_num, 100 );
187 }
188 }
189
190 $atomic{
191 proc_a= $spawn main_a();
192 proc_b= $spawn main_b();}
193
194 $atomic{
195 $wait proc_a;
196 $wait proc_b;}
197 // main_a();
198 // main_b();
199}}
200
201/* ======================================================================== */
202
203void lock_account( int account_num )
204{{
205 $assume 0 <= account_num;
206 $assume account_num <= NUM_ACCOUNTS;
207
208 // this needs to happen atomically -- does it?
209 $when (account_locked[account_num] == false) account_locked[account_num]= true;
210}}
211
212/* ======================================================================== */
213void unlock_account( int account_num )
214{{
215 $assume 0 <= account_num;
216 $assume account_num <= NUM_ACCOUNTS;
217
218 account_locked[ account_num ]= false;
219}}
220
221
222
223/* ======================================================================== */
224/* end of file */
225
226
Note: See TracBrowser for help on using the repository browser.