Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
E
examples
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
2
Issues
2
List
Boards
Labels
Milestones
Merge Requests
3
Merge Requests
3
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Iris
examples
Commits
955aa2d2
Commit
955aa2d2
authored
Apr 23, 2018
by
Aleš Bizjak
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add more examples from the lecture notes.
parent
e146b872
Changes
9
Expand all
Hide whitespace changes
Inline
Sidebyside
Showing
9 changed files
with
1847 additions
and
0 deletions
+1847
0
_CoqProject
_CoqProject
+8
0
theories/lecture_notes/ccounter.v
theories/lecture_notes/ccounter.v
+131
0
theories/lecture_notes/lists.v
theories/lecture_notes/lists.v
+506
0
theories/lecture_notes/lists_guarded.v
theories/lecture_notes/lists_guarded.v
+88
0
theories/lecture_notes/lock.v
theories/lecture_notes/lock.v
+132
0
theories/lecture_notes/lock_unary_spec.v
theories/lecture_notes/lock_unary_spec.v
+245
0
theories/lecture_notes/modular_incr.v
theories/lecture_notes/modular_incr.v
+290
0
theories/lecture_notes/recursion_through_the_store.v
theories/lecture_notes/recursion_through_the_store.v
+214
0
theories/lecture_notes/stack.v
theories/lecture_notes/stack.v
+233
0
No files found.
_CoqProject
View file @
955aa2d2
...
@@ 9,6 +9,14 @@ theories/barrier/example_joining_existentials.v
...
@@ 9,6 +9,14 @@ theories/barrier/example_joining_existentials.v
theories/lecture_notes/coq_intro_example_1.v
theories/lecture_notes/coq_intro_example_1.v
theories/lecture_notes/coq_intro_example_2.v
theories/lecture_notes/coq_intro_example_2.v
theories/lecture_notes/lists.v
theories/lecture_notes/lists_guarded.v
theories/lecture_notes/lock.v
theories/lecture_notes/lock_unary_spec.v
theories/lecture_notes/modular_incr.v
theories/lecture_notes/recursion_through_the_store.v
theories/lecture_notes/stack.v
theories/lecture_notes/ccounter.v
theories/spanning_tree/graph.v
theories/spanning_tree/graph.v
theories/spanning_tree/mon.v
theories/spanning_tree/mon.v
...
...
theories/lecture_notes/ccounter.v
0 → 100644
View file @
955aa2d2
(* Counter with contributions. A specification derived from the modular
specification proved in modular_incr module. *)
From
iris
.
program_logic
Require
Export
weakestpre
.
From
iris
.
heap_lang
Require
Export
lang
proofmode
notation
.
From
iris
.
proofmode
Require
Import
tactics
.
From
iris
.
algebra
Require
Import
frac_auth
.
From
iris_examples
.
lecture_notes
Require
Import
modular_incr
.
Class
ccounterG
Σ
:
=
CCounterG
{
ccounter_inG
:
>
inG
Σ
(
frac_authR
natR
)
}.
Definition
ccounter
Σ
:
gFunctors
:
=
#[
GFunctor
(
frac_authR
natR
)].
Instance
subG_ccounter
Σ
{
Σ
}
:
subG
ccounter
Σ
Σ
→
ccounterG
Σ
.
Proof
.
solve_inG
.
Qed
.
Section
ccounter
.
Context
`
{!
heapG
Σ
,
!
cntG
Σ
,
!
ccounterG
Σ
}
(
N
:
namespace
).
Lemma
ccounterRA_valid
(
m
n
:
natR
)
(
q
:
frac
)
:
✓
(
●
!
m
⋅
◯
!{
q
}
n
)
→
(
n
≤
m
)%
nat
.
Proof
.
intros
?.
(* This property follows directly from the generic properties of the relevant RAs. *)
by
apply
nat_included
,
(
frac_auth_included_total
q
).
Qed
.
Lemma
ccounterRA_valid_full
(
m
n
:
natR
)
:
✓
(
●
!
m
⋅
◯
!
n
)
→
(
n
=
m
)%
nat
.
Proof
.
by
intros
?%
frac_auth_agree
.
Qed
.
Lemma
ccounterRA_update
(
m
n
:
natR
)
(
q
:
frac
)
:
(
●
!
m
⋅
◯
!{
q
}
n
)
~~>
(
●
!
(
S
m
)
⋅
◯
!{
q
}
(
S
n
)).
Proof
.
apply
frac_auth_update
,
(
nat_local_update
_
_
(
S
_
)
(
S
_
)).
lia
.
Qed
.
Definition
ccounter_inv
(
γ₁
γ₂
:
gname
)
:
iProp
Σ
:
=
(
∃
n
,
own
γ₁
(
●
!
n
)
∗
γ₂
⤇½
(
Z
.
of_nat
n
))%
I
.
Definition
is_ccounter
(
γ₁
γ₂
:
gname
)
(
l
:
loc
)
(
q
:
frac
)
(
n
:
natR
)
:
iProp
Σ
:
=
(
own
γ₁
(
◯
!{
q
}
n
)
∗
inv
(
N
.@
"counter"
)
(
ccounter_inv
γ₁
γ₂
)
∗
Cnt
N
l
γ₂
)%
I
.
(** The main proofs. *)
Lemma
is_ccounter_op
γ₁
γ₂
ℓ
q1
q2
(
n1
n2
:
nat
)
:
is_ccounter
γ₁
γ₂
ℓ
(
q1
+
q2
)
(
n1
+
n2
)%
nat
⊣
⊢
is_ccounter
γ₁
γ₂
ℓ
q1
n1
∗
is_ccounter
γ₁
γ₂
ℓ
q2
n2
.
Proof
.
apply
uPred
.
equiv_spec
;
split
;
rewrite
/
is_ccounter
frag_auth_op
own_op
.

iIntros
"[? #?]"
.
iFrame
"#"
;
iFrame
.

iIntros
"[[? #?] [? _]]"
.
iFrame
"#"
;
iFrame
.
Qed
.
Lemma
newcounter_contrib_spec
(
R
:
iProp
Σ
)
m
:
{{{
True
}}}
newcounter
#
m
{{{
γ₁
γ₂
ℓ
,
RET
#
ℓ
;
is_ccounter
γ₁
γ₂
ℓ
1
m
%
nat
}}}.
Proof
.
iIntros
(
Φ
)
"_ HΦ"
.
rewrite

wp_fupd
.
wp_apply
newcounter_spec
;
auto
.
iIntros
(
ℓ
)
"H"
;
iDestruct
"H"
as
(
γ₂
)
"[#HCnt Hown]"
.
iMod
(
own_alloc
(
●
!
m
%
nat
⋅
◯
!
m
%
nat
))
as
(
γ₁
)
"[Hγ Hγ']"
;
first
done
.
iMod
(
inv_alloc
(
N
.@
"counter"
)
_
(
ccounter_inv
γ₁
γ₂
)
with
"[Hγ Hown]"
).
{
iNext
.
iExists
_
.
by
iFrame
.
}
iModIntro
.
iApply
"HΦ"
.
rewrite
/
is_ccounter
;
eauto
.
Qed
.
Lemma
incr_contrib_spec
γ₁
γ₂
ℓ
q
n
:
{{{
is_ccounter
γ₁
γ₂
ℓ
q
n
}}}
incr
#
ℓ
{{{
(
y
:
Z
),
RET
#
y
;
is_ccounter
γ₁
γ₂
ℓ
q
(
S
n
)
}}}.
Proof
.
iIntros
(
Φ
)
"[Hown #[Hinv HCnt]] HΦ"
.
iApply
(
incr_spec
N
γ₂
_
(
own
γ₁
(
◯
!{
q
}
n
))%
I
(
λ
_
,
(
own
γ₁
(
◯
!{
q
}
(
S
n
))))%
I
with
"[] [Hown]"
)
;
first
set_solver
.

iIntros
(
m
)
"!# [HOwnElem HP]"
.
iInv
(
N
.@
"counter"
)
as
(
k
)
"[>H1 >H2]"
"HClose"
.
iDestruct
(
makeElem_eq
with
"HOwnElem H2"
)
as
%>.
iMod
(
makeElem_update
_
_
_
(
k
+
1
)
with
"HOwnElem H2"
)
as
"[HOwnElem H2]"
.
iMod
(
own_update_2
with
"H1 HP"
)
as
"[H1 HP]"
.
{
apply
ccounterRA_update
.
}
iMod
(
"HClose"
with
"[H1 H2]"
)
as
"_"
.
{
iNext
;
iExists
(
S
k
)
;
iFrame
.
rewrite
Nat2Z
.
inj_succ
Z
.
add_1_r
//.
}
by
iFrame
.

by
iFrame
.

iNext
.
iIntros
(
m
)
"[HCnt' Hown]"
.
iApply
"HΦ"
.
by
iFrame
.
Qed
.
Lemma
read_contrib_spec
γ₁
γ₂
ℓ
q
n
:
{{{
is_ccounter
γ₁
γ₂
ℓ
q
n
}}}
read
#
ℓ
{{{
(
c
:
Z
),
RET
#
c
;
⌜
Z
.
of_nat
n
≤
c
⌝
∧
is_ccounter
γ₁
γ₂
ℓ
q
n
}}}.
Proof
.
iIntros
(
Φ
)
"[Hown #[Hinv HCnt]] HΦ"
.
wp_apply
(
read_spec
N
γ₂
_
(
own
γ₁
(
◯
!{
q
}
n
))%
I
(
λ
m
,
⌜
n
≤
m
⌝
∗
(
own
γ₁
(
◯
!{
q
}
n
)))%
I
with
"[] [Hown]"
)
;
first
set_solver
.

iIntros
(
m
)
"!# [HownE HOwnfrag]"
.
iInv
(
N
.@
"counter"
)
as
(
k
)
"[>H1 >H2]"
"HClose"
.
iDestruct
(
makeElem_eq
with
"HownE H2"
)
as
%>.
iDestruct
(
own_valid_2
with
"H1 HOwnfrag"
)
as
%
Hleq
%
ccounterRA_valid
.
iMod
(
"HClose"
with
"[H1 H2]"
)
as
"_"
.
{
iExists
_;
by
iFrame
.
}
iFrame
;
iIntros
"!>!%"
.
auto
using
inj_le
.

by
iFrame
.

iIntros
(
i
)
"[_ [% HQ]]"
.
iApply
"HΦ"
.
iSplit
;
first
by
iIntros
"!%"
.
iFrame
;
iFrame
"#"
.
Qed
.
Lemma
read_contrib_spec_1
γ₁
γ₂
ℓ
n
:
{{{
is_ccounter
γ₁
γ₂
ℓ
1
%
Qp
n
}}}
read
#
ℓ
{{{
RET
#
n
;
is_ccounter
γ₁
γ₂
ℓ
1
n
}}}.
Proof
.
iIntros
(
Φ
)
"[Hown #[Hinv HCnt]] HΦ"
.
wp_apply
(
read_spec
N
γ₂
_
(
own
γ₁
(
◯
!
n
))%
I
(
λ
m
,
⌜
Z
.
of_nat
n
=
m
⌝
∗
(
own
γ₁
(
◯
!
n
)))%
I
with
"[] [Hown]"
)
;
first
set_solver
.

iIntros
(
m
)
"!# [HownE HOwnfrag]"
.
iInv
(
N
.@
"counter"
)
as
(
k
)
"[>H1 >H2]"
"HClose"
.
iDestruct
(
makeElem_eq
with
"HownE H2"
)
as
%>.
iDestruct
(
own_valid_2
with
"H1 HOwnfrag"
)
as
%
Hleq
%
ccounterRA_valid_full
;
simplify_eq
.
iMod
(
"HClose"
with
"[H1 H2]"
)
as
"_"
.
{
iExists
_;
by
iFrame
.
}
iFrame
;
by
iIntros
"!>!%"
.

by
iFrame
.

iIntros
(
i
)
"[_ [% HQ]]"
.
simplify_eq
.
iApply
"HΦ"
.
iFrame
;
iFrame
"#"
.
Qed
.
End
ccounter
.
\ No newline at end of file
theories/lecture_notes/lists.v
0 → 100644
View file @
955aa2d2
This diff is collapsed.
Click to expand it.
theories/lecture_notes/lists_guarded.v
0 → 100644
View file @
955aa2d2
(* In this file we explain how to do the "list examples" from the Chapter on
Separation Logic for Sequential Programs in the Iris Lecture Notes, but where
we use the guarded fixed point and Löb induction to define and work with the
isList predicate. *)
(* Contains definitions of the weakest precondition assertion, and its basic rules. *)
From
iris
.
program_logic
Require
Export
weakestpre
.
(* Instantiation of Iris with the particular language. The notation file
contains many shorthand notations for the programming language constructs, and
the lang file contains the actual language syntax. *)
From
iris
.
heap_lang
Require
Export
notation
lang
.
(* Files related to the interactive proof mode. The first import includes the
general tactics of the proof mode. The second provides some more specialized
tactics particular to the instantiation of Iris to a particular programming
language. *)
From
iris
.
proofmode
Require
Export
tactics
.
From
iris
.
heap_lang
Require
Import
proofmode
.
(* The following line makes Coq check that we do not use any admitted facts /
additional assumptions not in the statement of the theorems being proved. *)
Set
Default
Proof
Using
"Type"
.
(*  *)
Section
list_model
.
(* This section contains the definition of our model of lists, i.e.,
definitions relating pointer data structures to our model, which is
simply mathematical sequences (Coq lists). *)
(* In order to do the proof we need to assume certain things about the
instantiation of Iris. The particular, even the heap is handled in an
analogous way as other ghost state. This line states that we assume the
Iris instantiation has sufficient structure to manipulate the heap, e.g.,
it allows us to use the pointsto predicate. *)
Context
`
{!
heapG
Σ
}.
Implicit
Types
l
:
loc
.
(* The variable Σ has to do with what ghost state is available, and the type
of Iris propositions (written Prop in the lecture notes) depends on this Σ.
But since Σ is the same throughout the development we shall define
shorthand notation which hides it. *)
Notation
iProp
:
=
(
iProp
Σ
).
(* First we define the is_list representation predicate via a guarded fixed
point of the functional is_list_pre. Note the use of the later modality. The
arrows c> express that the arrow is an arrow in the category of COFE's,
i.e., it is a nonexpansive function. To fully understand the meaning of this
it is necessary to understand the model of Iris.
Since the type val is discrete the nonexpansiveness condition is trivially
satisfied in this case, and we might as well have used the ordinary arrow,
but in more complex examples the domain of the predicate we are defining will
not be a discrete type, and the condition will be meaningful and necessary.
*)
Definition
is_list_pre
(
Φ
:
val

c
>
list
val

c
>
iProp
)
:
val

