Commit 54668a87 authored by Dan Frumin's avatar Dan Frumin
Browse files

Merge branch 'flock2'

parents 1c528f9b 92e9852f
......@@ -3,6 +3,7 @@
theories/lib/list.v
theories/lib/mset.v
theories/lib/spin_lock.v
theories/lib/flock.v
theories/lib/locking_heap.v
theories/lib/U.v
......
......@@ -2,6 +2,7 @@ From iris.heap_lang Require Export proofmode notation.
From iris.heap_lang Require Import adequacy spin_lock assert par.
From iris.algebra Require Import frac.
From iris_c.lib Require Import mset flock locking_heap.
From iris.bi Require Import fractional.
(* M A := ref (list loc) → Mutex → A *)
......@@ -23,7 +24,10 @@ Notation "x ;;ᶜ z" := (a_bind (λ: <>, z) x)%E
Definition a_run : val := λ: "x",
let: "env" := mset_create #() in
let: "l" := newlock #() in
"x" "env" "l".
let: "v" := "x" "env" "l"
in "v". (* TODO: we have a dummy step here :(
but potentially we would have a free(l) operation here
*)
(* M A → M A *)
Definition a_atomic : val := λ: "x" "env" "l",
......@@ -67,13 +71,16 @@ Section a_wp.
full_locking_heap σ
correct_locks X (locked_locs σ))%I.
Definition flock_resources (γ : flock_name) (I : gmap prop_id (iProp Σ * frac)) :=
([ map] i p I, flock_res γ i p.1 p.2)%I.
Definition awp (e : expr)
(R : iProp Σ) (Φ : val iProp Σ) : iProp Σ :=
tc_opaque (WP e {{ ev, (γ : flock_name) (π : frac) (env : val) (l : val),
tc_opaque (WP e {{ ev, (γ : flock_name) (env : val) (l : val) (I : gmap prop_id (iProp Σ * frac)),
is_flock amonadN γ l -
flock_res γ (env_inv env R) -
unflocked γ π -
WP ev env l {{ v, Φ v unflocked γ π }}
flock_resources γ I -
(([ map] p I, p.1) (env_inv env R)) -
WP ev env l {{ v, Φ v flock_resources γ I }}
}})%I.
Global Instance elim_bupd_awp p e Φ :
......@@ -120,19 +127,29 @@ Section a_wp_rules.
Lemma awp_insert_res e Φ R1 R2 :
R1 -
AWP e @ (R1 R2) {{ Φ }} -
AWP e @ (R1 R2) {{ v, R1 - Φ v }} -
AWP e @ R2 {{ Φ }}.
Proof.
iIntros "HR1 Hawp". rewrite /awp /=.
iApply (wp_wand with "Hawp").
iIntros (v) "HΦ".
iIntros (γ π env l) "#Hflock Hres Hunfl".
iMod (flock_res_insert_unflocked with "Hflock Hres Hunfl HR1")
as "(#Hres & Hunfl)"; first done.
iApply ("HΦ" with "Hflock [Hres] Hunfl").
rewrite (comm ()%I R1 R2).
rewrite (assoc ()%I _ R2 R1).
by iFrame "Hres".
iIntros (γ env l I) "#Hflock Hres #Heq".
iMod (flock_res_single_alloc _ (dom (gset prop_id) I) with "Hflock HR1") as (j) "[% Hres']"; first done.
pose (I' := <[j:= (R1,1%Qp)]>I).
assert (I !! j = None) by by eapply not_elem_of_dom.
iSpecialize ("HΦ" $! _ env l I' with "Hflock [Hres Hres'] []").
{ rewrite /flock_resources /I'.
rewrite big_sepM_insert; last done. iFrame. }
{ rewrite big_sepM_insert; last done. simpl. iRewrite "Heq".
rewrite (assoc _ R1 _ R2).
rewrite (comm _ R1 (env_inv env)).
rewrite -(assoc _ _ R1 R2). done. }
iApply wp_fupd.
iApply (wp_wand with "HΦ").
iIntros (w) "[HΦ HI]". rewrite /flock_resources /I'.
rewrite big_sepM_insert /=; last done. iDestruct "HI" as "[HR1 $]".
iMod (flock_res_single_dealloc with "Hflock HR1") as (R') "[HR' Heq']"; first done.
iApply "HΦ". iModIntro. do 2 iNext. by iRewrite "Heq'".
Qed.
Lemma awp_wand e (Φ Ψ : val iProp Σ) R :
......@@ -143,8 +160,8 @@ Section a_wp_rules.
iIntros "HAWP Hv". rewrite /awp /=.
iApply (wp_wand with "HAWP").
iIntros (v) "HΦ".
iIntros (γ π env l) "#Hflock #Hres Hunfl".
iApply (wp_wand with "[HΦ Hunfl]"); first by iApply "HΦ".
iIntros (γ env l I) "#Hflock Hres #Heq".
iApply (wp_wand with "[HΦ Hres]"). iApply ("HΦ" with "Hflock Hres Heq").
iIntros (w) "[HΦ $]". by iApply "Hv".
Qed.
......@@ -163,7 +180,7 @@ Section a_wp_rules.
Proof.
iIntros "Hwp". rewrite /awp /a_ret /=. wp_apply (wp_wand with "Hwp").
iIntros (v) "HΦ". wp_lam.
iIntros (γ π env l) "#Hlock #Hres Hunfl". do 2 wp_lam. iFrame.
iIntros (γ env l I) "#Hlock Hres #Heq". do 2 wp_lam. iFrame.
Qed.
Lemma awp_bind (f e : expr) R Φ :
......@@ -173,53 +190,65 @@ Section a_wp_rules.
Proof.
iIntros ([fv <-]) "Hwp". rewrite /awp /a_bind /=. wp_lam. wp_bind e.
iApply (wp_wand with "Hwp"). iIntros (ev) "Hwp". wp_lam.
iIntros (γ π env l) "#Hlock #Hres Hunfl". do 2 wp_lam. wp_bind (ev env l).
iApply (wp_wand with "[Hwp Hunfl]"); first by iApply "Hwp".
iIntros (w) "[Hwp Hunfl]". wp_let. wp_apply (wp_wand with "Hwp").
iIntros (v) "H". by iApply ("H" with "[$]").
iIntros (γ env l I) "#Hflock Hres #Heq". do 2 wp_lam. wp_bind (ev env l).
iApply (wp_wand with "[Hwp Hres]"). iApply ("Hwp" with "Hflock Hres Heq").
iIntros (w) "[Hwp Hres]". wp_let. wp_apply (wp_wand with "Hwp").
iIntros (v) "H". iApply ("H" with "Hflock Hres Heq").
Qed.
Lemma awp_atomic (e : expr) (ev : val) R Φ :
IntoVal e ev
(R - R', R' AWP (ev #()) @ R' {{ w, R' - R Φ w }}) -
AWP (a_atomic e) @ R {{ Φ }}.
(R - R', R' AWP ev #() @ R' {{ w, R' - R Φ w }}) -
AWP a_atomic e @ R {{ Φ }}.
Proof.
iIntros (<-) "Hwp". rewrite /awp /a_atomic /=. wp_lam.
iIntros (γ π env l) "#Hlock1 #Hres Hunfl1". do 2 wp_let.
iIntros (γ env l I) "#Hlock1 Hres #Heq1". do 2 wp_let.
wp_apply (acquire_cancel_spec with "[$]").
iIntros (f) "([Henv HR] & Hcl)". wp_seq.
iDestruct ("Hwp" with "HR") as (R') "[HR' Hwp]".
iIntros "[HI Hcl]". iRewrite "Heq1" in "HI".
iDestruct "HI" as "[Henv HR]".
iDestruct ("Hwp" with "HR") as (Q) "[HQ Hwp]".
wp_seq.
wp_apply (newlock_cancel_spec amonadN); first done.
iIntros (k γ') "[#Hlock2 Hunfl2]". wp_let.
iMod (flock_res_alloc_unflocked _ _ _ _ (env_inv env R')%I
with "Hlock2 Hunfl2 [$Henv $HR']") as "[#Hres2 Hunfl2]"; first done.
wp_apply (wp_wand with "Hwp"); iIntros (ev') "Hwp". wp_bind (ev' _ _).
iApply (wp_wand with "[Hwp Hunfl2]"); first by iApply "Hwp".
iIntros (w) "[HR Hunfl2]".
iMod (cancel_lock with "Hlock2 Hres2 Hunfl2") as "[Henv HR']"; first done.
iIntros (k γ') "#Hlock2".
iMod (flock_res_single_alloc _ (dom (gset prop_id) I) _ _ (env_inv env Q)%I
with "Hlock2 [$Henv $HQ]") as (i') "[% Hres]"; first done.
wp_let.
iDestruct ("HR" with "HR'") as "[HR HΦ]".
wp_apply (release_cancel_spec with "[$Hlock1 Hcl Henv HR]").
{ iApply "Hcl". by iNext; iFrame. }
iIntros "Hunfl1". wp_seq. iFrame.
wp_apply (wp_wand with "Hwp"); iIntros (ev') "Hwp". wp_bind (ev' _ _).
iApply (wp_wand with "[Hwp Hres]").
- iApply ("Hwp" $! _ _ _ {[i' := ((env_inv env Q)%I,1%Qp)]} with "Hlock2 [Hres] []").
+ rewrite /flock_resources big_sepM_singleton //.
+ rewrite big_sepM_singleton //.
- iIntros (w) "[HR Hres]".
rewrite /flock_resources big_sepM_singleton /=.
iMod (flock_res_single_dealloc with "Hlock2 Hres") as (Q') "[HQ' #Heq2]"; first done.
wp_let.
iAssert ( (env_inv env Q))%I with "[HQ']" as "[Henv HQ]".
{ iNext. by iRewrite "Heq2". }
iDestruct ("HR" with "HQ") as "[HR HΦ]".
iMod ("Hcl" with "[HR Henv]") as "[Hflocked Hres]".
{ iNext. iRewrite "Heq1". iFrame. }
wp_apply (release_cancel_spec with "[$Hlock1 $Hflocked]").
iIntros "_". wp_seq. iFrame.
Qed.
Lemma awp_atomic_env (e : expr) (ev : val) R Φ :
IntoVal e ev
( env, env_inv env - R -
WP ev env {{ w, env_inv env R Φ w }}) -
WP ev env {{ w, env_inv env R Φ w }}) -
AWP (a_atomic_env e) @ R {{ Φ }}.
Proof.
iIntros (<-) "Hwp". rewrite /awp /a_atomic_env /=. wp_lam.
iIntros (γ π env l) "#Hlock #Hres Hunfl". do 2 wp_lam.
iIntros (γ env l I) "#Hlock Hres #Heq". do 2 wp_lam.
wp_apply (acquire_cancel_spec with "[$]").
iIntros (f) "([Henv HR] & Hcl)". wp_seq.
iIntros "[HI Hcl]". iRewrite "Heq" in "HI".
iDestruct "HI" as "[Henv HR]".
iDestruct ("Hwp" with "Henv HR") as "Hwp".
wp_apply (wp_wand with "Hwp").
wp_seq. wp_apply (wp_wand with "Hwp").
iIntros (w) "[Henv [HR HΦ]]". wp_let.
wp_apply (release_cancel_spec with "[$Hlock Hcl Henv HR]").
{ iApply "Hcl". by iNext; iFrame. }
iIntros "Hunfl". wp_seq. iFrame.
iRewrite "Heq" in "Hcl".
iMod ("Hcl" with "[$HR $Henv]") as "[Hflocked Hres]".
wp_apply (release_cancel_spec with "[$Hlock $Hflocked]").
iIntros "_". wp_seq. iFrame.
Qed.
Lemma awp_par (Ψ1 Ψ2 : val iProp Σ) e1 e2 R (Φ : val iProp Σ) :
......@@ -233,13 +262,27 @@ Section a_wp_rules.
iIntros (ev1) "Hwp1". wp_lam.
wp_bind e2. iApply (wp_wand with "Hwp2").
iIntros (ev2) "Hwp2". wp_lam.
iIntros (γ π env l) "#Hlock #Hres [Hunfl1 Hunfl2]". do 2 wp_lam.
iApply (par_spec (λ v, Ψ1 v unflocked _ (π/2))%I
(λ v, Ψ2 v unflocked _ (π/2))%I
with "[Hwp1 Hunfl1] [Hwp2 Hunfl2]").
- wp_lam. iApply ("Hwp1" with "Hlock Hres Hunfl1").
- wp_lam. iApply ("Hwp2" with "Hlock Hres Hunfl2").
- iNext. iIntros (w1 w2) "[[HΨ1 $] [HΨ2 $]]".
iIntros (γ env l I) "#Hlock Hres #Heq". do 2 wp_lam.
pose (I' := fmap (λ x, (x.1, (x.2/2)%Qp)) I).
iAssert (flock_resources γ I' flock_resources γ I')%I with "[Hres]" as "[Hres1 Hres2]".
{ rewrite /flock_resources -big_sepM_sepM.
rewrite /I' big_sepM_fmap /=.
iApply (big_sepM_mono with "Hres"). iIntros (k x Hk). simpl.
by rewrite -flock_res_op Qp_div_2. }
iApply (par_spec (λ v, Ψ1 v flock_resources γ I')%I
(λ v, Ψ2 v flock_resources γ I')%I
with "[Hwp1 Hres1] [Hwp2 Hres2]").
- wp_lam. iApply ("Hwp1" with "Hlock Hres1").
by rewrite /I' big_sepM_fmap /=.
- wp_lam. iApply ("Hwp2" with "Hlock Hres2").
by rewrite /I' big_sepM_fmap /=.
- iNext. iIntros (w1 w2) "[[HΨ1 Hres1] [HΨ2 Hres2]]".
iAssert (flock_resources γ I)%I with "[Hres1 Hres2]" as "$".
{ iCombine "Hres1 Hres2" as "Hres".
rewrite /flock_resources -big_sepM_sepM.
rewrite /I' big_sepM_fmap /=.
iApply (big_sepM_mono with "Hres"). iIntros (k x Hk). simpl.
by rewrite -flock_res_op Qp_div_2. }
iApply ("HΦ" with "[$] [$]").
Qed.
End a_wp_rules.
......@@ -249,7 +292,7 @@ Section a_wp_run.
Lemma awp_run (e : expr) R Φ :
AsVal e
R - ( `{amonadG Σ}, AWP e @ R {{ w, R ={}= Φ w }}) -
R - ( `{amonadG Σ}, AWP e @ R {{ w, R ={}= Φ w }}) -
WP a_run e {{ Φ }}.
Proof.
iIntros ([ev <-]) "HR Hwp". rewrite /awp /a_run /=. wp_let.
......@@ -258,16 +301,22 @@ Section a_wp_run.
iMod locking_heap_init as (?) "Hσ".
pose (amg := AMonadG Σ _ _ _ _).
wp_apply (newlock_cancel_spec amonadN); first done.
iIntros (k γ') "[#Hlock Hunfl]". wp_let. rewrite- wp_fupd.
iMod (flock_res_alloc_unflocked _ _ _ _ (env_inv env R)%I
with "Hlock Hunfl [Henv Hσ $HR]") as "[#Hres Hunfl]"; first done.
iIntros (k γ') "#Hlock". rewrite- wp_fupd.
iMod (flock_res_single_alloc _ _ _ (env_inv env R)%I
with "Hlock [Henv Hσ $HR]") as (i) "[_ Hres]"; first done.
{ iNext. iExists , . iFrame. eauto. }
iSpecialize ("Hwp" $! amg).
wp_apply (wp_wand with "Hwp"). iIntros (v') "Hwp".
iApply (wp_wand with "[Hwp Hunfl]"); first by iApply "Hwp".
iIntros (w) "[HΦ Hunfl]".
iMod (cancel_lock with "Hlock Hres Hunfl") as "[HEnv HR]"; first done.
by iApply "HΦ".
iMod (wp_value_inv with "Hwp") as "Hwp".
wp_let. wp_bind (ev env k).
iApply (wp_wand with "[Hwp Hres]").
- iApply ("Hwp" $! _ _ _ {[i := ((env_inv env R)%I,1%Qp)]} with "Hlock [Hres] []").
+ rewrite /flock_resources big_sepM_singleton //.
+ rewrite big_sepM_singleton //.
- iIntros (w) "[HΦ Hres]".
rewrite /flock_resources big_sepM_singleton /=.
iMod (flock_res_single_dealloc with "Hlock Hres") as (R') "[HR' #Heq]"; first done.
wp_let.
iApply "HΦ". iNext. iRewrite -"Heq" in "HR'". iDestruct "HR'" as "[_ $]".
Qed.
End a_wp_run.
......
......@@ -193,8 +193,7 @@ Section proofs.
assert (#l X).
{ unfold correct_locks in *. intros Hx. apply Hl.
destruct (Hlocks _ Hx) as [l' [? Hl']]. by simplify_eq/=. }
wp_let.
wp_apply wp_assert.
wp_lam. wp_apply wp_assert.
wp_apply (mset_member_spec with "HX").
iIntros "Henv /=". case_decide; first by exfalso. simpl.
wp_op. iSplit; eauto. iNext. wp_seq.
......@@ -262,7 +261,7 @@ Section proofs.
rewrite {2}/env_inv.
iDestruct "Henv" as (X σ) "(HX & Hσ & Hlocks)".
iDestruct "Hlocks" as %Hlocks.
wp_let. iApply (mset_clear_spec with "HX").
wp_lam. iApply (mset_clear_spec with "HX").
iNext. iIntros "HX".
iDestruct "HΦ" as (us) "[Hus HΦ]".
clear Hlocks.
......@@ -363,7 +362,7 @@ Section proofs.
iSpecialize ("Hfa" with "HΨ").
iModIntro.
awp_let.
iApply awp_atomic. iIntros "HR".
iApply awp_atomic. iNext. iIntros "HR".
iDestruct ("Hfa" with "HR") as (R') "[HR' Hfa]".
iExists R'. iFrame. by awp_let.
Qed.
......
This diff is collapsed.
From iris.program_logic Require Export weakestpre.
From iris.heap_lang Require Export lang.
From iris.proofmode Require Import tactics.
From iris.heap_lang Require Import proofmode notation.
From iris.algebra Require Import excl.
From iris.heap_lang.lib Require Import lock.
Set Default Proof Using "Type".
Definition newlock : val := λ: <>, ref #false.
Definition try_acquire : val := λ: "l", CAS "l" #false #true.
Definition acquire : val :=
rec: "acquire" "l" := if: try_acquire "l" then #() else "acquire" "l".
Definition release : val := λ: "l", "l" <- #false.
(** The CMRA we need. *)
(* Not bundling heapG, as it may be shared with other users. *)
Class lockG Σ := LockG { lock_tokG :> inG Σ (exclR unitC) }.
Definition lockΣ : gFunctors := #[GFunctor (exclR unitC)].
Instance subG_lockΣ {Σ} : subG lockΣ Σ lockG Σ.
Proof. solve_inG. Qed.
Section proof.
Context `{!heapG Σ, !lockG Σ} (N : namespace).
Definition lock_inv (γ : gname) (l : loc) (R : iProp Σ) : iProp Σ :=
( b : bool, l #b if b then True else own γ (Excl ()) R)%I.
Definition is_lock (γ : gname) (lk : val) (R : iProp Σ) : iProp Σ :=
( l: loc, lk = #l inv N (lock_inv γ l R))%I.
Definition locked (γ : gname) : iProp Σ := own γ (Excl ()).
Lemma locked_exclusive (γ : gname) : locked γ - locked γ - False.
Proof. iIntros "H1 H2". by iDestruct (own_valid_2 with "H1 H2") as %?. Qed.
Global Instance lock_inv_ne γ l : NonExpansive (lock_inv γ l).
Proof. solve_proper. Qed.
Global Instance is_lock_ne γ l : NonExpansive (is_lock γ l).
Proof. solve_proper. Qed.
(** The main proofs. *)
Global Instance is_lock_persistent γ l R : Persistent (is_lock γ l R).
Proof. apply _. Qed.
Global Instance locked_timeless γ : Timeless (locked γ).
Proof. apply _. Qed.
Lemma newlock_spec (R : iProp Σ):
{{{ R }}} newlock #() {{{ lk γ, RET lk; is_lock γ lk R }}}.
Proof.
iIntros (Φ) "HR HΦ". rewrite -wp_fupd /newlock /=.
wp_lam. wp_alloc l as "Hl".
iMod (own_alloc (Excl ())) as (γ) "Hγ"; first done.
iMod (inv_alloc N _ (lock_inv γ l R) with "[-HΦ]") as "#?".
{ iIntros "!>". iExists false. by iFrame. }
iModIntro. iApply "HΦ". iExists l. eauto.
Qed.
Lemma try_acquire_spec γ lk R :
{{{ is_lock γ lk R }}} try_acquire lk
{{{ b, RET #b; if b is true then locked γ R else True }}}.
Proof.
iIntros (Φ) "#Hl HΦ". iDestruct "Hl" as (l ->) "#Hinv".
wp_rec. iInv N as ([]) "[Hl HR]" "Hclose".
- wp_cas_fail. iMod ("Hclose" with "[Hl]"); first (iNext; iExists true; eauto).
iModIntro. iApply ("HΦ" $! false). done.
- wp_cas_suc. iDestruct "HR" as "[Hγ HR]".
iMod ("Hclose" with "[Hl]"); first (iNext; iExists true; eauto).
iModIntro. rewrite /locked. by iApply ("HΦ" $! true with "[$Hγ $HR]").
Qed.
Lemma acquire_spec γ lk R :
( Φ,
is_lock γ lk R - (locked γ R - |={}=> Φ #()%V) - WP acquire lk {{ Φ }})%I.
Proof.
iIntros (Φ) "#Hl HΦ". iLöb as "IH". wp_rec.
wp_apply (try_acquire_spec with "Hl"). iIntros ([]).
- iIntros "[Hlked HR]". iMod ("HΦ" with "[$Hlked $HR]"). wp_if. done.
- iIntros "_". wp_if. iApply ("IH" with "[HΦ]"). auto.
Qed.
Lemma release_spec γ lk R :
{{{ is_lock γ lk R locked γ R }}} release lk {{{ RET #(); True }}}.
Proof.
iIntros (Φ) "(Hlock & Hlocked & HR) HΦ".
iDestruct "Hlock" as (l ->) "#Hinv".
rewrite /release /=. wp_let. iInv N as (b) "[Hl _]" "Hclose".
wp_store. iApply "HΦ". iApply "Hclose". iNext. iExists false. by iFrame.
Qed.
End proof.
Typeclasses Opaque is_lock locked.
......@@ -123,18 +123,17 @@ Section test.
Lemma invoke_test (l : loc) (z0 z1 z2: Z) R :
l C #z0 -
awp (a_bin_op PlusOp
(a_invoke assignF (a_par (a_ret #l) (a_ret #z1)))
(a_invoke assignF (a_par (a_ret #l) (a_ret #z2)))) R
(λ v, v = #(z1 + z2))%I.
AWP (a_invoke assignF (l ||| z1))
+ (a_invoke assignF (l ||| z2)) @ R
{{ v, v = #(z1 + z2) ( w, l C w) }}.
Proof.
iIntros "Hl".
iApply (awp_insert_res _ _ ( v, l C v)%I with "[Hl]").
{ iNext. by iExists #z0. }
iApply a_bin_op_spec.
- iApply invoke_assignF_2.
- iApply invoke_assignF_2.
- iIntros (? ? -> ->). iExists #(z1+z2). eauto.
- iApply (invoke_assignF_2 l #z1).
- iApply (invoke_assignF_2 l #z2). (* TODO: we have to give z1/z2 explicitly here *)
- iIntros (? ? -> ->). iExists #(z1+z2). iSplit; eauto.
Qed.
End test.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment