source: CIVL/examples/concurrency/bank.cvl@ 2b5dc93

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since 2b5dc93 was a6ae46e, checked in by Stephen Siegel <siegel@…>, 13 years ago

Fixed a defect in the bank.cvl example. Improved the output of the Deadlock predicate by making it print source information.

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

  • Property mode set to 100644
File size: 5.0 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 withdraw( 0, 50 );
161 transfer( 0, 1, 50 );
162 deposit( 2, 100 );
163}}
164
165void main_b()
166{{
167 deposit( 1, 10 );
168 withdraw( 2, 50 );
169 transfer( 2, 0, 20 );
170}}
171
172void main()
173{{
174 int acct_num = 0;
175
176 $proc proc_a;
177 $proc proc_b;
178
179 init();
180
181 /* give all accounts some money */
182 for ( acct_num= 0; acct_num < NUM_ACCOUNTS; acct_num++ ) {
183 deposit( acct_num, 100 );
184 }
185
186 proc_a= $spawn main_a();
187 proc_b= $spawn main_b();
188
189 $wait proc_a;
190 $wait proc_b;
191 // main_a();
192 // main_b();
193}}
194
195/* ======================================================================== */
196
197void lock_account( int account_num )
198{{
199 $assume 0 <= account_num;
200 $assume account_num <= NUM_ACCOUNTS;
201
202 // this needs to happen atomically -- does it?
203 $when (account_locked[account_num] == false) account_locked[account_num]= true;
204}}
205
206/* ======================================================================== */
207void unlock_account( int account_num )
208{{
209 $assume 0 <= account_num;
210 $assume account_num <= NUM_ACCOUNTS;
211
212 account_locked[ account_num ]= false;
213}}
214
215
216
217/* ======================================================================== */
218/* end of file */
219
220
Note: See TracBrowser for help on using the repository browser.