mirror of
https://github.com/achlipala/frap.git
synced 2024-11-10 00:07:51 +00:00
Checkpoint simplifying SharedMemory
This commit is contained in:
parent
db0f87d654
commit
824d4bc524
1 changed files with 33 additions and 37 deletions
|
@ -276,7 +276,7 @@ Proof.
|
|||
equality.
|
||||
Qed.
|
||||
|
||||
(* The key correctnss property: when an original step takes place, either it
|
||||
(* The key correctness property: when an original step takes place, either it
|
||||
* has no effect or can be duplicated when we apply [runLocal] both *before* and
|
||||
* *after* the step. *)
|
||||
Lemma step_runLocal : forall h l c h' l' c',
|
||||
|
@ -413,7 +413,7 @@ Example independent_threads :=
|
|||
else
|
||||
Fail)
|
||||
|| (b <- Read 2;
|
||||
Write 2 (b + 1)).
|
||||
Write 2 (b + 1)).
|
||||
|
||||
(* Unfortunately, our existing model-checker does in fact follow the
|
||||
* "exponential" strategy to build the state space. *)
|
||||
|
@ -456,7 +456,7 @@ Record summary := {
|
|||
Locks : set nat
|
||||
}.
|
||||
|
||||
(* Here is a relation to check the accuracy of a summary for a single thread. *)
|
||||
(* Here is a relation to check the accuracy of a summary. *)
|
||||
Inductive summarize : cmd -> summary -> Prop :=
|
||||
| SumReturn : forall r s,
|
||||
summarize (Return r) s
|
||||
|
@ -465,6 +465,8 @@ Inductive summarize : cmd -> summary -> Prop :=
|
|||
| SumBind : forall c1 c2 s,
|
||||
summarize c1 s
|
||||
-> (forall r, summarize (c2 r) s)
|
||||
(* Note the approximation here: we consider all [r] values, even if some
|
||||
* are semantically impossible. *)
|
||||
-> summarize (Bind c1 c2) s
|
||||
| SumRead : forall a s,
|
||||
a \in s.(Reads)
|
||||
|
@ -477,22 +479,15 @@ Inductive summarize : cmd -> summary -> Prop :=
|
|||
-> summarize (Lock a) s
|
||||
| SumUnlock : forall a s,
|
||||
a \in s.(Locks)
|
||||
-> summarize (Unlock a) s.
|
||||
|
||||
(* And here's one to check the accuracy of a summary for a list of threads.
|
||||
* Each thread is packaged with its verified summary in the list. *)
|
||||
Inductive summarizeThreads : cmd -> list (cmd * summary) -> Prop :=
|
||||
| StPar : forall c1 c2 ss1 ss2,
|
||||
summarizeThreads c1 ss1
|
||||
-> summarizeThreads c2 ss2
|
||||
-> summarizeThreads (Par c1 c2) (ss1 ++ ss2)
|
||||
| StAtomic : forall c s,
|
||||
summarize c s
|
||||
-> summarizeThreads c [(c, s)].
|
||||
(* We will use these expanded lists as the command type in the new semantics. *)
|
||||
-> summarize (Unlock a) s
|
||||
| SumPar : forall c1 c2 s,
|
||||
summarize c1 s
|
||||
-> summarize c2 s
|
||||
-> summarize (Par c1 c2) s.
|
||||
|
||||
(* To check commutativity, it is helpful to know which atomic command a thread
|
||||
* could run next. *)
|
||||
* could run next. We skip coverage of parallel compositions to make things
|
||||
* simple. *)
|
||||
Inductive nextAction : cmd -> cmd -> Prop :=
|
||||
| NaReturn : forall r,
|
||||
nextAction (Return r) (Return r)
|
||||
|
@ -526,41 +521,42 @@ Definition commutes (c : cmd) (s : summary) : Prop :=
|
|||
end.
|
||||
|
||||
(* Now the new semantics: *)
|
||||
Inductive stepC : heap * locks * list (cmd * summary) -> heap * locks * list (cmd * summary) -> Prop :=
|
||||
Inductive stepC (s : summary) : heap * locks * cmd -> heap * locks * cmd -> Prop :=
|
||||
|
||||
(* It is always OK to let the first thread run. *)
|
||||
| StepFirst : forall h l c h' l' c' s cs,
|
||||
step (h, l, c) (h', l', c')
|
||||
-> stepC (h, l, (c, s) :: cs) (h', l', (c', s) :: cs)
|
||||
| StepFirst : forall h l c1 h' l' c1' c2,
|
||||
step (h, l, c1) (h', l', c1')
|
||||
-> stepC s (h, l, c1 || c2) (h', l', c1' || c2)
|
||||
|
||||
(* However, you may only pick another thread to run if it would be unsound to
|
||||
* consider just the first thread. The negation of the soundness condition is
|
||||
* expressed in the first premise below. *)
|
||||
| StepAny : forall h l c h' l' s cs1 c1 s1 cs2 c1',
|
||||
(forall c0 h'' l'' c'', nextAction c c0
|
||||
(* The first thread [c] has some atomic action [c0]
|
||||
* ready to run. *)
|
||||
-> List.Forall (fun c_s => commutes c0 (snd c_s)) (cs1 ++ (c1, s1) :: cs2)
|
||||
(* All other threads only contain actiosn that commute
|
||||
* with [c0]. *)
|
||||
| StepAny : forall h l c2 h' l' c2' c1,
|
||||
(forall c0 h'' l'' c1'', nextAction c1 c0
|
||||
(* The first thread [c] has some atomic action [c0]
|
||||
* ready to run. *)
|
||||
-> commutes c0 s
|
||||
(* All other threads only contain actions that commute
|
||||
* with [c0]. *)
|
||||
|
||||
-> step (h, l, c) (h'', l'', c'')
|
||||
(* Finaly, [c] is actually enabled to run, which might
|
||||
* not be the case if [c0] is a locking command. *)
|
||||
-> step (h, l, c1) (h'', l'', c1'')
|
||||
(* Finaly, [c] is actually enabled to run, which
|
||||
* might not be the case if [c0] is a locking
|
||||
* command. *)
|
||||
|
||||
-> False)
|
||||
-> False)
|
||||
|
||||
(* If we passed that check, then we can step a single thread as expected! *)
|
||||
-> step (h, l, c1) (h', l', c1')
|
||||
-> stepC (h, l, (c, s) :: cs1 ++ (c1, s1) :: cs2) (h', l', (c, s) :: cs1 ++ (c1', s1) :: cs2).
|
||||
-> step (h, l, c2) (h', l', c2')
|
||||
-> stepC s (h, l, c1 || c2) (h', l', c1 || c2').
|
||||
|
||||
(* Notice how this definition turns the partial-order-reduction optimization
|
||||
* "off and on" during state-space exploration. We only restrict our attention
|
||||
* to the first thread so long as the soundness condition above is true. *)
|
||||
|
||||
Definition trsys_ofC (h : heap) (l : locks) (cs : list (cmd * summary)) := {|
|
||||
Initial := {(h, l, cs)};
|
||||
Step := stepC
|
||||
Definition trsys_ofC (s : summary) (h : heap) (l : locks) (c : cmd) := {|
|
||||
Initial := {(h, l, c)};
|
||||
Step := stepC s
|
||||
|}.
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue