source: CIVL/examples/concurrency/bank.cvl

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

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

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/* simple exercise in multitasking verification using CIVL.
2 * Commandline execution:
3 * civl verify -inputNUM_ACCOUNTS=5 bank.cvl
4 * */
5#include<civlc.cvh>
6
7$input int NUM_ACCOUNTS = 3;
8
9/* ========================================================================
10 constants
11 */
12#define true 1
13#define false 0
14
15/* ========================================================================
16 prototypes
17 */
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/* ======================================================================== */
34void init ()
35{
36 int acct_num;
37
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 int result;
50
51 $assume(0 <= account_num);
52 $assume(account_num <= NUM_ACCOUNTS);
53 $assume(amount >= 0);
54 // begin transaction
55 lock_account( account_num );
56 if ( account_balance[account_num] >= amount ) {
57 account_balance[account_num]= account_balance[account_num]- amount;
58 result= false;
59 } else {
60 result= true;
61 }
62 // end transaction
63 unlock_account( account_num );
64 return result;
65}
66
67/* ======================================================================== */
68int deposit( int account_num, int amount )
69/* Return value: false if success, true if an error occurred
70 */
71{
72 $assume(0 <= account_num);
73 $assume(account_num <= NUM_ACCOUNTS);
74 $assume(amount >= 0);
75 // begin transaction
76 lock_account( account_num );
77 account_balance[account_num]= account_balance[account_num]+ amount;
78 // end transaction
79 unlock_account( account_num );
80 return false;
81}
82
83/* ======================================================================== */
84int balance( int account_num )
85/* Return value: the balance of the indicated account
86 */
87{
88 int balance= 0;
89
90 $assume(0 <= account_num);
91 $assume(account_num <= NUM_ACCOUNTS);
92 // begin transaction
93 lock_account( account_num );
94 balance= account_balance[account_num];
95 // end transaction
96 unlock_account( account_num );
97 return account_balance[account_num];
98}
99
100/* ======================================================================== */
101int transfer( int to_account_num, int from_account_num, int amount )
102/* Return value: false if success, true if an error occurred
103 */
104{
105 int result= false;
106
107 $assume(0 <= to_account_num);
108 $assume(to_account_num <= NUM_ACCOUNTS);
109 $assume(0 <= from_account_num);
110 $assume(from_account_num <= NUM_ACCOUNTS);
111 $assume(from_account_num != to_account_num);
112 $assume(amount >= 0);
113 // begin transaction
114 if ( from_account_num < to_account_num ) {
115 lock_account( from_account_num );
116 lock_account( to_account_num );
117 } else {
118 lock_account( to_account_num );
119 lock_account( from_account_num );
120 }
121 if ( account_balance[from_account_num] >= amount ) {
122 account_balance[from_account_num]-= amount;
123 account_balance[to_account_num]+= amount;
124 result= false;
125 } else {
126 result= true;
127 }
128 // end transaction
129 if ( from_account_num < to_account_num ) {
130 unlock_account( to_account_num );
131 unlock_account( from_account_num );
132 } else {
133 unlock_account( from_account_num );
134 unlock_account( to_account_num );
135 }
136 return result;
137}
138
139/* ======================================================================== */
140/* main() and its helper ftns
141 */
142void main_a()
143{
144 withdraw( 0, 50 );
145 transfer( 0, 1, 50 );
146 deposit( 2, 100 );
147}
148
149void main_b()
150{
151 deposit( 1, 10 );
152 withdraw( 2, 50 );
153 transfer( 2, 0, 20 );
154}
155
156void main()
157{
158 int acct_num = 0;
159 $proc proc_a;
160 $proc proc_b;
161
162 init();
163 /* give all accounts some money */
164 for ( acct_num= 0; acct_num < NUM_ACCOUNTS; acct_num++ ) {
165 deposit( acct_num, 100 );
166 }
167 proc_a= $spawn main_a();
168 proc_b= $spawn main_b();
169 $wait(proc_a);
170 $wait(proc_b);
171}
172
173/* ======================================================================== */
174void lock_account( int account_num )
175{
176 $assume(0 <= account_num);
177 $assume(account_num <= NUM_ACCOUNTS);
178 // this needs to happen atomically -- does it?
179 $when (account_locked[account_num] == false) account_locked[account_num]= true;
180}
181
182/* ======================================================================== */
183void unlock_account( int account_num )
184{
185 $assume(0 <= account_num);
186 $assume(account_num <= NUM_ACCOUNTS);
187
188 account_locked[ account_num ]= false;
189}
190/* ======================================================================== */
191/* end of file */
Note: See TracBrowser for help on using the repository browser.