diff --git a/_CoqProject b/_CoqProject index e11d05278fdf979e417560538971829fed6eb1c2..de45759499bb4f9d0b0a36c1cc51d145a0da8f23 100644 --- a/_CoqProject +++ b/_CoqProject @@ -54,6 +54,7 @@ theories/typing/lib/cell.v theories/typing/lib/spawn.v theories/typing/lib/rc/rc.v theories/typing/lib/rc/weak.v +theories/typing/lib/mutex/mutex.v theories/typing/lib/refcell/refcell.v theories/typing/lib/refcell/ref.v theories/typing/lib/refcell/refmut.v diff --git a/theories/lang/lib/lock.v b/theories/lang/lib/lock.v index b85d05f1599b9fd90224774969d47837ad8ba8f7..adcdcffbd5056639c4f7a519a1a2103abc916b73 100644 --- a/theories/lang/lib/lock.v +++ b/theories/lang/lib/lock.v @@ -45,21 +45,20 @@ Section proof. Qed. (** The main proofs. *) - Lemma lock_proto_create (E : coPset) (R : iProp Σ) l (b : bool) : - l ↦ #b -∗ (if b then True else ▷ R) ={E}=∗ ∃ γ, ▷ lock_proto γ l R. + Lemma lock_proto_create (R : iProp Σ) l (b : bool) : + l ↦ #b -∗ (if b then True else ▷ R) ==∗ ∃ γ, ▷ lock_proto γ l R. Proof. iIntros "Hl HR". iMod (own_alloc (Excl ())) as (γ) "Hγ"; first done. iExists _, _. iFrame "Hl". destruct b; first done. by iFrame. Qed. - Lemma lock_proto_destroy E γ l R : - ↑N ⊆ E → - ▷ lock_proto γ l R ={E}=∗ ∃ (b : bool), l ↦ #b ∗ if b then True else ▷ R. + Lemma lock_proto_destroy γ l R : + lock_proto γ l R -∗ ∃ (b : bool), l ↦ #b ∗ if b then True else R. Proof. - iIntros (?) "Hlck". iDestruct "Hlck" as (b) "[>Hl HR]". + iIntros "Hlck". iDestruct "Hlck" as (b) "[Hl HR]". iExists b. iFrame "Hl". destruct b; first done. - iDestruct "HR" as "[_ $]". done. + iDestruct "HR" as "[_ $]". Qed. (* At this point, it'd be really nice to have some sugar for symmetric diff --git a/theories/typing/lib/mutex/mutex.v b/theories/typing/lib/mutex/mutex.v new file mode 100644 index 0000000000000000000000000000000000000000..1030c87273c87574b8c250bd686e437155b04f78 --- /dev/null +++ b/theories/typing/lib/mutex/mutex.v @@ -0,0 +1,86 @@ +From Coq.QArith Require Import Qcanon. +From iris.proofmode Require Import tactics. +From iris.algebra Require Import auth csum frac agree. +From iris.base_logic Require Import big_op. +From lrust.lang.lib Require Import memcpy lock. +From lrust.lifetime Require Import na_borrow. +From lrust.typing Require Export type. +From lrust.typing Require Import typing option. +Set Default Proof Using "Type". + +Definition mutexN := lrustN .@ "mutex". + +(* This type is an experiment in defining a Rust type on top of a non-typesysten-specific + interface, like the one provided by lang.lib.lock. + It turns out that we need an accessor-based spec for this purpose, so that + we can put the protocol into shared borrows. Cancellable invariants + don't work because their cancelling view shift has a non-empty mask, + and it would have to be executed in the consequence view shift of + a borrow. +*) + +Section mutex. + Context `{!typeG Σ, !lockG Σ}. + + (* + pub struct Mutex<T: ?Sized> { + // Note that this mutex is in a *box*, not inlined into the struct itself. + // Once a native mutex has been used once, its address can never change (it + // can't be moved). This mutex type can be safely moved at any time, so to + // ensure that the native mutex is used correctly we box the inner lock to + // give it a constant address. + inner: Box<sys::Mutex>, + poison: poison::Flag, + data: UnsafeCell<T>, + } + *) + + Program Definition mutex (ty : type) := + {| ty_size := 1 + ty.(ty_size); + ty_own tid vl := + match vl return _ with + | #(LitInt z) :: vl' => + ⌜∃ b, z = Z_of_bool b⌠∗ ty.(ty_own) tid vl' + | _ => False end; + ty_shr κ tid l := + ∃ γ κ', + &shr{κ, mutexN} (lock_proto γ l (&{κ'} shift_loc l 1 ↦∗: ty.(ty_own) tid)) ∗ κ ⊑ κ' + |}%I. + Next Obligation. + iIntros (??[|[[]|]]); try iIntros "[]". rewrite ty_size_eq. + iIntros "[_ %] !% /=". congruence. + Qed. + Next Obligation. + iIntros (ty E κ l tid q ?) "#LFT Hbor Htok". + iMod (bor_acc_cons with "LFT Hbor Htok") as "[H Hclose]"; first done. + iDestruct "H" as ([|[[| |n]|]vl]) "[H↦ H]"; try iDestruct "H" as ">[]". + rewrite heap_mapsto_vec_cons. iDestruct "H↦" as ">[Hl H↦]". + iDestruct "H" as "[>EQ Hown]". iDestruct "EQ" as %[b ->]. + (* We need to turn the ohne borrow into two, so we close it -- and then + we open one of them again. *) + iMod ("Hclose" $! ((∃ b, l ↦ #(Z_of_bool b)) ∗ (shift_loc l 1 ↦∗: ty_own ty tid))%I + with "[] [Hl H↦ Hown]") as "[Hbor Htok]". + { clear. iNext. iIntros "[Hl Hown] !>". iNext. iDestruct "Hl" as (b) "Hl". + iDestruct "Hown" as (vl) "[H↦ Hown]". iExists (#(Z_of_bool b) :: vl). + rewrite heap_mapsto_vec_cons. iFrame. iPureIntro. eauto. } + { iNext. iSplitL "Hl"; first by eauto. + iExists vl. iFrame. } + clear b vl. iMod (bor_sep with "LFT Hbor") as "[Hl Hbor]"; first done. + iMod (bor_acc_cons with "LFT Hl Htok") as "[>Hl Hclose]"; first done. + iDestruct "Hl" as (b) "Hl". + iMod (lock_proto_create with "Hl [Hbor]") as (γ) "Hproto". + { destruct b; last by iExact "Hbor". done. } + iMod ("Hclose" with "[] Hproto") as "[Hl Htok]". + { clear b. iIntros "!> Hproto !>". iDestruct (lock_proto_destroy with "Hproto") as (b) "[Hl _]". + iNext. eauto with iFrame. } + iFrame "Htok". iExists γ, κ. + iMod (bor_share with "Hl") as "$"; [solve_ndisj..|]. + iApply lft_incl_refl. + Qed. + Next Obligation. + iIntros (ty κ κ' tid l) "#Hincl H". + iDestruct "H" as (γ κ'') "(#Hlck & #Hlft)". + iExists _, _. iSplit; first by iApply shr_bor_shorten. + iApply lft_incl_trans; done. + Qed. +End mutex.