c
>
list
val

c
>
iProp
:
=
λ
hd
xs
,
match
xs
with
[]
=>
⌜
hd
=
NONEV
⌝

(
x
::
xs
)
=>
(
∃
(
ℓ
:
loc
)
(
hd'
:
val
),
⌜
hd
=
SOMEV
#
ℓ⌝
∗
ℓ
↦
(
x
,
hd'
)
∗
▷
Φ
hd'
xs
)
end
%
I
.
(* To construct the fixed point we need to show that the functional we have defined is contractive.
Most of the proof is automated via the f_contractive tactic. *)
Local
Instance
is_list_pre_contractive
:
Contractive
is_list_pre
.
Proof
.
rewrite
/
is_list_pre
.
intros
n
Φ
Φ
'
Hdist
hd
ℓ
.
repeat
(
f_contractive

f_equiv
)
;
apply
Hdist
.
Qed
.
Definition
is_list_def
:
val
→
list
val
→
iProp
:
=
fixpoint
is_list_pre
.
Definition
is_list_aux
:
seal
(@
is_list_def
).
by
eexists
.
Qed
.
Definition
is_list
:
=
unseal
(@
is_list_aux
).
Definition
is_list_eq
:
@
is_list
=
@
is_list_def
:
=
seal_eq
is_list_aux
.
Lemma
is_list_unfold
hd
xs
:
is_list
hd
xs
⊣
⊢
is_list_pre
is_list
hd
xs
.
Proof
.
rewrite
is_list_eq
.
apply
(
fixpoint_unfold
is_list_pre
).
Qed
.
(* Exercise.
Using an approach as above, given a predicate Ψ : val → iProp, define a
predicate is_list_Ψ : val → iProp, where is_list_Ψ hd means that hd points to a linked list of elements, all of which satisfy Ψ.
*)
(* Exercise. Reprove all the specifications from lists.v using the above definition of is_list. *)
End
list_model
.
\ No newline at end of file
theories/lecture_notes/lock.v
0 → 100644
View file @
955aa2d2
(* This file contains the specification of the lock module implemented as a simple spin lock and discussed in
section 7.6 in the invariants and ghost state chapter of the Iris Lecture Notes.
*)
(* Contains definitions of the weakest precondition assertion, and its basic rules. *)
From
iris
.
program_logic
Require
Export
weakestpre
.
(* Instantiation of Iris with the particular language. The notation file
contains many shorthand notations for the programming language constructs, and
the lang file contains the actual language syntax. *)
From
iris
.
heap_lang
Require
Export
notation
lang
.
(* Files related to the interactive proof mode. The first import includes the
general tactics of the proof mode. The second provides some more specialized
tactics particular to the instantiation of Iris to a particular programming
language. *)
From
iris
.
proofmode
Require
Export
tactics
.
From
iris
.
heap_lang
Require
Import
proofmode
.
(* Definition of invariants and their rules (expressed using the fancy update modality). *)
From
iris
.
base_logic
.
lib
Require
Export
invariants
.
(* The exclusive resource algebra. *)
From
iris
.
algebra
Require
Import
excl
.
Section
lock_model
.
(* In order to do the proof we need to assume certain things about the
instantiation of Iris. The particular, even the heap is handled in an
analogous way as other ghost state. This line states that we assume the Iris
instantiation has sufficient structure to manipulate the heap, e.g., it
allows us to use the pointsto predicate, and that the ghost state includes
the exclusive resource algebra over the singleton set (represented using the
unitR type). *)
Context
`
{
heapG
Σ
}.
Context
`
{
inG
Σ
(
exclR
unitR
)}.
(* We use a ghost name with a token to model whether the lock is locked or not.
The the token is just exclusive ownerwhip of unit value. *)
Definition
locked
γ
:
=
own
γ
(
Excl
()).
(* The name of a lock. *)
Definition
lockN
(
l
:
loc
)
:
=
nroot
.@
"lock"
.@
l
.
(* The lock invariant *)
Definition
is_lock
γ
l
P
:
=
inv
(
lockN
l
)
((
l
↦
(#
false
)
∗
P
∗
locked
γ
)
∨
l
↦
(#
true
))%
I
.
(* The is_lock predicate is persistent *)
Global
Instance
is_lock_persistent
γ
l
Φ
:
Persistent
(
is_lock
γ
l
Φ
).
Proof
.
apply
_
.
Qed
.
End
lock_model
.
Section
lock_code
.
(* Here is the standard spin lock code *)
Definition
newlock
:
val
:
=
λ
:
<>,
ref
#
false
.
Definition
acquire
:
val
:
=
rec
:
"acquire"
"l"
:
=
if
:
CAS
"l"
#
false
#
true
then
#()
else
"acquire"
"l"
.
Definition
release
:
val
:
=
λ
:
"l"
,
"l"
<
#
false
.
End
lock_code
.
Section
lock_spec
.
Context
`
{
heapG
Σ
}.
Context
`
{
inG
Σ
(
exclR
unitR
)}.
Lemma
wp_newlock_t
P
:
{{{
P
}}}
newlock
#()
{{{
v
,
RET
v
;
∃
(
l
:
loc
)
γ
,
⌜
v
=
#
l
⌝
∧
is_lock
γ
l
P
}}}.
Proof
.
iIntros
(
φ
)
"Hi Hcont"
.
rewrite

