Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions rocq-brick-libstdcpp/proof/mutex/proof/lock_guard.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ Require Import skylabs.brick.libstdcpp.mutex.spec.mutex.
Require Import skylabs.brick.libstdcpp.mutex.spec.lock_guard.

Require Import skylabs.brick.libstdcpp.mutex.inc_hpp.
Require Import skylabs.brick.libstdcpp.lib.lock_ghost.

Import linearity.

Section with_cpp.
Context `{Σ : cpp_logic, σ : genv}.
Context {HAS_THREADS : HasStdThreads Σ}.
Context `{!lock_ghost.lockG Σ}.

Import lock_guard.

Expand All @@ -17,9 +19,6 @@ Section with_cpp.
Cbn (Learn (learn_eq ==> learn_eq ==> learn_eq ==> fin_at) mutex.R).
Proof. solve_learnable. Qed.

#[global] Instance UNSAFE_token_learn : Cbn (Learn (req_eq ==> learn_eq ==> learn_hints.fin) mutex.token).
Proof. solve_learnable. Qed.

#[local] Hint Resolve fractional.UNSAFE_read_prim_learn : sl_opacity.

Lemma ctor_ok : verify[source] ctor_spec.
Expand Down
5 changes: 3 additions & 2 deletions rocq-brick-libstdcpp/proof/mutex/proof/unique_lock.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ Require Import skylabs.brick.libstdcpp.mutex.spec.prelude.
Require Import skylabs.brick.libstdcpp.mutex.spec.unique_lock.
Require Import skylabs.brick.libstdcpp.mutex.spec.mutex.
Require Import skylabs.brick.libstdcpp.lib.tactics.
Require Import skylabs.brick.libstdcpp.lib.lock_ghost.

NES.Begin unique_lock.
Section with_cpp.
Context `{Σ : cpp_logic} {σ : genv}.
Context `{HAS_THREADS : !HasStdThreads Σ}.
Context `{!lock_ghost.lockG Σ}.

Import R_unfold.

Expand Down Expand Up @@ -43,10 +45,9 @@ NES.Begin unique_lock.
"std::unique_lock<std::mutex>::unique_lock(std::mutex&)".
Proof.
verify_spec; go.
iExists K.
iExists K, q.
(* Time Succeed solve [setoid_rewrite cQp.scale_mut; setoid_rewrite (right_id_L 1%Qp Qp.mul); ego with br_erefl]. *)

iExists _, q.
rewrite cQp.scale_mut (right_id_L 1%Qp Qp.mul).
go with br_erefl.
Qed.
Expand Down
11 changes: 6 additions & 5 deletions rocq-brick-libstdcpp/proof/mutex/spec/lock_guard.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Require Import skylabs.brick.libstdcpp.mutex.spec.mutex.
Require Export skylabs.brick.libstdcpp.runtime.pred.

Require Import skylabs.brick.libstdcpp.mutex.inc_hpp.
Require Import skylabs.brick.libstdcpp.lib.lock_ghost.


Import linearity.
Expand Down Expand Up @@ -47,6 +48,7 @@ Module lock_guard.
Section with_cpp.
Context `{Σ : cpp_logic, σ : genv}.
Context {HAS_THREADS : HasStdThreads Σ}.
Context `{!lock_ghost.lockG Σ}.

#[global] Instance R_learn :
Cbn (Learn (learn_eq ==> any ==> learn_eq ==> learn_hints.fin) lock_guard.R) :=
Expand Down Expand Up @@ -87,20 +89,20 @@ Section with_cpp.
\arg{mp} "m" (Vptr mp)
\persist{thr} current_thread thr
\pre{g q P} mp |-> mutex.R g q$m P
\pre mutex.token g q
\pre lock_ghost.user g thr
\post
this |-> R (mp, g, q) 1$m P **
P ** mutex.locked g thr q
P ** mutex.locked g thr
).

cpp.spec "std::lock_guard<std::mutex>::~lock_guard()" as dtor_spec from source with (
\this this
\pre{mp g q P} this |-> R (mp, g, q) 1$m P
\persist{thr} current_thread thr
\pre mutex.locked g thr q
\pre mutex.locked g thr
\pre ▷P
\post
mutex.token g q **
lock_ghost.user g thr **
mp |-> mutex.R g q$m P
).

Expand All @@ -124,4 +126,3 @@ Section with_cpp.

End with_cpp.
End lock_guard.

55 changes: 29 additions & 26 deletions rocq-brick-libstdcpp/proof/mutex/spec/mutex.v
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Require Export skylabs.brick.libstdcpp.runtime.pred.

Require Import skylabs.brick.libstdcpp.mutex.inc_hpp.
Require Import skylabs.brick.libstdcpp.mutex.requirements.
Require Import skylabs.brick.libstdcpp.lib.lock_ghost.
Export skylabs.brick.libstdcpp.lib.lock_ghost(lockG).

Import linearity.

Expand All @@ -28,20 +30,13 @@ Section with_cpp.
#[global] Declare Instance R_learnable : forall {HAS_THREADS : HasStdThreads Σ} {σ : genv},
Cbn (Learn (learn_eq ==> any ==> learn_eq ==> learn_hints.fin) R).

(** Owning [mutex_token γ 1] proves that the mutex is not locked, and
therefore can be safely destroyed: the standard specifies that calling
[std::mutex::~mutex()] while holding the lock results in undefined behavior.
*)
Parameter token : forall {HAS_THREADS : HasStdThreads Σ} {σ : genv}, gname -> Qp -> mpred.
#[only(fractional,fracvalid,asfractional,timeless)] derive token.

Section with_RepFor.
Import rep.RepFor.
Import RepScheme.

#[global] Instance repfor `{!HasStdThreads Σ} {σ : genv} :
rep.RepFor.C "std::mutex" [ArgType.Constant _; ArgType.CFrac; ArgType.Constant _]
(funI γ q P => R γ q P ∗ pureR (token γ q)) := {}.
(funI γ q P => R γ q P) := {}.
End with_RepFor.


Expand All @@ -65,69 +60,78 @@ Section with_cpp.
>>
*)
Parameter locked : forall {HAS_THREADS : HasStdThreads Σ} {σ : genv},
gname -> thread_idT -> Qp -> mpred.
gname -> thread_idT -> mpred.
#[only(timeless)] derive locked.

(** locked takes a [Qp] but _cannot_ be split. *)
#[only(exclusive)] derive locked.

Context `{!lockG Σ}.

Abbreviation used_threads γ s :=
(lock_ghost.used_threads γ s).

Abbreviation users γ ths :=
(lock_ghost.users γ ths).

Abbreviation user γ th := (users γ {[ th ]}).

Context `{MOD : source ⊧ σ}.
Context {HAS_THREADS : HasStdThreads Σ}.

#[global] Instance locked_learn : Cbn (Learn (req_eq ==> learn_eq ==> learn_eq ==> learn_hints.fin) locked).
#[global] Instance locked_learn : Cbn (Learn (req_eq ==> learn_eq ==> learn_hints.fin) locked).
Proof. solve_learnable. Qed.


cpp.spec "std::mutex::mutex()" as ctor_spec with (
\this this
\pre{P} ▷P
\post Exists g, this |-> R g 1$m P ** token g 1).
\post Exists g, this |-> R g 1$m P ** used_threads g ).

cpp.spec "std::mutex::~mutex()" as dtor_spec with (
\this this
\pre{g P} this |-> R g 1$m P ** token g 1
\pre{g P} this |-> R g 1$m P ** used_threads g
\post P).

(* "Inline" version of these specs. *)
cpp.spec "std::mutex::lock()" as lock_spec_alt with (
\this this
\prepost{q P g} this |-> R g q P
\persist{thr} current_thread thr
\pre{q'} token g q'
\post P ** locked g thr q').
\pre user g thr
\post P ** locked g thr).

Definition do_lock (lk : gname * mpred) (K: mpred) : mpred :=
let g := lk.1 in
let P := lk.2 in
q thr, current_thread thr ∗ token g q
∃ thr, current_thread thr ∗ user g thr
(* TODO readd *)
(* ▷ *)
(locked g thr q ** P -* K).
(locked g thr ** P -* K).
#[global] Arguments do_lock /.

cpp.spec "std::mutex::unlock()" as unlock_spec_alt with (
\this this
\prepost{q P g} this |-> R g q P
\persist{thr} current_thread thr
\pre{q'} locked g thr q'
\pre locked g thr
\pre ▷P
\post token g q').
\post user g thr).

Definition do_unlock (lk : gname * mpred) (Q : mpred) : mpred :=
let g := lk.1 in
let P := lk.2 in
Exists q thr, current_thread thr ** locked g thr q ** ▷P **
Exists thr, current_thread thr ** locked g thr ** ▷P **
(* TODO readd *)
(* ▷ *)
(token g q -* Q).
(user g thr -* Q).
#[global] Arguments do_unlock /.

cpp.spec "std::mutex::try_lock()" as try_lock_spec_alt with (
\this this
\prepost{q P g} this |-> R g q P
\persist{th} current_thread th
\pre{q'} token g q'
\post{b}[Vbool b] if b then P ** locked g th q' else token g q').
\pre user g th
\post{b}[Vbool b] if b then P ** locked g th else user g th).

(* Obtain same specs from (Basic)Lockable. *)
(** <<std::mutex>> implements [BasicLockable] *)
Expand All @@ -146,9 +150,9 @@ Section with_cpp.
Definition do_try_lock (lk : gname * mpred) (Q : bool -> mpred) : mpred :=
let g := lk.1 in
let P := lk.2 in
q thr, current_thread thr ∗ token g q
∃ thr, current_thread thr ∗ user g thr
∀ b : bool,
(if b then P ** locked g thr q else token g q) -∗ Q b.
(if b then P ** locked g thr else user g thr) -∗ Q b.
#[global] Arguments do_try_lock /.

#[global,program] Instance mutex_lockable : Lockable (T:=T) "std::mutex" (λ q γP, R γP.1 q γP.2) :=
Expand All @@ -173,4 +177,3 @@ Section with_cpp.
Qed.
End with_cpp.
End mutex.

20 changes: 11 additions & 9 deletions rocq-brick-libstdcpp/proof/mutex/spec/scoped_lock.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Require Import skylabs.brick.libstdcpp.mutex.inc_hpp.

Require Export skylabs.brick.libstdcpp.runtime.pred.
Require Import skylabs.brick.libstdcpp.mutex.spec.mutex.
Require Import skylabs.brick.libstdcpp.lib.lock_ghost.

Module scoped_lock.
Section with_cpp.
Expand All @@ -17,6 +18,7 @@ Module scoped_lock.
Section with_threads.
Context {σ : genv}.
Context `{HAS_THREADS : !HasStdThreads Σ}.
Context `{!lock_ghost.lockG Σ}.

#[global] Instance: LearnEqF1 R := ltac:(solve_learnable).

Expand All @@ -25,17 +27,17 @@ Module scoped_lock.
(* "std::scoped_lock<std::mutex, std::mutex>::scoped_lock(std::mutex&, std::mutex&)" *)
as ctor_spec from source with (
\this this
\persist{thr} current_thread thr
\arg{mp1} "" (Vptr mp1)
\pre{g1 q1 P1} mp1 |-> mutex.R g1 q1$m P1
\pre mutex.token g1 q1
\pre lock_ghost.user g1 thr
\arg{mp2} "" (Vptr mp2)
\pre{g2 q2 P2} mp2 |-> mutex.R g2 q2$m P2
\pre mutex.token g2 q2
\persist{thr} current_thread thr
\pre lock_ghost.user g2 thr
\post
this |-> R 1$m [ (mp1, g1, q1, P1); (mp2, g2, q2, P2)] **
P1 ** mutex.locked g1 thr q1 **
P2 ** mutex.locked g2 thr q2
P1 ** mutex.locked g1 thr **
P2 ** mutex.locked g2 thr
).

cpp.spec "std::scoped_lock<...<std::mutex, std::mutex>>::~scoped_lock()"
Expand All @@ -50,11 +52,11 @@ Module scoped_lock.
this |-> R 1$m [ (mp1, g1, q1, P1); (mp2, g2, q2, P2)]
\pre |> P1
\pre |> P2
\pre mutex.locked g1 thr q1
\pre mutex.locked g2 thr q2
\pre mutex.locked g1 thr
\pre mutex.locked g2 thr
\post
mp1 |-> mutex.R g1 q1$m P1 ** mutex.token g1 q1 **
mp2 |-> mutex.R g2 q2$m P2 ** mutex.token g2 q2
mp1 |-> mutex.R g1 q1$m P1 ** lock_ghost.user g1 thr **
mp2 |-> mutex.R g2 q2$m P2 ** lock_ghost.user g2 thr
).
End with_threads.
End with_cpp.
Expand Down
Loading