Skip to content

Commit 954a8d2

Browse files
authored
Merge branch 'main' into gebner_phase1_matcher
2 parents c54e544 + e243a9e commit 954a8d2

File tree

1 file changed

+178
-0
lines changed

1 file changed

+178
-0
lines changed

share/pulse/examples/Dekker.fst

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
module Dekker
2+
#lang-pulse
3+
open Pulse.Lib.Pervasives
4+
module GR = Pulse.Lib.GhostReference
5+
module R = Pulse.Lib.Reference
6+
open Pulse.Class.PtsTo
7+
8+
(* Dekker's algorithm for mutual exclusion relies on sequential consistency
9+
10+
a := 0; b := 0;
11+
par
12+
(
13+
atomic_write a 1;
14+
if atomic_read b = 0
15+
then /* critical section */
16+
)
17+
(
18+
atomic_write b 1;
19+
if atomic_read a = 0
20+
then /* critical section */
21+
)
22+
23+
This is provable in Pulse with an invariant & ghost state
24+
*)
25+
26+
27+
// Some primitives for atomic read and write
28+
atomic
29+
fn read_atomic (r:R.ref bool) (#p:perm) (#v:erased bool)
30+
requires
31+
r |-> Frac p v
32+
returns b:bool
33+
ensures
34+
r |-> Frac p v
35+
ensures
36+
pure (b == reveal v)
37+
{admit()}
38+
39+
atomic
40+
fn write_atomic (r:R.ref bool) (b:bool)
41+
requires
42+
exists* v. r |-> v
43+
ensures
44+
r |-> b
45+
{ admit() }
46+
47+
//The main invariant
48+
let dekker_inv (ra rb:R.ref bool) (ga gb:GR.ref bool) (p:slprop)
49+
: slprop
50+
= exists* (va vb ua ub:bool).
51+
(ra |-> Frac 0.5R va) **
52+
(rb |-> Frac 0.5R vb) **
53+
(ga |-> Frac 0.5R ua) **
54+
(gb |-> Frac 0.5R ub) **
55+
cond (ua || ub) emp p ** //if both ghost variables are false, then p is available
56+
pure ( //ghost vars are false if their concrete counterparts are
57+
(va=false ==> ua=false) /\
58+
(vb=false ==> ub=false)
59+
)
60+
61+
ghost
62+
fn intro_dekker_inv_init
63+
(ra rb:R.ref bool) (ga gb:GR.ref bool) (p:slprop)
64+
requires
65+
(ra |-> Frac 0.5R false) **
66+
(rb |-> Frac 0.5R false) **
67+
(ga |-> Frac 0.5R false) **
68+
(gb |-> Frac 0.5R false) **
69+
p
70+
ensures
71+
dekker_inv ra rb ga gb p
72+
{
73+
intro_cond_false emp p;
74+
fold (dekker_inv ra rb ga gb p)
75+
}
76+
77+
ghost
78+
fn init_dekker_inv
79+
(ra rb:R.ref bool)
80+
(ga gb:GR.ref bool)
81+
(p:slprop)
82+
requires
83+
(ra |-> false) **
84+
(rb |-> false) **
85+
(ga |-> false) **
86+
(gb |-> false) **
87+
p
88+
returns i:iname
89+
ensures
90+
inv i (dekker_inv ra rb ga gb p)
91+
ensures
92+
(ra |-> Frac 0.5R false) **
93+
(rb |-> Frac 0.5R false) **
94+
(ga |-> Frac 0.5R false) **
95+
(gb |-> Frac 0.5R false)
96+
{
97+
R.share ra; R.share rb;
98+
GR.share ga; GR.share gb;
99+
intro_dekker_inv_init ra rb ga gb p;
100+
let i = new_invariant (dekker_inv ra rb ga gb p);
101+
i
102+
}
103+
104+
ghost
105+
fn intro_dekker_inv_a
106+
(ra rb:R.ref bool) (ga gb:GR.ref bool) (p:slprop)
107+
requires
108+
exists* (vb ub:bool).
109+
(ra |-> Frac 0.5R true) **
110+
(rb |-> Frac 0.5R vb) **
111+
(ga |-> Frac 0.5R true) **
112+
(gb |-> Frac 0.5R ub) **
113+
pure (
114+
(vb=false ==> ub=false)
115+
)
116+
ensures
117+
dekker_inv ra rb ga gb p
118+
{
119+
intro_cond_true emp p;
120+
fold (dekker_inv ra rb ga gb p)
121+
}
122+
123+
124+
fn procA (i:iname) (ra rb:R.ref bool) (ga gb:GR.ref bool) (p:slprop)
125+
preserves
126+
inv i (dekker_inv ra rb ga gb p) //with the invariant
127+
requires
128+
(ra |-> Frac 0.5R false) ** //if a is initially false
129+
(exists* (ua:bool). ga |-> Frac 0.5R ua) //and with ga
130+
returns b:bool
131+
ensures
132+
(ra |-> Frac 0.5R true) ** //a is true
133+
(ga |-> Frac 0.5R b) //g is set to the return value
134+
ensures
135+
(if b then p else emp) //and if this returns true then we have the resource p
136+
{
137+
later_credit_buy 1;
138+
with_invariants i
139+
returns _:unit
140+
ensures
141+
later (dekker_inv ra rb ga gb p) **
142+
(ra |-> Frac 0.5R true) **
143+
(ga |-> Frac 0.5R false)
144+
{
145+
later_elim _;
146+
unfold dekker_inv;
147+
R.gather ra;
148+
write_atomic ra true; // x := true
149+
R.share ra;
150+
GR.gather ga;
151+
GR.share ga;
152+
fold (dekker_inv ra rb ga gb p);
153+
later_intro (dekker_inv ra rb ga gb p);
154+
};
155+
later_credit_buy 1;
156+
with_invariants i
157+
{
158+
later_elim _;
159+
unfold dekker_inv;
160+
R.gather ra; R.share ra;
161+
if (read_atomic rb)
162+
{
163+
fold (dekker_inv ra rb ga gb);
164+
later_intro (dekker_inv _ _ _ _ _);
165+
false
166+
}
167+
else
168+
{
169+
GR.gather ga;
170+
elim_cond_false _ _ _;
171+
GR.write ga true;
172+
GR.share ga;
173+
intro_dekker_inv_a ra rb ga gb p;
174+
later_intro (dekker_inv _ _ _ _ _);
175+
true
176+
}
177+
};
178+
}

0 commit comments

Comments
 (0)