-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathread_optimized_reference.v
More file actions
334 lines (303 loc) · 9.99 KB
/
Copy pathread_optimized_reference.v
File metadata and controls
334 lines (303 loc) · 9.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
From iris.bi Require Import lib.fractional.
From iris.proofmode Require Import tactics.
From self.base Require Import primitive_laws.
From self.lang Require Import lang.
From self.high Require Import dprop.
From self.lang Require Import notation lang.
From self.algebra Require Import view.
From self.base Require Import primitive_laws class_instances.
From self.high Require Import proofmode wpc_proofmode if_rec.
From self.high Require Import dprop abstract_state_instances modalities
resources crash_weakestpre weakestpre weakestpre_na weakestpre_at
recovery_weakestpre lifted_modalities protocol protocols no_buffer
mapsto_na_flushed.
From self.high.modalities Require Import fence.
(* Implementation. *)
Definition RR_init : expr :=
λ: "v",
let: "per" := ref_NA "v" in
Flush "per" ;;
FenceSync ;;
let: "vol" := ref_NA "v" in
("per", "vol").
Definition RR_read : expr :=
λ: "rr", !_NA (Snd "rr").
Definition RR_write : expr :=
λ: "rr" "v",
let: "per" := Fst "rr" in
let: "vol" := Snd "rr" in
"per" <-_NA "v" ;;
Flush "per" ;;
FenceSync ;;
"vol" <-_NA "v".
Definition RR_recover : expr :=
λ: "rr",
let: "per" := Fst "rr" in
let: "vol" := ref_NA (!_NA "per") in
("per", "vol").
Section spec.
Context `{nvmG Σ}.
Context `{!stagedG Σ}.
Program Definition rr_prot : LocationProtocol (numbered val) :=
{| p_inv := λ '(mk_numbered t v) v', ⌜ v = v' ⌝%I;
p_bumper v := v |}.
Global Instance rr_prot_conditions : ProtocolConditions rr_prot.
Proof.
split; try apply _.
- destruct s. simpl. apply _.
- iIntros ([?] ?) "? /=". iModIntro. done.
Qed.
Definition is_RR (vrr : val) v : dProp Σ :=
∃ (ℓp ℓv : loc) n ss,
"->" ∷ ⌜ vrr = (#ℓp, #ℓv)%V ⌝ ∗
"pPts" ∷ ℓp ↦_{rr_prot} [mk_numbered n v] ∗
"perLb" ∷ persist_lb ℓp rr_prot (mk_numbered n v) ∗
"vPts" ∷ ℓv ↦_{rr_prot} (ss ++ [mk_numbered n v]).
Definition is_recoverable_RR (vrr : val) v : dProp Σ :=
∃ (ℓp ℓv : loc) n,
"->" ∷ ⌜ vrr = (#ℓp, #ℓv)%V ⌝ ∗
"pPts" ∷ ℓp ↦_{rr_prot} [mk_numbered n v] ∗
"perLb" ∷ persist_lb ℓp rr_prot (mk_numbered n v).
Lemma crash_condition_impl' n v ℓp (ℓv : loc) :
ℓp ↦_{rr_prot} [mk_numbered n v] -∗
persist_lb ℓp rr_prot (mk_numbered n v) -∗
<PC> is_recoverable_RR (#ℓp, #ℓv) v.
Proof.
iIntros "pPts perLb".
iModIntro.
iDestruct "perLb" as "(per & Hh)".
iDestruct "Hh" as (sRec incl) "#crashedIn".
iDestruct (crashed_in_if_rec with "crashedIn pPts")
as (??) "(%prefix & crashedIn2 & pPts)".
apply prefix_app_singleton in prefix as [-> ->].
simpl.
iExists ℓp, ℓv, n.
iSplitPure; first done.
simpl.
iFrame "pPts".
iFrame "per".
Qed.
Lemma is_RR_post_crash vrr v :
is_RR vrr v ⊢ <PC> is_recoverable_RR vrr v.
Proof.
iNamed 1.
iApply (crash_condition_impl' with "pPts perLb").
Qed.
Lemma RR_init_spec (v : val) s E :
⊢ WPC RR_init v @ s; E {{ rv, is_RR rv v }} {{ True }}%I.
Proof.
rewrite /RR_init.
iApply wp_wpc.
wp_pures.
wp_apply (wp_alloc_na v (mk_numbered 0 v) rr_prot); simpl; first done.
iIntros (ℓp) "pPts".
wp_pures.
wp_apply (wp_flush_na _ _ _ _ [] with "pPts").
iIntros "(pPts & _ & perLb)".
wp_pures.
wp_apply wp_fence_sync. iModIntro.
wp_pures.
wp_apply (wp_alloc_na v (mk_numbered 0 v) rr_prot); simpl; first done.
iIntros (ℓv) "vPts".
wp_pures.
iModIntro. iExists _, _, _, [].
iSplitPure; first done. iFrameF "pPts". iFrame "vPts perLb".
Qed.
Lemma crash_condition_impl n v ℓp (ℓv : loc) :
ℓp ↦_{rr_prot} [mk_numbered n v] -∗
ℓv ↦_{rr_prot} [mk_numbered n v] -∗
persist_lb ℓp rr_prot (mk_numbered n v) -∗
<PC> is_recoverable_RR (#ℓp, #ℓv) v.
Proof.
iIntros "pPts vPts perLb".
iApply is_RR_post_crash.
iExists ℓp, ℓv, n, [].
iSplitPure; first done.
iFrame.
Qed.
Lemma prefix_of_2 {A} (xs : list A) x1 x2 :
xs `prefix_of` [x1; x2] →
xs = [] ∨ xs = [x1] ∨ xs = [x1; x2].
Proof.
destruct xs as [|x1' xs]. { naive_solver. }
intros [-> pre]%prefix_cons_inv.
destruct xs as [|x2' xs]. { naive_solver. }
apply prefix_cons_inv in pre as [-> pre].
apply prefix_nil_inv in pre as ->.
naive_solver.
Qed.
Lemma crash_condition_impl_2 n v w ℓp (ℓv : loc) :
ℓp ↦_{rr_prot} [mk_numbered n v; mk_numbered (n + 1) w] -∗
persist_lb ℓp rr_prot (mk_numbered n v) -∗
<PC> ∃ u, is_recoverable_RR (#ℓp, #ℓv) u ∗ ⌜ u = v ∨ u = w ⌝.
Proof.
iIntros "pPts perLb".
iCrashIntro.
iDestruct "perLb" as "[per (% & hi & crashedIn)]".
iDestruct (crashed_in_if_rec with "crashedIn pPts")
as (??) "(%pre & crashedIn2 & pPts)".
apply prefix_of_2 in pre as [eq | [eq | eq]].
{ destruct ss'; inversion eq. }
- destruct ss'; inversion eq.
2: { destruct ss'; inversion eq. }
iExists v.
iSplit; last naive_solver.
repeat iExists _.
iSplitPure; first done.
iFrameF "pPts".
simpl.
iFrame "per".
- destruct ss'; inversion eq.
destruct ss'; inversion eq.
2: { simpl in eq. destruct ss'; inversion eq. }
iExists w.
iSplit; last naive_solver.
iExists _, _, (n + 1).
iSplitPure; first done.
iDestruct (crashed_in_persist_lb with "crashedIn2") as "#per2".
simpl.
iFrame "per2".
iDestruct (mapsto_na_persist_lb with "pPts per2") as "HII".
{ intros [?|?]; lia. }
iFrame "HII".
Qed.
Lemma RR_read_spec rv (v : val) s E :
is_RR rv v -∗
WPC RR_read rv @ s; E {{ w, ⌜ v = w ⌝ ∗ is_RR rv v }}
{{ <PC> is_recoverable_RR rv v }}%I.
Proof.
iNamed 1.
rewrite /RR_read.
wpc_pures.
{ iApply (crash_condition_impl' with "pPts perLb"). }
iApply wpc_atomic_no_mask.
iSplit.
{ iApply (crash_condition_impl' with "pPts perLb"). }
wp_apply (wp_load_na with "[$vPts]").
{ apply last_snoc. }
{ iModIntro. simpl.
iIntros (?) "#H". iFrame "H". rewrite right_id. iApply "H". }
iIntros (?) "(vPts & <-)".
iSplit.
{ iModIntro.
iApply (crash_condition_impl' with "pPts perLb"). }
iModIntro. iSplitPure; first reflexivity.
repeat iExists _.
iFrame "pPts vPts perLb".
done.
Qed.
Lemma RR_write_spec rv (v w : val) s E :
is_RR rv v -∗
WPC RR_write rv w @ s; E
{{ _, is_RR rv w }}
{{ <PC> ∃ u, is_recoverable_RR rv u ∗ ⌜ u = v ∨ u = w ⌝}}%I.
Proof.
iNamed 1.
rewrite /RR_write.
wpc_pures.
{ iApply post_crash_mono;
last iApply (crash_condition_impl' with "pPts perLb").
iIntros "H". iExists _. iFrame "H". naive_solver. }
wpc_bind (_ <-_NA _)%E.
iApply wpc_atomic_no_mask.
iSplit.
{ iApply post_crash_mono;
last iApply (crash_condition_impl' with "pPts perLb").
iIntros "H". iExists _. iFrame "H". naive_solver. }
iApply (wp_store_na _ rr_prot _ _ _ (mk_numbered (n + 1) w) with "[$pPts]").
{ done. }
{ apply numbered_le. lia. }
{ simpl. done. }
iIntros "!> pPts".
iSplit.
{ iApply (crash_condition_impl_2 with "pPts perLb"). }
iModIntro.
wpc_pures.
{ iApply (crash_condition_impl_2 with "pPts perLb"). }
wpc_bind (Flush _)%E.
iApply wpc_atomic_no_mask.
iSplit.
{ iApply (crash_condition_impl_2 with "pPts perLb"). }
iApply (wp_flush_na with "pPts").
iNext.
iIntros "(pPts & ? & pLb)".
iSplit.
{ iModIntro. iApply (crash_condition_impl_2 with "pPts perLb"). }
iModIntro.
wpc_pures.
{ iApply (crash_condition_impl_2 with "pPts perLb"). }
(* The fence. *)
wpc_bind (FenceSync)%E.
iApply wpc_atomic_no_mask.
iSplit. { iApply (crash_condition_impl_2 with "pPts perLb"). }
iApply wp_fence_sync. do 2 iModIntro.
iSplit. { iApply (crash_condition_impl_2 with "pPts perLb"). }
iModIntro.
iDestruct "pLb" as "#pLb".
wpc_pures.
{ iApply (crash_condition_impl_2 with "pPts perLb"). }
iDestruct (mapsto_na_persist_lb with "pPts pLb") as "pPts".
{ intros [?|?]; lia. }
iApply wpc_atomic_no_mask.
iSplit. {
iApply post_crash_mono;
last iApply (crash_condition_impl' with "pPts pLb").
iIntros "H". iExists _. iFrame "H". naive_solver. }
iApply (wp_store_na _ rr_prot _ _ _ (mk_numbered (n + 1) w) with "[$vPts]").
{ apply last_snoc. }
{ apply numbered_le. lia. }
{ simpl. done. }
iIntros "!> vPts".
iSplit. {
iApply post_crash_mono;
last iApply (crash_condition_impl' with "pPts pLb").
iIntros "H". iExists _. iFrame "H". naive_solver. }
iModIntro.
repeat iExists _.
iSplitPure; first done.
iFrameF "pPts".
iFrameF "pLb".
iFrame "vPts".
Qed.
Lemma RR_recover_spec rv (v w : val) s E :
is_recoverable_RR rv v -∗
WPC RR_recover rv @ s; E
{{ rv2, is_RR rv2 v }}
{{ <PC> is_recoverable_RR rv v }}%I.
Proof.
iNamed 1.
rewrite /RR_recover.
wpc_pures.
{ iApply (crash_condition_impl' with "pPts perLb"). }
wpc_bind (!_NA _)%E.
iApply wpc_atomic_no_mask.
iSplit.
{ iApply (crash_condition_impl' with "pPts perLb"). }
wp_apply (wp_load_na with "[$pPts]").
{ done. }
{ iModIntro. simpl.
iIntros (?) "#H". iFrame "H". rewrite right_id. iApply "H". }
iIntros (?) "(pPts & <-)".
iSplit.
{ iModIntro.
iApply (crash_condition_impl' with "pPts perLb"). }
iModIntro.
wpc_bind (ref_NA _)%E.
iApply wpc_atomic_no_mask.
iSplit. { iApply (crash_condition_impl' with "pPts perLb"). }
wp_apply (wp_alloc_na v (mk_numbered n v) rr_prot); simpl; first done.
iIntros (ℓv') "vPts".
iSplit.
{ iModIntro.
iApply (crash_condition_impl' with "pPts perLb"). }
iModIntro.
wpc_pures.
{ iApply (crash_condition_impl' with "pPts perLb"). }
iModIntro.
iExists _, _, _, [].
iSplitPure; first done.
iFrameF "pPts".
iFrameF "perLb".
iFrame "vPts".
Qed.
End spec.