wp_fupd
/
newlock
.
wp_lam
.
wp_alloc
l
as
"HPt"
.
iMod
(
own_alloc
(
Excl
()))
as
(
γ
)
"Hld"
;
first
done
.
iMod
(
inv_alloc
_
_
((
l
↦
(#
false
)
∗
P
∗
locked
γ
)
∨
l
↦
(#
true
))%
I
with
"[Hcont]"
)
as
"Hinv"
;
last
eauto
.
{
iNext
;
iLeft
;
iFrame
.
}
iApply
"Hcont"
.
iExists
l
,
γ
.
iModIntro
.
iSplit
;
first
done
.
iFrame
.
Qed
.
Lemma
wp_acquire_t
E
γ
l
P
:
nclose
(
lockN
l
)
⊆
E
→
{{{
is_lock
γ
l
P
}}}
acquire
(#
l
)
@
E
{{{
v
,
RET
#
v
;
P
∗
locked
γ
}}}.
Proof
.
iIntros
(
HE
φ
)
"#Hi Hcont"
;
rewrite
/
acquire
.
iL
ö
b
as
"IH"
.
wp_rec
.
wp_bind
(
CAS
_
_
_
).
iInv
(
lockN
l
)
as
"[(Hl & HP & Ht)Hl]"
"Hcl"
.

