Commit 9369e246 authored by Martin Clochard's avatar Martin Clochard
Browse files

verifythis parallel gcd: proof for thread interleaving (including termination)

parent 069bd159
......@@ -108,7 +108,6 @@ end
(** Threads interleaving.
Code and invariants by Rustan Leino. *)
(***
module Interleaving
use import int.Int
......@@ -117,6 +116,23 @@ module Interleaving
lemma gcd_sub: forall a b: int. gcd a b = gcd a (b - a)
(* Representation of a thread: two local variables
(register copies of the globals) and a program counter:
ReadA:
local_a <- a
ReadB:
local_b <- b
Compare:
if local_a = local_b goto Halt;
if local_a > local_b a := local_a - local_b;
goto ReadA;
Halt:
For the sake of simplicity, every section is considered atomic.
(strictly speaking, section Compare is not, but it interacts
atomically with memory so it would be equivalent)
*)
type state = ReadA | ReadB | Compare | Halt
type thread = {
......@@ -125,24 +141,69 @@ module Interleaving
mutable state : state;
}
predicate inv (th: thread) (a0 b0 a b: int) =
0 < a /\ 0 < b /\ gcd a b = gcd a0 b0 /\
(* Thread invariant. *)
predicate inv (th: thread) (d a b: int) =
0 < a /\ 0 < b /\ gcd a b = d /\
match th.state with
| ReadA -> true
| ReadB -> th.local_a = a
| ReadB -> th.local_a = a (* No other thread can write in a. *)
| Compare -> th.local_a = a && b <= th.local_b &&
(th.local_b <= th.local_a -> th.local_b = b)
| Halt -> th.local_a = a = b
(* Other thread may have overwritten b, but only in a decreasing
decreasing fashion, and only once under a. *)
| Halt -> th.local_a = a = b (* Final state is stable. *)
end
(* Does running this thread make any progress toward the result ? *)
predicate progress_thread (th:thread) (a b:int) =
a > b \/ (a = b /\ th.state <> Halt)
(* Decreasing ordering on program counter *)
function state_index (s:state) : int = match s with
| ReadA -> 7
| ReadB -> 5
| Compare -> 3
| Halt -> 2
end
(* Synchronisation status. *)
predicate sync (th:thread) (b:int) =
match th.state with Compare -> th.local_b = b | _ -> true end
(* Convert status into an index. *)
function sync_index (th:thread) (b:int) : int =
if sync th b then 0 else 42
(* Thread progression index: if running this thread should make any
progression toward the result, then it will have the following shape:
- A first (optional) loop run for synchronization.
- A second synchronized run until effective progress *)
function prog_index (th:thread) (b:int) : int =
sync_index th b + state_index th.state
val create_thread () : thread
ensures { result.state = ReadA }
let step (th: thread) (ghost a0 b0: int) (a b: ref int)
requires { inv th a0 b0 !a !b }
(* Fair scheduler modelisation: Each time it switch to a thread,
it also writes down the time remaining before it switch to the other.
If it does not switch, this timeout decrease. *)
val ghost scheduled : ref bool
val ghost timer : ref int
val schedule () : bool
writes { scheduled , timer }
ensures { !scheduled = old !scheduled -> 0 <= !timer < old !timer }
ensures { result = !scheduled }
(* Execution of one thread step. *)
let step (th: thread) (ghost d: int) (a b: ref int)
requires { inv th d !a !b }
writes { th, a }
ensures { inv th a0 b0 !a !b }
ensures { inv th d !a !b }
ensures { 0 < !a <= old !a }
ensures { old !a > !a -> old !a >= !a + !b }
ensures { progress_thread th !a !b ->
prog_index (old th) !b > prog_index th !b \/ !a < old !a }
=
match th.state with
| ReadA ->
......@@ -162,20 +223,30 @@ module Interleaving
let parallel_gcd (a0 b0: int) : int
requires { 0 < a0 /\ 0 < b0 }
diverges
ensures { result = gcd a0 b0 }
=
(* shared variables *)
let a = ref a0 in
let b = ref b0 in
let ghost d = gcd a0 b0 in
(* two threads *)
let th1 = create_thread () in
let th2 = create_thread () in
while th1.state <> Halt || th2.state <> Halt do
invariant { inv th1 a0 b0 !a !b /\ inv th2 b0 a0 !b !a }
if any bool then step th1 a0 b0 a b else step th2 b0 a0 b a
invariant { inv th1 d !a !b /\ inv th2 d !b !a }
variant { !a + !b ,
if !a = !b
then prog_index th2 !a + prog_index th1 !b
else if !a < !b
then prog_index th2 !a
else prog_index th1 !b ,
if progress_thread th1 !a !b
then if !scheduled then 1 else 0
else if progress_thread th2 !b !a
then if !scheduled then 0 else 1
else 0 , !timer }
if schedule () then step th1 d a b else step th2 d b a
done;
!a
end
***)
......@@ -5,52 +5,54 @@
<prover id="0" name="CVC4" version="1.4" timelimit="6" memlimit="1000"/>
<prover id="1" name="Z3" version="4.3.1" timelimit="6" memlimit="1000"/>
<prover id="2" name="Spass" version="3.7" timelimit="6" memlimit="1000"/>
<prover id="3" name="Alt-Ergo" version="0.95.2" timelimit="6" memlimit="1000"/>
<prover id="4" name="Vampire" version="0.6" timelimit="6" memlimit="1000"/>
<prover id="5" name="Alt-Ergo" version="0.99.1" timelimit="5" memlimit="1000"/>
<prover id="6" name="CVC3" version="2.4.1" timelimit="5" memlimit="1000"/>
<prover id="7" name="Eprover" version="1.8-001" timelimit="5" memlimit="1000"/>
<file name="../verifythis_2015_parallel_gcd.mlw" expanded="true">
<theory name="ParallelGCD" sum="8319d7f76f67ab787192d931e1a55949">
<goal name="gcd_sub">
<proof prover="2"><result status="valid" time="0.05"/></proof>
<proof prover="4"><result status="valid" time="0.02"/></proof>
<proof prover="4" obsolete="true"><result status="valid" time="0.02"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd" expl="VC for parallel_gcd">
<transf name="split_goal_wp">
<goal name="WP_parameter parallel_gcd.1" expl="1. loop invariant init">
<proof prover="3"><result status="valid" time="0.01" steps="2"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.01" steps="2"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.2" expl="2. loop invariant preservation">
<proof prover="3"><result status="valid" time="0.01" steps="11"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.01" steps="11"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.3" expl="3. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02"/></proof>
<proof prover="2"><result status="valid" time="0.02"/></proof>
<proof prover="3"><result status="valid" time="0.03" steps="21"/></proof>
<proof prover="4"><result status="valid" time="0.12"/></proof>
<proof prover="4" obsolete="true"><result status="valid" time="0.12"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.03" steps="37"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.4" expl="4. loop invariant preservation">
<proof prover="3"><result status="valid" time="0.02" steps="10"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.02" steps="10"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.5" expl="5. loop invariant preservation">
<proof prover="3"><result status="valid" time="0.02" steps="10"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.02" steps="10"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.6" expl="6. loop invariant preservation">
<proof prover="3"><result status="valid" time="0.01" steps="11"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.01" steps="11"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.7" expl="7. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.02"/></proof>
<proof prover="2" timelimit="30"><result status="valid" time="0.09"/></proof>
<proof prover="3"><result status="valid" time="0.02" steps="13"/></proof>
<proof prover="4" timelimit="30"><result status="valid" time="0.09"/></proof>
<proof prover="4" timelimit="30" obsolete="true"><result status="valid" time="0.09"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.02" steps="13"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.8" expl="8. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01"/></proof>
<proof prover="1"><result status="valid" time="0.01"/></proof>
<proof prover="3"><result status="valid" time="0.01" steps="10"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.01" steps="10"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.9" expl="9. loop invariant preservation">
<proof prover="0"><result status="valid" time="0.01"/></proof>
<proof prover="1"><result status="valid" time="0.00"/></proof>
<proof prover="3"><result status="valid" time="0.00" steps="10"/></proof>
<proof prover="5" timelimit="6"><result status="valid" time="0.00" steps="10"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.10" expl="10. postcondition">
<proof prover="0"><result status="valid" time="0.03"/></proof>
......@@ -58,5 +60,133 @@
</transf>
</goal>
</theory>
<theory name="Interleaving" sum="8a7f2e36501d957e8de13171fbd9f63c" expanded="true">
<goal name="gcd_sub">
<proof prover="7"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="WP_parameter step" expl="VC for step">
<transf name="split_goal_wp">
<goal name="WP_parameter step.1" expl="1. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="8"/></proof>
</goal>
<goal name="WP_parameter step.2" expl="2. postcondition">
<proof prover="5"><result status="valid" time="0.01" steps="5"/></proof>
</goal>
<goal name="WP_parameter step.3" expl="3. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="4"/></proof>
</goal>
<goal name="WP_parameter step.4" expl="4. postcondition">
<proof prover="5"><result status="valid" time="0.89" steps="180"/></proof>
</goal>
<goal name="WP_parameter step.5" expl="5. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="11"/></proof>
</goal>
<goal name="WP_parameter step.6" expl="6. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="5"/></proof>
</goal>
<goal name="WP_parameter step.7" expl="7. postcondition">
<proof prover="5"><result status="valid" time="0.01" steps="4"/></proof>
</goal>
<goal name="WP_parameter step.8" expl="8. postcondition">
<proof prover="5"><result status="valid" time="1.86" steps="269"/></proof>
</goal>
<goal name="WP_parameter step.9" expl="9. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="14"/></proof>
</goal>
<goal name="WP_parameter step.10" expl="10. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="5"/></proof>
</goal>
<goal name="WP_parameter step.11" expl="11. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="4"/></proof>
</goal>
<goal name="WP_parameter step.12" expl="12. postcondition">
<proof prover="6"><result status="valid" time="0.04"/></proof>
</goal>
<goal name="WP_parameter step.13" expl="13. postcondition">
<proof prover="5"><result status="valid" time="0.94" steps="41"/></proof>
</goal>
<goal name="WP_parameter step.14" expl="14. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="11"/></proof>
</goal>
<goal name="WP_parameter step.15" expl="15. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="12"/></proof>
</goal>
<goal name="WP_parameter step.16" expl="16. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="13"/></proof>
</goal>
<goal name="WP_parameter step.17" expl="17. postcondition">
<proof prover="5"><result status="valid" time="0.01" steps="11"/></proof>
</goal>
<goal name="WP_parameter step.18" expl="18. postcondition">
<proof prover="5"><result status="valid" time="0.02" steps="6"/></proof>
</goal>
<goal name="WP_parameter step.19" expl="19. postcondition">
<proof prover="5"><result status="valid" time="0.01" steps="5"/></proof>
</goal>
<goal name="WP_parameter step.20" expl="20. postcondition">
<proof prover="6"><result status="valid" time="0.03"/></proof>
</goal>
<goal name="WP_parameter step.21" expl="21. postcondition">
<proof prover="5"><result status="valid" time="0.01" steps="2"/></proof>
</goal>
<goal name="WP_parameter step.22" expl="22. postcondition">
<proof prover="5"><result status="valid" time="0.01" steps="3"/></proof>
</goal>
<goal name="WP_parameter step.23" expl="23. postcondition">
<proof prover="5"><result status="valid" time="0.01" steps="2"/></proof>
</goal>
<goal name="WP_parameter step.24" expl="24. postcondition">
<proof prover="5"><result status="valid" time="0.01" steps="10"/></proof>
</goal>
</transf>
</goal>
<goal name="WP_parameter parallel_gcd" expl="VC for parallel_gcd">
<transf name="split_goal_wp">
<goal name="WP_parameter parallel_gcd.1" expl="1. loop invariant init">
<proof prover="5"><result status="valid" time="0.04" steps="16"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.2" expl="2. precondition">
<proof prover="5"><result status="valid" time="0.01" steps="7"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.3" expl="3. loop invariant preservation">
<proof prover="5"><result status="valid" time="0.19" steps="98"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.4" expl="4. loop variant decrease">
<transf name="inline_goal">
<goal name="WP_parameter parallel_gcd.4.1" expl="1. loop variant decrease">
<transf name="inline_goal">
<goal name="WP_parameter parallel_gcd.4.1.1" expl="1. loop variant decrease">
<proof prover="0" timelimit="5"><result status="valid" time="0.13"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal>
<goal name="WP_parameter parallel_gcd.5" expl="5. precondition">
<proof prover="5"><result status="valid" time="0.01" steps="7"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.6" expl="6. loop invariant preservation">
<proof prover="5"><result status="valid" time="0.05" steps="59"/></proof>
</goal>
<goal name="WP_parameter parallel_gcd.7" expl="7. loop variant decrease">
<transf name="inline_goal">
<goal name="WP_parameter parallel_gcd.7.1" expl="1. loop variant decrease">
<transf name="inline_goal">
<goal name="WP_parameter parallel_gcd.7.1.1" expl="1. loop variant decrease">
<proof prover="0" timelimit="5"><result status="valid" time="0.17"/></proof>
</goal>
</transf>
</goal>
</transf>
</goal>
<goal name="WP_parameter parallel_gcd.8" expl="8. postcondition">
<proof prover="1" timelimit="5"><result status="valid" time="0.03"/></proof>
<proof prover="2" timelimit="5"><result status="valid" time="1.10"/></proof>
<proof prover="6"><result status="valid" time="0.06"/></proof>
<proof prover="7"><result status="valid" time="0.07"/></proof>
</goal>
</transf>
</goal>
</theory>
</file>
</why3session>
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