source: CIVL/examples/concurrency/bank.cvl@ 8d704f9e

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 8d704f9e was 8d704f9e, checked in by Tim Zirkel <zirkeltk@…>, 13 years ago

Added bank example.

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

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