wp_cas_suc
.
iMod
(
"Hcl"
with
"[Hl]"
)
as
"_"
;
first
by
iRight
.
iModIntro
.
wp_if
.
iApply
"Hcont"
.
iFrame
.

wp_cas_fail
.
iMod
(
"Hcl"
with
"[Hl]"
)
as
"_"
;
first
by
iRight
.
iModIntro
.
wp_if
.
iApply
(
"IH"
with
"[$Hcont]"
).
Qed
.
Lemma
wp_release_t
E
γ
l
P
:
nclose
(
lockN
l
)
⊆
E
→
{{{
is_lock
γ
l
P
∗
locked
γ
∗
P
}}}
release
(#
l
)
@
E
{{{
RET
#()
;
True
}}}.
Proof
.
iIntros
(
HE
φ
)
"(#Hi & Hld & HP) Hcont"
;
rewrite
/
release
.
wp_lam
.
iInv
(
lockN
l
)
as
"[(Hl & HQ & >Ht)Hl]"
"Hcl"
.

iDestruct
(
own_valid_2
with
"Hld Ht"
)
as
%
Hv
.
done
.

wp_store
.
iMod
(
"Hcl"
with
"[Hcont]"
)
as
"_"
;
first
by
iNext
;
iLeft
;
iFrame
.
iApply
"Hcont"
.
done
.
Qed
.
Global
Opaque
newlock
release
acquire
.
End
lock_spec
.
Typeclasses
Opaque
locked
.
Global
Opaque
locked
.
Typeclasses
Opaque
is_lock
.
Global
Opaque
is_lock
.
\ No newline at end of file
theories/lecture_notes/lock_unary_spec.v
0 → 100644
View file @
955aa2d2
(* This file contains the specification of a lock module discussed
in the section on the Fancy update modality and weakest precondition
in the Iris Lecture Notes.
Recall from loc. cit. that the point of this
alternative lock specification is that it allows ones
to allocate the lock before one knows what the resource
of the invariant it is going to protect is.
*)
(* Contains definitions of the weakest precondition assertion, and its basic rules. *)
From
iris
.
program_logic
Require
Export
weakestpre
.
(* Instantiation of Iris with the particular language. The notation file
contains many shorthand notations for the programming language constructs, and
the lang file contains the actual language syntax. *)
From
iris
.
heap_lang
Require
Export
notation
lang
.
(* Files related to the interactive proof mode. The first import includes the
general tactics of the proof mode. The second provides some more specialized
tactics particular to the instantiation of Iris to a particular programming
language. *)
From
iris
.
proofmode
Require
Export
tactics
.
From
iris
.
heap_lang
Require
Import
proofmode
.
(* Definition of invariants and their rules (expressed using the fancy update
modality). *)
From
iris
.
base_logic
.
lib
Require
Export
invariants
.
(* The exclusive resource algebra *)
From
iris
.
algebra
Require
Import
excl
.
Section
lock_model
.
(* In order to do the proof we need to assume certain things about the
instantiation of Iris. The particular, even the heap is handled in an
analogous way as other ghost state. This line states that we assume the Iris
instantiation has sufficient structure to manipulate the heap, e.g., it
allows us to use the pointsto predicate, and that the ghost state includes
the exclusive resource algebra over the singleton set (represented using the
unitR type). *)
Context
`
{
heapG
Σ
}.
Context
`
{
inG
Σ
(
exclR
unitR
)}.
(* We use a ghost name with a token to model whether the lock is locked or not.
The the token is just exclusive ownerwhip of unit value. *)
Definition
locked
γ
:
=
own
γ
(
Excl
()).
(* The name of a lock. *)
Definition
lockN
(
l
:
loc
)
:
=
nroot
.@
"lock"
.@
l
.
(* The lock invariant *)
Definition
is_lock
γ
l
P
:
=
inv
(
lockN
l
)
((
l
↦
(#
false
)
∗
P
∗
locked
γ
)
∨
l
↦
(#
true
))%
I
.
(* The is_lock predicate is persistent *)
Global
Instance
is_lock_persistent
γ
l
Φ
:
Persistent
(
is_lock
γ
l
Φ
).
Proof
.
apply
_
.
Qed
.
End
lock_model
.
Section
lock_code
.
(* Here is the standard spin lock code *)
Definition
newlock
:
val
:
=
λ
:
<>,
ref
#
false
.
Definition
acquire
:
val
:
=
rec
:
"acquire"
"l"
:
=
if
:
CAS
"l"
#
false
#
true
then
#()
else
"acquire"
"l"
.
Definition
release
:
val
:
=
λ
:
"l"
,
"l"
<
#
false
.
End
lock_code
.
Section
lock_spec
.
Context
`
{
heapG
Σ
}.
Context
`
{
inG
Σ
(
exclR
unitR
)}.
(* Here is the interesting part of this example, namely the new specification
for newlock, which allows one to get a postcondition which can be instantiated
with the lock invariant at some point later, when it is known.
See the discussion in Iris Lecture Notes.
First we show the specs using triples, and afterwards using weakest preconditions.
*)
Lemma
wp_newlock_t
:
{{{
True
}}}
newlock
#()
{{{
v
,
RET
v
;
∃
(
l
:
loc
)
γ
,
⌜
v
=
#
l
⌝
∧
(
∀
P
E
,
P
={
E
}=
∗
is_lock
γ
l
P
)
}}}.
Proof
.
iIntros
(
φ
)
"Hi Hcont"
.
rewrite

wp_fupd
/
newlock
.
wp_lam
.
wp_alloc
l
as
"HPt"
.
iApply
"Hcont"
.
iExists
l
.
iMod
(
own_alloc
(
Excl
()))
as
(
γ
)
"Hld"
;
first
done
.
iExists
γ
.
iModIntro
.
iSplit
;
first
done
.
iIntros
(
P
E
)
"HP"
.
iMod
(
inv_alloc
_
_
((
l
↦
(#
false
)
∗
P
∗
locked
γ
)
∨
l
↦
(#
true
))%
I
with
"[]"
)
as
"Hinv"
;
last
eauto
.
{
iNext
;
iLeft
;
iFrame
.
}
Qed
.
Lemma
wp_acquire_t
E
γ
l
P
:
nclose
(
lockN
l
)
⊆
E
→
{{{
is_lock
γ
l
P
}}}
acquire
(#
l
)
@
E
{{{
v
,
RET
#
v
;
P
∗
locked
γ
}}}.
Proof
.
iIntros
(
HE
φ
)
"#Hi Hcont"
;
rewrite
/
acquire
.
iL
ö
b
as
"IH"
.
wp_rec
.
wp_bind
(
CAS
_
_
_
).
iInv
(
lockN
l
)
as
"[(Hl & HP & Ht)Hl]"
"Hcl"
.

wp_cas_suc
.
iMod
(
"Hcl"
with
"[Hl]"
)
as
"_"
;
first
by
iRight
.
iModIntro
.
wp_if
.
iApply
"Hcont"
.
iFrame
.

wp_cas_fail
.
iMod
(
"Hcl"
with
"[Hl]"
)
as
"_"
;
first
by
iRight
.
iModIntro
.
wp_if
.
iApply
(
"IH"
with
"[$Hcont]"
).
Qed
.
Lemma
wp_release_t
E
γ
l
P
:
nclose
(
lockN
l
)
⊆
E
→
{{{
is_lock
γ
l
P
∗
locked
γ
∗
P
}}}
release
(#
l
)
@
E
{{{
RET
#()
;
True
}}}.
Proof
.
iIntros
(
HE
φ
)
"(#Hi & Hld & HP) Hcont"
;
rewrite
/
release
.
wp_lam
.
iInv
(
lockN
l
)
as
"[(Hl & HQ & >Ht)Hl]"
"Hcl"
.

iDestruct
(
own_valid_2
with
"Hld Ht"
)
as
%
Hv
.
done
.

wp_store
.
iMod
(
"Hcl"
with
"[Hcont]"
)
as
"_"
;
first
by
iNext
;
iLeft
;
iFrame
.
iApply
"Hcont"
.
done
.
Qed
.
(* Here are the specifications again, just written using weakest preconditions *)
Lemma
wp_newlock
:
True
⊢
WP
newlock
#()
{{
v
,
∃
(
l
:
loc
)
γ
,
⌜
v
=
#
l
⌝
∧
(
∀
P
E
,
P
={
E
}=
∗
is_lock
γ
l
P
)
}}.
Proof
.
iIntros
"_"
.
rewrite

wp_fupd
/
newlock
.
wp_lam
.
wp_alloc
l
as
"HPt"
.
iExists
l
.
iMod
(
own_alloc
(
Excl
()))
as
(
γ
)
"Hld"
;
first
done
.
iExists
γ
.
iModIntro
.
iSplit
;
first
done
.
iIntros
(
P
E
)
"HP"
.
iMod
(
inv_alloc
_
_
((
l
↦
(#
false
)
∗
P
∗
locked
γ
)
∨
l
↦
(#
true
))%
I
with
"[]"
)
as
"Hinv"
;
last
eauto
.
{
iNext
;
iLeft
;
iFrame
.
}
Qed
.
Lemma
wp_acquire
E
γ
l
P
:
nclose
(
lockN
l
)
⊆
E
→
is_lock
γ
l
P
⊢
WP
acquire
(#
l
)
@
E
{{
v
,
P
∗
locked
γ
}}.
Proof
.
iIntros
(
HE
)
"#Hi"
;
rewrite
/
acquire
.
iL
ö
b
as
"IH"
.
wp_rec
.
wp_bind
(
CAS
_
_
_
).
iInv
(
lockN
l
)
as
"[(Hl & HP & Ht)Hl]"
"Hcl"
.

wp_cas_suc
.
iMod
(
"Hcl"
with
"[Hl]"
)
as
"_"
;
first
by
iRight
.
iModIntro
.
wp_if
.
iFrame
.

wp_cas_fail
.
iMod
(
"Hcl"
with
"[Hl]"
)
as
"_"
;
first
by
iRight
.
iModIntro
.
wp_if
.
iApply
"IH"
.
Qed
.
Lemma
wp_release
E
γ
l
P
:
nclose
(
lockN
l
)
⊆
E
→
is_lock
γ
l
P
∗
locked
γ
∗
P
⊢
WP
release
(#
l
)
@
E
{{
v
,
True
}}.
Proof
.
iIntros
(
HE
)
"(#Hi & Hld & HP)"
;
rewrite
/
release
.
wp_lam
.
iInv
(
lockN
l
)
as
"[(Hl & HQ & >Ht)Hl]"
"Hcl"
.

iDestruct
(
own_valid_2
with
"Hld Ht"
)
as
%
Hv
.
done
.

wp_store
.
iMod
(
"Hcl"
with
"[]"
)
as
"_"
;
first
by
iNext
;
iLeft
;
iFrame
.
done
.
Qed
.
Global
Opaque
newlock
release
acquire
.
(* We now present a simple client of the lock which cannot be verified with the
lock specification described in the Chapter on Invariants and Ghost State in the
Iris Lecture Notes, but which can be specifed and verified with the current
specification.
*)
Definition
test
:
expr
:
=
let
:
"l"
:
=
newlock
#()
in
let
:
"r"
:
=
ref
#
0
in
(
λ
:
<>,
acquire
"l"
;;
"r"
<
!
"r"
+
#
1
;;
release
"l"
).
Lemma
test_spec
:
{{{
True
}}}
test
#()
{{{
v
,
RET
v
;
True
}}}.
Proof
.
iIntros
(
φ
)
"Hi HCont"
;
rewrite
/
test
.
wp_bind
(
newlock
#())%
E
.
iApply
(
wp_newlock_t
)
;
auto
.
iNext
.
iIntros
(
v
)
"Hs"
.
wp_lam
.
wp_bind
(
ref
#
0
)%
E
.
wp_alloc
l
as
"Hl"
.
wp_lam
.
wp_lam
.
wp_bind
(
acquire
v
)%
E
.
iDestruct
"Hs"
as
(
l'
γ
)
"[% H2]"
.
subst
.
iMod
(
"H2"
$!
(
∃
(
n
:
Z
),
l
↦
#
n
)%
I
with
"[Hl]"
)
as
"#H3"
.
{
iExists
0
;
iFrame
.
}
wp_apply
(
wp_acquire_t
with
"H3"
)
;
auto
.
iIntros
(
v
)
"(Hpt & Hlocked)"
.
iDestruct
"Hpt"
as
(
u
)
"Hpt"
.
wp_lam
.
wp_load
.
wp_op
.
wp_store
.
wp_apply
(
wp_release_t
with
"[HCont]"
)
;
auto
.
iFrame
"H3 Hlocked"
.
iExists
_;
iFrame
.
Qed
.
End
lock_spec
.
Typeclasses
Opaque
locked
.
Global
Opaque
locked
.
Typeclasses
Opaque
is_lock
.
Global
Opaque
is_lock
.
\ No newline at end of file
theories/lecture_notes/modular_incr.v
0 → 100644
View file @
955aa2d2
(* Modular Specifications for Concurrent Modules. *)
From
iris
.
program_logic
Require
Export
hoare
weakestpre
.
From
iris
.
heap_lang
Require
Export
lang
proofmode
notation
.
From
iris
.
proofmode
Require
Import
tactics
.
From
iris
.
algebra
Require
Import
agree
frac
frac_auth
.
From
iris
.
base_logic
.
lib
Require
Import
fractional
.
From
iris
.
heap_lang
.
lib
Require
Import
par
.
Definition
cntCmra
:
cmraT
:
=
(
prodR
fracR
(
agreeR
(
leibnizC
Z
))).
Class
cntG
Σ
:
=
CntG
{
CntG_inG
:
>
inG
Σ
cntCmra
}.
Definition
cnt
Σ
:
gFunctors
:
=
#[
GFunctor
cntCmra
].
Instance
subG_cnt
Σ
{
Σ
}
:
subG
cnt
Σ
Σ
→
cntG
Σ
.
Proof
.
solve_inG
.
Qed
.
Definition
newcounter
:
val
:
=
λ
:
"m"
,
ref
"m"
.
Definition
read
:
val
:
=
λ
:
"ℓ"
,
!
"ℓ"
.
Definition
incr
:
val
:
=
rec
:
"incr"
"l"
:
=
let
:
"oldv"
:
=
!
"l"
in
if
:
CAS
"l"
"oldv"
(
"oldv"
+
#
1
)
then
"oldv"
(* return old value if success *)
else
"incr"
"l"
.
Definition
wk_incr
:
val
:
=
λ
:
"l"
,
let
:
"n"
:
=
!
"l"
in
"l"
<
"n"
+
#
1
.
Section
cnt_model
.
Context
`
{!
cntG
Σ
}.
Definition
makeElem
(
q
:
Qp
)
(
m
:
Z
)
:
cntCmra
:
=
(
q
,
to_agree
m
).
Notation
"γ ⤇[ q ] m"
:
=
(
own
γ
(
makeElem
q
m
))