Library CompOptCert.PromiseInjection
Require Import sflib.
Require Import Axioms.
Require Import Basic.
Require Import DataStructure.
Require Import Loc.
Require Import Coqlib.
Require Import Language.
Require Import Time.
Require Import Event.
Require Import View.
Require Import Cell.
Require Import Memory.
Require Import TView.
Require Import Local.
Require Import Thread.
Require Import NPThread.
Require Import Configuration.
Require Import MsgMapping.
Require Import MemoryReorder.
Require Import ReorderPromise.
Require Import ReorderReserve.
Require Import ReorderCancel.
Inductive promise_inj: Mapping → Memory.t → Memory.t → Prop :=
| Promise_inj_intro
promises1 promises2 inj
(SOUND: ∀ loc to val from released,
Memory.get loc to promises1 = Some (from, Message.concrete val released) →
∃ to' released',
inj loc to = Some to' ∧
Memory.get loc to' promises2 = Some (from, Message.concrete val released'))
(COMPLETE: ∀ loc to' val from' released',
Memory.get loc to' promises2 = Some (from', Message.concrete val released') →
∃ to released,
inj loc to = Some to' ∧
Memory.get loc to promises1 = Some (from', Message.concrete val released))
(RSV_SOUND: ∀ loc to from,
Memory.get loc to promises1 = Some (from, Message.reserve) →
Memory.get loc to promises2 = Some (from, Message.reserve))
(RSV_COMPLETE: ∀ loc to from,
Memory.get loc to promises2 = Some (from, Message.reserve) →
Memory.get loc to promises1 = Some (from, Message.reserve)):
promise_inj inj promises1 promises2.
Lemma promise_inj_incr
inj inj' promises promises'
(P_INJ: promise_inj inj promises promises')
(INJ_INCR: incr_inj inj inj'):
promise_inj inj' promises promises'.
Proof.
inv P_INJ.
econs; ii; eauto.
{
eapply SOUND in H; eauto.
des; eauto.
}
{
eapply COMPLETE in H; eauto.
des; eauto.
}
Qed.
Lemma promise_inj_remove_reseve
inj promises promises' loc from to promises1 promises1'
(P_INJ: promise_inj inj promises promises')
(REMOVE_RSV1: Memory.remove promises loc from to Message.reserve promises1)
(REMOVE_RSV2: Memory.remove promises' loc from to Message.reserve promises1'):
promise_inj inj promises1 promises1'.
Proof.
inv P_INJ.
econs; ii.
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss; subst; eauto.
eapply SOUND in H; eauto.
destruct H as (to' & released' & INJ & GET).
∃ to', released'. split; eauto.
erewrite Memory.remove_o; eauto.
des_if; eauto. ss. des; subst. ss.
clear - REMOVE_RSV2 GET.
exploit Memory.remove_get0; eauto; ii; des.
rewrite GET in GET0; inv GET0; eauto.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss; des; eauto.
exploit COMPLETE; eauto; ii; des.
exploit Memory.remove_get1; [eapply REMOVE_RSV1 | eauto..]. ii.
des; subst; ss.
do 2 eexists. split; eauto.
exploit COMPLETE; eauto; ii; des.
exploit Memory.remove_get1; [eapply REMOVE_RSV1 | eauto..]. ii.
des; subst; ss.
eapply Memory.remove_get0 in REMOVE_RSV1; eauto; des.
rewrite GET in H1. inv H1.
do 2 eexists. split; eauto.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss.
eapply RSV_SOUND in H.
exploit Memory.remove_get1; eauto. ii.
destruct H0; eauto.
destruct H0; subst; des; ss.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.remove_o; eauto.
des_if; eauto.
ss; des; subst; ss.
}
Qed.
Lemma promise_inj_remove_concrete
inj promises promises' loc from to msg from' to' msg' promises1 promises1'
(P_INJ: promise_inj inj promises promises')
(REMOVE_RSV1: Memory.remove promises loc from to msg promises1)
(REMOVE_RSV2: Memory.remove promises' loc from' to' msg' promises1')
(INJ: inj loc to = Some to')
(MON: monotonic_inj inj)
(CONCRETE_MSG: ∃ val released, msg = Message.concrete val released):
promise_inj inj promises1 promises1'.
Proof.
des; subst.
inv P_INJ.
econs; ii.
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss.
exploit SOUND; eauto. ii.
destruct H0 as (to1 & released1 & INJ1 & GET1).
destruct (Loc.eq_dec loc0 loc).
{
des; subst; ss.
assert(to' ≠ to1).
{
eapply monotonic_inj_implies_disj_mapping; eauto.
}
eapply Memory.remove_get1 in GET1; eauto; des; subst; ss.
do 3 eexists; eauto.
}
{
eapply Memory.remove_get1 in GET1; eauto; des; subst; ss.
do 3 eexists; eauto.
do 3 eexists; eauto.
}
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss; des; ss; eauto.
exploit COMPLETE; eauto; ii; des.
exploit Memory.remove_get1; [eapply REMOVE_RSV1 | eauto..]. ii.
des; subst; ss.
do 2 eexists. split; eauto.
exploit COMPLETE; eauto; ii; des.
exploit Memory.remove_get1; [eapply REMOVE_RSV1 | eauto..]. ii.
des; subst; ss.
rewrite INJ in H0; inv H0; ss.
do 2 eexists. split; eauto.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss; des; ss; eauto.
eapply RSV_SOUND in H; eauto.
erewrite Memory.remove_o; eauto.
des_if; eauto; ss; des; subst; ss.
eapply RSV_SOUND in H; eauto.
erewrite Memory.remove_o; eauto.
des_if; eauto; ss; des; subst; ss.
exploit Memory.remove_get0; eauto; ii; des.
rewrite GET in H; inv H.
exploit Memory.remove_get0; [eapply REMOVE_RSV1 | eauto..]; ii; des.
eapply SOUND in GET1; eauto; des.
rewrite INJ in GET1; inv GET1.
rewrite GET in GET3. inv GET3.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.remove_o; eauto.
des_if. ss. destruct a; subst. des; ss.
exploit Memory.remove_get0; [eapply REMOVE_RSV1 | eauto..]; ii; des.
rewrite H in GET; inv GET.
ss.
}
Qed.
Lemma promise_inj_split
inj promises promises' loc from to ts val msg1 msg2 from' to' msg1' msg2' ts' promises1 promises1'
(P_INJ: promise_inj inj promises promises')
(SPLIT1: Memory.split promises loc from to ts msg1 msg2 promises1)
(SPLIT2: Memory.split promises' loc from' to' ts' msg1' msg2' promises1')
(INJ: inj loc to = Some to')
(INJ': inj loc ts = Some ts')
(SPLIT_EQ: to = to')
(MON: monotonic_inj inj)
(CONCRETE_MSG1: ∃ released, msg1 = Message.concrete val released)
(CONCRETE_MSG1': ∃ released, msg1' = Message.concrete val released)
(CONCRETE_MSG2: ∃ val released, msg2 = Message.concrete val released)
(CONCRETE_MSG2': ∃ val released, msg2' = Message.concrete val released):
promise_inj inj promises1 promises1'.
Proof.
subst. des; subst.
inv P_INJ.
assert(from = from').
{
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
eapply SOUND in GET0; eauto. des.
rewrite INJ' in GET0. inv GET0.
rewrite GET7 in GET4. inv GET4. eauto.
}
subst.
econs; ii.
{
dup H.
erewrite Memory.split_o in H; eauto.
des_ifH H; eauto; ss; des; subst.
{
inv H.
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
rewrite GET1 in H0; inv H0.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
do 2 eexists. split; eauto.
}
{
des_ifH H; ss; des; subst; ss.
exploit SOUND; [eapply H | eauto..]; ii; des.
assert(Memory.get loc0 to'0 promises1' = Some (from, Message.concrete val2 released')).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
exploit SOUND; [eapply H | eauto..]; ii; des.
assert(Memory.get loc0 to'0 promises1' = Some (from, Message.concrete val2 released')).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
}
des_ifH H; ss; des; subst; ss.
{
inv H.
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
rewrite GET2 in H0; inv H0.
exploit SOUND; eauto. ii; des.
rewrite INJ' in H. inv H.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
rewrite GET4 in H0. inv H0.
do 2 eexists. split; eauto.
}
{
exploit SOUND; eauto. ii; des.
assert(Memory.get loc0 to'0 promises1' = Some (from, Message.concrete val2 released')).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
}
{
exploit SOUND; eauto. ii; des.
do 2 eexists.
split; eauto.
erewrite Memory.split_o; eauto. instantiate (1 := released').
des_if; ss; des; subst.
clear - INJ o H1 MON.
exploit monotonic_inj_implies_disj_mapping; [eapply MON | eapply H1 | eapply INJ | eapply o | eauto..].
ii; ss.
des_if; ss; des; subst; ss.
des_if; ss; des; subst; ss.
clear - INJ' o0 H1 MON.
exploit monotonic_inj_implies_disj_mapping; [eapply MON | eapply H1 | eapply INJ' | eapply o0 | eauto..].
ii; ss.
}
}
{
dup H.
erewrite Memory.split_o in H; eauto.
des_ifH H; eauto; ss; des; subst.
{
inv H.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
rewrite GET1 in H0; inv H0.
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
do 2 eexists. split; eauto.
}
{
des_ifH H; ss; des; subst; ss.
exploit COMPLETE; [eapply H | eauto..]; ii; des.
assert(Memory.get loc0 to promises1 = Some (from'0, Message.concrete val2 released3)).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
exploit COMPLETE; [eapply H | eauto..]; ii; des.
assert(Memory.get loc0 to promises1 = Some (from'0, Message.concrete val2 released3)).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
}
des_ifH H; ss; des; subst; ss.
{
inv H.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
rewrite GET2 in H0; inv H0.
exploit COMPLETE; eauto. ii; des.
assert(to = ts).
{
clear - MON INJ' H.
destruct(Time.eq_dec to ts); eauto.
exploit monotonic_inj_implies_disj_mapping; [eapply MON | eapply H | eapply INJ' | eapply n | eauto..].
ii; ss.
}
subst.
rewrite INJ' in H. inv H.
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
rewrite GET4 in H0. inv H0.
do 2 eexists. split; eauto.
}
{
exploit COMPLETE; eauto. ii; des.
assert(Memory.get loc0 to promises1 = Some (from'0, Message.concrete val2 released3)).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
}
{
exploit COMPLETE; eauto. ii; des.
do 2 eexists.
split; eauto.
erewrite Memory.split_o; eauto. instantiate (1 := released3).
des_if; ss; des; subst.
clear - INJ o H1 MON.
rewrite INJ in H1. inv H1. ss.
des_if; ss; des; subst; ss.
des_if; ss; des; subst; ss.
rewrite INJ' in H1. inv H1. ss.
}
}
{
erewrite Memory.split_o in H; eauto.
des_ifH H; eauto; ss; des; ss.
des_ifH H; eauto; ss; des; ss.
eapply RSV_SOUND in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
eapply RSV_SOUND in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_ifH H; eauto; ss; des; ss.
eapply RSV_SOUND in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
eapply RSV_SOUND in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
subst.
exploit Memory.split_get0; [eapply SPLIT2 | eauto]; ii; des.
rewrite GET0 in H. inv H.
}
{
erewrite Memory.split_o in H; eauto.
des_ifH H; eauto; ss; des; ss.
des_ifH H; eauto; ss; des; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_ifH H; eauto; ss; des; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
subst.
exploit Memory.split_get0; [eapply SPLIT1 | eauto]; ii; des.
rewrite GET0 in H. inv H.
}
Qed.
Lemma promise_inj_lower
inj promises promises' loc from to msg1 msg2 from' to' msg1' msg2' promises1 promises1'
(P_INJ: promise_inj inj promises promises')
(LOWER1: Memory.lower promises loc from to msg1 msg2 promises1)
(LOWER2: Memory.lower promises' loc from' to' msg1' msg2' promises1')
(CONCRETE: ∃ val released, msg1 = Message.concrete val released)
(INJ: inj loc to = Some to'):
promise_inj inj promises1 promises1'.
Proof.
inv P_INJ. des; subst.
econs; ii.
{
erewrite Memory.lower_o in H; eauto.
des_ifH H; eauto; ss; des; subst; ss.
{
inv H.
eapply Memory.lower_get0 in LOWER1; eauto; des.
inv MSG_LE.
exploit SOUND; eauto; ii; des.
rewrite INJ in H; inv H.
eapply Memory.lower_get0 in LOWER2; eauto; des.
rewrite GET1 in H0; inv H0.
inv MSG_LE. do 2 eexists. split; eauto.
}
{
eapply SOUND in H; eauto; des; subst.
eapply Memory.lower_get1 in LOWER2; eauto; des.
inv MSG_LE.
do 2 eexists.
split; eauto.
}
{
eapply SOUND in H; eauto. des; subst.
eapply Memory.lower_get1 in LOWER2; eauto; des.
inv MSG_LE.
do 2 eexists.
split; eauto.
}
}
{
erewrite Memory.lower_o in H; eauto.
des_ifH H; ss; des; subst; eauto.
{
inv H.
eapply Memory.lower_get0 in LOWER1; eauto; des. inv MSG_LE.
eapply Memory.lower_get0 in LOWER2; eauto; des. inv MSG_LE.
exploit SOUND; eauto. ii; des.
rewrite INJ in H; inv H.
rewrite GET1 in H0. inv H0.
do 2 eexists. split; eauto.
exploit SOUND; eauto. ii; des.
rewrite INJ in H; inv H.
rewrite GET1 in H0; inv H0.
}
{
eapply COMPLETE in H; eauto. des.
exploit Memory.lower_get1; [eapply LOWER1 | eauto..].
ii; des. inv MSG_LE.
do 2 eexists. split; eauto.
}
{
eapply COMPLETE in H; eauto. des.
exploit Memory.lower_get1; [eapply LOWER1 | eauto..].
ii; des. inv MSG_LE.
do 2 eexists. split; eauto.
}
}
{
erewrite Memory.lower_o in H; eauto.
des_ifH H; ss; des; subst; eauto.
{
inv H.
eapply Memory.lower_get0 in LOWER1; eauto; des.
inv MSG_LE.
}
{
eapply RSV_SOUND in H.
erewrite Memory.lower_o; eauto.
des_if; eauto; ss; des; subst; ss.
}
{
eapply RSV_SOUND in H.
erewrite Memory.lower_o; eauto.
des_if; eauto; ss; des; subst; ss.
eapply Memory.lower_get0 in LOWER1; eauto; des.
eapply Memory.lower_get0 in LOWER2; eauto; des.
eapply SOUND in GET; des; eauto.
rewrite INJ in GET; inv GET.
rewrite GET3 in GET1; inv GET1.
inv MSG_LE.
rewrite GET3 in H. inv H.
}
}
{
erewrite Memory.lower_o in H; eauto.
des_ifH H; eauto; ss; des; ss; subst.
{
inv H.
eapply Memory.lower_get0 in LOWER1; eauto; des.
inv MSG_LE.
eapply SOUND in GET; eauto; des.
rewrite INJ in GET; inv GET.
eapply Memory.lower_get0 in LOWER2; eauto; des.
rewrite GET1 in GET; inv GET.
inv MSG_LE.
}
{
eapply RSV_COMPLETE in H.
erewrite Memory.lower_o; eauto.
des_if; eauto; ss; subst; des; ss.
}
{
eapply RSV_COMPLETE in H.
erewrite Memory.lower_o; eauto.
des_if; eauto; ss; des; subst; ss.
eapply Memory.lower_get0 in LOWER1; eauto; des.
rewrite GET in H. inv H.
}
}
Qed.
Lemma mem_nonsynch_loc_msgInj
promises promises' mem mem' inj loc
(MEM_INJ: MsgInj inj mem mem')
(LE1: Memory.le promises mem)
(LE2: Memory.le promises' mem')
(PROM_INJ: promise_inj inj promises promises')
(NONSYNC_LOC: Memory.nonsynch_loc loc promises):
Memory.nonsynch_loc loc promises'.
Proof.
unfold Memory.nonsynch_loc in *; ii.
inv PROM_INJ.
destruct msg; ss.
dup GET.
exploit COMPLETE; eauto. ii; des.
exploit NONSYNC_LOC; eauto. ii; ss; subst.
inv MEM_INJ.
dup H0.
eapply LE1 in H1.
eapply SOUND0 in H1; eauto. des.
rewrite H in H1. inv H1.
unfold opt_ViewInj in H2. destruct R'; ss.
eapply LE2 in GET.
rewrite GET in H3. inv H3; eauto.
Qed.
Lemma mem_nonsynch_msgInj
promises promises' mem mem' inj
(MEM_INJ: MsgInj inj mem mem')
(LE1: Memory.le promises mem)
(LE2: Memory.le promises' mem')
(PROM_INJ: promise_inj inj promises promises')
(NONSYNC: Memory.nonsynch promises):
Memory.nonsynch promises'.
Proof.
unfold Memory.nonsynch in ×. intro loc.
specialize (NONSYNC loc).
eapply mem_nonsynch_loc_msgInj; eauto.
Qed.
Lemma promise_inj_bot
promises promises' inj
(PROM_INJ: promise_inj inj promises promises')
(BOT: promises = Memory.bot):
promises' = Memory.bot.
Proof.
subst.
inv PROM_INJ.
destruct (classic (∃ loc to from msg, Memory.get loc to promises' = Some (from, msg))).
{
des.
destruct msg.
eapply COMPLETE in H; eauto; des.
rewrite Memory.bot_get in H0; ss.
eapply RSV_COMPLETE in H; eauto; des.
rewrite Memory.bot_get in H; ss.
}
{
eapply Memory.ext; ii.
rewrite Memory.bot_get.
destruct (Memory.get loc ts promises') eqn:Heqe; eauto.
destruct p.
contradiction H; eauto.
}
Qed.
Lemma write_step_promise_inj_stable
lc1 sc1 mem1 loc from1 to1 val releasedr1 releasedw1 ord lc1' sc1' mem1' kind1 lo
lc2 sc2 mem2 from2 to2 releasedr2 releasedw2 lc2' sc2' mem2' kind2
inj inj'
(WRITE1: Local.write_step lc1 sc1 mem1 loc from1 to1 val releasedr1 releasedw1 ord lc1' sc1' mem1' kind1 lo)
(WRITE2: Local.write_step lc2 sc2 mem2 loc from2 to2 val releasedr2 releasedw2 ord lc2' sc2' mem2' kind2 lo)
(PROM_INJ: promise_inj inj (Local.promises lc1) (Local.promises lc2))
(INJ_INCR: incr_inj inj inj')
(INJ: inj' loc to1 = Some to2)
(MON: monotonic_inj inj')
(KIND_MATCH: kind_match kind1 kind2)
(SPLIT: ∀ t val R, kind1 = Memory.op_kind_split t (Message.concrete val R) →
∃ t' val' R', kind2 = Memory.op_kind_split t' (Message.concrete val' R') ∧
to1 = to2 ∧ inj loc t = Some t'):
promise_inj inj' (Local.promises lc1') (Local.promises lc2').
Proof.
inv WRITE1; ss. inv WRITE. inv PROMISE.
- destruct kind2; ss.
inv WRITE2; ss. inv WRITE. inv PROMISE.
assert(Local.promises lc1 = promises2).
{
eapply MemoryMerge.MemoryMerge.add_remove; eauto.
}
subst.
assert(Local.promises lc2 = promises1).
{
eapply MemoryMerge.MemoryMerge.add_remove; eauto.
}
subst.
eapply promise_inj_incr; eauto.
- des; subst. inv RESERVE.
destruct kind2; ss.
exploit SPLIT; eauto. ii; des; subst.
inv H. des; subst.
assert(promise_inj inj' (Local.promises lc1) (Local.promises lc2)).
{
eapply promise_inj_incr; eauto.
}
inv WRITE2; ss.
inv WRITE. inv PROMISE. des; ss.
inv RESERVE. inv RESERVEORIGINAL.
exploit promise_inj_split; eauto.
ii.
eapply promise_inj_remove_concrete; eauto.
- des; subst.
destruct kind2; ss.
inv WRITE2; ss. inv WRITE. inv PROMISE. des; subst.
subst.
assert(INJ'': inj loc to1 = Some to2).
{
clear - PROM_INJ INJ INJ_INCR PROMISES PROMISES0.
exploit Memory.lower_get0; [eapply PROMISES | eauto..]. ii; des.
inv PROM_INJ.
eapply SOUND in GET; eauto. des.
dup GET.
eapply INJ_INCR in GET. rewrite GET in INJ. inv INJ. eauto.
}
exploit promise_inj_lower; eauto. ii.
eapply promise_inj_incr in H; eauto.
eapply promise_inj_remove_concrete in H; eauto.
- ss.
Qed.
Require Import Axioms.
Require Import Basic.
Require Import DataStructure.
Require Import Loc.
Require Import Coqlib.
Require Import Language.
Require Import Time.
Require Import Event.
Require Import View.
Require Import Cell.
Require Import Memory.
Require Import TView.
Require Import Local.
Require Import Thread.
Require Import NPThread.
Require Import Configuration.
Require Import MsgMapping.
Require Import MemoryReorder.
Require Import ReorderPromise.
Require Import ReorderReserve.
Require Import ReorderCancel.
Inductive promise_inj: Mapping → Memory.t → Memory.t → Prop :=
| Promise_inj_intro
promises1 promises2 inj
(SOUND: ∀ loc to val from released,
Memory.get loc to promises1 = Some (from, Message.concrete val released) →
∃ to' released',
inj loc to = Some to' ∧
Memory.get loc to' promises2 = Some (from, Message.concrete val released'))
(COMPLETE: ∀ loc to' val from' released',
Memory.get loc to' promises2 = Some (from', Message.concrete val released') →
∃ to released,
inj loc to = Some to' ∧
Memory.get loc to promises1 = Some (from', Message.concrete val released))
(RSV_SOUND: ∀ loc to from,
Memory.get loc to promises1 = Some (from, Message.reserve) →
Memory.get loc to promises2 = Some (from, Message.reserve))
(RSV_COMPLETE: ∀ loc to from,
Memory.get loc to promises2 = Some (from, Message.reserve) →
Memory.get loc to promises1 = Some (from, Message.reserve)):
promise_inj inj promises1 promises2.
Lemma promise_inj_incr
inj inj' promises promises'
(P_INJ: promise_inj inj promises promises')
(INJ_INCR: incr_inj inj inj'):
promise_inj inj' promises promises'.
Proof.
inv P_INJ.
econs; ii; eauto.
{
eapply SOUND in H; eauto.
des; eauto.
}
{
eapply COMPLETE in H; eauto.
des; eauto.
}
Qed.
Lemma promise_inj_remove_reseve
inj promises promises' loc from to promises1 promises1'
(P_INJ: promise_inj inj promises promises')
(REMOVE_RSV1: Memory.remove promises loc from to Message.reserve promises1)
(REMOVE_RSV2: Memory.remove promises' loc from to Message.reserve promises1'):
promise_inj inj promises1 promises1'.
Proof.
inv P_INJ.
econs; ii.
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss; subst; eauto.
eapply SOUND in H; eauto.
destruct H as (to' & released' & INJ & GET).
∃ to', released'. split; eauto.
erewrite Memory.remove_o; eauto.
des_if; eauto. ss. des; subst. ss.
clear - REMOVE_RSV2 GET.
exploit Memory.remove_get0; eauto; ii; des.
rewrite GET in GET0; inv GET0; eauto.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss; des; eauto.
exploit COMPLETE; eauto; ii; des.
exploit Memory.remove_get1; [eapply REMOVE_RSV1 | eauto..]. ii.
des; subst; ss.
do 2 eexists. split; eauto.
exploit COMPLETE; eauto; ii; des.
exploit Memory.remove_get1; [eapply REMOVE_RSV1 | eauto..]. ii.
des; subst; ss.
eapply Memory.remove_get0 in REMOVE_RSV1; eauto; des.
rewrite GET in H1. inv H1.
do 2 eexists. split; eauto.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss.
eapply RSV_SOUND in H.
exploit Memory.remove_get1; eauto. ii.
destruct H0; eauto.
destruct H0; subst; des; ss.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.remove_o; eauto.
des_if; eauto.
ss; des; subst; ss.
}
Qed.
Lemma promise_inj_remove_concrete
inj promises promises' loc from to msg from' to' msg' promises1 promises1'
(P_INJ: promise_inj inj promises promises')
(REMOVE_RSV1: Memory.remove promises loc from to msg promises1)
(REMOVE_RSV2: Memory.remove promises' loc from' to' msg' promises1')
(INJ: inj loc to = Some to')
(MON: monotonic_inj inj)
(CONCRETE_MSG: ∃ val released, msg = Message.concrete val released):
promise_inj inj promises1 promises1'.
Proof.
des; subst.
inv P_INJ.
econs; ii.
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss.
exploit SOUND; eauto. ii.
destruct H0 as (to1 & released1 & INJ1 & GET1).
destruct (Loc.eq_dec loc0 loc).
{
des; subst; ss.
assert(to' ≠ to1).
{
eapply monotonic_inj_implies_disj_mapping; eauto.
}
eapply Memory.remove_get1 in GET1; eauto; des; subst; ss.
do 3 eexists; eauto.
}
{
eapply Memory.remove_get1 in GET1; eauto; des; subst; ss.
do 3 eexists; eauto.
do 3 eexists; eauto.
}
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss; des; ss; eauto.
exploit COMPLETE; eauto; ii; des.
exploit Memory.remove_get1; [eapply REMOVE_RSV1 | eauto..]. ii.
des; subst; ss.
do 2 eexists. split; eauto.
exploit COMPLETE; eauto; ii; des.
exploit Memory.remove_get1; [eapply REMOVE_RSV1 | eauto..]. ii.
des; subst; ss.
rewrite INJ in H0; inv H0; ss.
do 2 eexists. split; eauto.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss; des; ss; eauto.
eapply RSV_SOUND in H; eauto.
erewrite Memory.remove_o; eauto.
des_if; eauto; ss; des; subst; ss.
eapply RSV_SOUND in H; eauto.
erewrite Memory.remove_o; eauto.
des_if; eauto; ss; des; subst; ss.
exploit Memory.remove_get0; eauto; ii; des.
rewrite GET in H; inv H.
exploit Memory.remove_get0; [eapply REMOVE_RSV1 | eauto..]; ii; des.
eapply SOUND in GET1; eauto; des.
rewrite INJ in GET1; inv GET1.
rewrite GET in GET3. inv GET3.
}
{
erewrite Memory.remove_o in H; eauto.
des_ifH H; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.remove_o; eauto.
des_if. ss. destruct a; subst. des; ss.
exploit Memory.remove_get0; [eapply REMOVE_RSV1 | eauto..]; ii; des.
rewrite H in GET; inv GET.
ss.
}
Qed.
Lemma promise_inj_split
inj promises promises' loc from to ts val msg1 msg2 from' to' msg1' msg2' ts' promises1 promises1'
(P_INJ: promise_inj inj promises promises')
(SPLIT1: Memory.split promises loc from to ts msg1 msg2 promises1)
(SPLIT2: Memory.split promises' loc from' to' ts' msg1' msg2' promises1')
(INJ: inj loc to = Some to')
(INJ': inj loc ts = Some ts')
(SPLIT_EQ: to = to')
(MON: monotonic_inj inj)
(CONCRETE_MSG1: ∃ released, msg1 = Message.concrete val released)
(CONCRETE_MSG1': ∃ released, msg1' = Message.concrete val released)
(CONCRETE_MSG2: ∃ val released, msg2 = Message.concrete val released)
(CONCRETE_MSG2': ∃ val released, msg2' = Message.concrete val released):
promise_inj inj promises1 promises1'.
Proof.
subst. des; subst.
inv P_INJ.
assert(from = from').
{
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
eapply SOUND in GET0; eauto. des.
rewrite INJ' in GET0. inv GET0.
rewrite GET7 in GET4. inv GET4. eauto.
}
subst.
econs; ii.
{
dup H.
erewrite Memory.split_o in H; eauto.
des_ifH H; eauto; ss; des; subst.
{
inv H.
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
rewrite GET1 in H0; inv H0.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
do 2 eexists. split; eauto.
}
{
des_ifH H; ss; des; subst; ss.
exploit SOUND; [eapply H | eauto..]; ii; des.
assert(Memory.get loc0 to'0 promises1' = Some (from, Message.concrete val2 released')).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
exploit SOUND; [eapply H | eauto..]; ii; des.
assert(Memory.get loc0 to'0 promises1' = Some (from, Message.concrete val2 released')).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
}
des_ifH H; ss; des; subst; ss.
{
inv H.
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
rewrite GET2 in H0; inv H0.
exploit SOUND; eauto. ii; des.
rewrite INJ' in H. inv H.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
rewrite GET4 in H0. inv H0.
do 2 eexists. split; eauto.
}
{
exploit SOUND; eauto. ii; des.
assert(Memory.get loc0 to'0 promises1' = Some (from, Message.concrete val2 released')).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
}
{
exploit SOUND; eauto. ii; des.
do 2 eexists.
split; eauto.
erewrite Memory.split_o; eauto. instantiate (1 := released').
des_if; ss; des; subst.
clear - INJ o H1 MON.
exploit monotonic_inj_implies_disj_mapping; [eapply MON | eapply H1 | eapply INJ | eapply o | eauto..].
ii; ss.
des_if; ss; des; subst; ss.
des_if; ss; des; subst; ss.
clear - INJ' o0 H1 MON.
exploit monotonic_inj_implies_disj_mapping; [eapply MON | eapply H1 | eapply INJ' | eapply o0 | eauto..].
ii; ss.
}
}
{
dup H.
erewrite Memory.split_o in H; eauto.
des_ifH H; eauto; ss; des; subst.
{
inv H.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
rewrite GET1 in H0; inv H0.
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
do 2 eexists. split; eauto.
}
{
des_ifH H; ss; des; subst; ss.
exploit COMPLETE; [eapply H | eauto..]; ii; des.
assert(Memory.get loc0 to promises1 = Some (from'0, Message.concrete val2 released3)).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
exploit COMPLETE; [eapply H | eauto..]; ii; des.
assert(Memory.get loc0 to promises1 = Some (from'0, Message.concrete val2 released3)).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
}
des_ifH H; ss; des; subst; ss.
{
inv H.
exploit Memory.split_get0; [eapply SPLIT2 | eauto..]. ii; des.
rewrite GET2 in H0; inv H0.
exploit COMPLETE; eauto. ii; des.
assert(to = ts).
{
clear - MON INJ' H.
destruct(Time.eq_dec to ts); eauto.
exploit monotonic_inj_implies_disj_mapping; [eapply MON | eapply H | eapply INJ' | eapply n | eauto..].
ii; ss.
}
subst.
rewrite INJ' in H. inv H.
exploit Memory.split_get0; [eapply SPLIT1 | eauto..]. ii; des.
rewrite GET4 in H0. inv H0.
do 2 eexists. split; eauto.
}
{
exploit COMPLETE; eauto. ii; des.
assert(Memory.get loc0 to promises1 = Some (from'0, Message.concrete val2 released3)).
{
erewrite Memory.split_o; eauto.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
des_if; ss; subst; des; subst; ss.
}
do 2 eexists. split; eauto.
}
{
exploit COMPLETE; eauto. ii; des.
do 2 eexists.
split; eauto.
erewrite Memory.split_o; eauto. instantiate (1 := released3).
des_if; ss; des; subst.
clear - INJ o H1 MON.
rewrite INJ in H1. inv H1. ss.
des_if; ss; des; subst; ss.
des_if; ss; des; subst; ss.
rewrite INJ' in H1. inv H1. ss.
}
}
{
erewrite Memory.split_o in H; eauto.
des_ifH H; eauto; ss; des; ss.
des_ifH H; eauto; ss; des; ss.
eapply RSV_SOUND in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
eapply RSV_SOUND in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_ifH H; eauto; ss; des; ss.
eapply RSV_SOUND in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
eapply RSV_SOUND in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
subst.
exploit Memory.split_get0; [eapply SPLIT2 | eauto]; ii; des.
rewrite GET0 in H. inv H.
}
{
erewrite Memory.split_o in H; eauto.
des_ifH H; eauto; ss; des; ss.
des_ifH H; eauto; ss; des; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_ifH H; eauto; ss; des; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
eapply RSV_COMPLETE in H.
erewrite Memory.split_o; eauto.
des_if; ss; des; ss.
des_if; ss; des; ss.
des_if; ss; des; ss.
subst.
exploit Memory.split_get0; [eapply SPLIT1 | eauto]; ii; des.
rewrite GET0 in H. inv H.
}
Qed.
Lemma promise_inj_lower
inj promises promises' loc from to msg1 msg2 from' to' msg1' msg2' promises1 promises1'
(P_INJ: promise_inj inj promises promises')
(LOWER1: Memory.lower promises loc from to msg1 msg2 promises1)
(LOWER2: Memory.lower promises' loc from' to' msg1' msg2' promises1')
(CONCRETE: ∃ val released, msg1 = Message.concrete val released)
(INJ: inj loc to = Some to'):
promise_inj inj promises1 promises1'.
Proof.
inv P_INJ. des; subst.
econs; ii.
{
erewrite Memory.lower_o in H; eauto.
des_ifH H; eauto; ss; des; subst; ss.
{
inv H.
eapply Memory.lower_get0 in LOWER1; eauto; des.
inv MSG_LE.
exploit SOUND; eauto; ii; des.
rewrite INJ in H; inv H.
eapply Memory.lower_get0 in LOWER2; eauto; des.
rewrite GET1 in H0; inv H0.
inv MSG_LE. do 2 eexists. split; eauto.
}
{
eapply SOUND in H; eauto; des; subst.
eapply Memory.lower_get1 in LOWER2; eauto; des.
inv MSG_LE.
do 2 eexists.
split; eauto.
}
{
eapply SOUND in H; eauto. des; subst.
eapply Memory.lower_get1 in LOWER2; eauto; des.
inv MSG_LE.
do 2 eexists.
split; eauto.
}
}
{
erewrite Memory.lower_o in H; eauto.
des_ifH H; ss; des; subst; eauto.
{
inv H.
eapply Memory.lower_get0 in LOWER1; eauto; des. inv MSG_LE.
eapply Memory.lower_get0 in LOWER2; eauto; des. inv MSG_LE.
exploit SOUND; eauto. ii; des.
rewrite INJ in H; inv H.
rewrite GET1 in H0. inv H0.
do 2 eexists. split; eauto.
exploit SOUND; eauto. ii; des.
rewrite INJ in H; inv H.
rewrite GET1 in H0; inv H0.
}
{
eapply COMPLETE in H; eauto. des.
exploit Memory.lower_get1; [eapply LOWER1 | eauto..].
ii; des. inv MSG_LE.
do 2 eexists. split; eauto.
}
{
eapply COMPLETE in H; eauto. des.
exploit Memory.lower_get1; [eapply LOWER1 | eauto..].
ii; des. inv MSG_LE.
do 2 eexists. split; eauto.
}
}
{
erewrite Memory.lower_o in H; eauto.
des_ifH H; ss; des; subst; eauto.
{
inv H.
eapply Memory.lower_get0 in LOWER1; eauto; des.
inv MSG_LE.
}
{
eapply RSV_SOUND in H.
erewrite Memory.lower_o; eauto.
des_if; eauto; ss; des; subst; ss.
}
{
eapply RSV_SOUND in H.
erewrite Memory.lower_o; eauto.
des_if; eauto; ss; des; subst; ss.
eapply Memory.lower_get0 in LOWER1; eauto; des.
eapply Memory.lower_get0 in LOWER2; eauto; des.
eapply SOUND in GET; des; eauto.
rewrite INJ in GET; inv GET.
rewrite GET3 in GET1; inv GET1.
inv MSG_LE.
rewrite GET3 in H. inv H.
}
}
{
erewrite Memory.lower_o in H; eauto.
des_ifH H; eauto; ss; des; ss; subst.
{
inv H.
eapply Memory.lower_get0 in LOWER1; eauto; des.
inv MSG_LE.
eapply SOUND in GET; eauto; des.
rewrite INJ in GET; inv GET.
eapply Memory.lower_get0 in LOWER2; eauto; des.
rewrite GET1 in GET; inv GET.
inv MSG_LE.
}
{
eapply RSV_COMPLETE in H.
erewrite Memory.lower_o; eauto.
des_if; eauto; ss; subst; des; ss.
}
{
eapply RSV_COMPLETE in H.
erewrite Memory.lower_o; eauto.
des_if; eauto; ss; des; subst; ss.
eapply Memory.lower_get0 in LOWER1; eauto; des.
rewrite GET in H. inv H.
}
}
Qed.
Lemma mem_nonsynch_loc_msgInj
promises promises' mem mem' inj loc
(MEM_INJ: MsgInj inj mem mem')
(LE1: Memory.le promises mem)
(LE2: Memory.le promises' mem')
(PROM_INJ: promise_inj inj promises promises')
(NONSYNC_LOC: Memory.nonsynch_loc loc promises):
Memory.nonsynch_loc loc promises'.
Proof.
unfold Memory.nonsynch_loc in *; ii.
inv PROM_INJ.
destruct msg; ss.
dup GET.
exploit COMPLETE; eauto. ii; des.
exploit NONSYNC_LOC; eauto. ii; ss; subst.
inv MEM_INJ.
dup H0.
eapply LE1 in H1.
eapply SOUND0 in H1; eauto. des.
rewrite H in H1. inv H1.
unfold opt_ViewInj in H2. destruct R'; ss.
eapply LE2 in GET.
rewrite GET in H3. inv H3; eauto.
Qed.
Lemma mem_nonsynch_msgInj
promises promises' mem mem' inj
(MEM_INJ: MsgInj inj mem mem')
(LE1: Memory.le promises mem)
(LE2: Memory.le promises' mem')
(PROM_INJ: promise_inj inj promises promises')
(NONSYNC: Memory.nonsynch promises):
Memory.nonsynch promises'.
Proof.
unfold Memory.nonsynch in ×. intro loc.
specialize (NONSYNC loc).
eapply mem_nonsynch_loc_msgInj; eauto.
Qed.
Lemma promise_inj_bot
promises promises' inj
(PROM_INJ: promise_inj inj promises promises')
(BOT: promises = Memory.bot):
promises' = Memory.bot.
Proof.
subst.
inv PROM_INJ.
destruct (classic (∃ loc to from msg, Memory.get loc to promises' = Some (from, msg))).
{
des.
destruct msg.
eapply COMPLETE in H; eauto; des.
rewrite Memory.bot_get in H0; ss.
eapply RSV_COMPLETE in H; eauto; des.
rewrite Memory.bot_get in H; ss.
}
{
eapply Memory.ext; ii.
rewrite Memory.bot_get.
destruct (Memory.get loc ts promises') eqn:Heqe; eauto.
destruct p.
contradiction H; eauto.
}
Qed.
Lemma write_step_promise_inj_stable
lc1 sc1 mem1 loc from1 to1 val releasedr1 releasedw1 ord lc1' sc1' mem1' kind1 lo
lc2 sc2 mem2 from2 to2 releasedr2 releasedw2 lc2' sc2' mem2' kind2
inj inj'
(WRITE1: Local.write_step lc1 sc1 mem1 loc from1 to1 val releasedr1 releasedw1 ord lc1' sc1' mem1' kind1 lo)
(WRITE2: Local.write_step lc2 sc2 mem2 loc from2 to2 val releasedr2 releasedw2 ord lc2' sc2' mem2' kind2 lo)
(PROM_INJ: promise_inj inj (Local.promises lc1) (Local.promises lc2))
(INJ_INCR: incr_inj inj inj')
(INJ: inj' loc to1 = Some to2)
(MON: monotonic_inj inj')
(KIND_MATCH: kind_match kind1 kind2)
(SPLIT: ∀ t val R, kind1 = Memory.op_kind_split t (Message.concrete val R) →
∃ t' val' R', kind2 = Memory.op_kind_split t' (Message.concrete val' R') ∧
to1 = to2 ∧ inj loc t = Some t'):
promise_inj inj' (Local.promises lc1') (Local.promises lc2').
Proof.
inv WRITE1; ss. inv WRITE. inv PROMISE.
- destruct kind2; ss.
inv WRITE2; ss. inv WRITE. inv PROMISE.
assert(Local.promises lc1 = promises2).
{
eapply MemoryMerge.MemoryMerge.add_remove; eauto.
}
subst.
assert(Local.promises lc2 = promises1).
{
eapply MemoryMerge.MemoryMerge.add_remove; eauto.
}
subst.
eapply promise_inj_incr; eauto.
- des; subst. inv RESERVE.
destruct kind2; ss.
exploit SPLIT; eauto. ii; des; subst.
inv H. des; subst.
assert(promise_inj inj' (Local.promises lc1) (Local.promises lc2)).
{
eapply promise_inj_incr; eauto.
}
inv WRITE2; ss.
inv WRITE. inv PROMISE. des; ss.
inv RESERVE. inv RESERVEORIGINAL.
exploit promise_inj_split; eauto.
ii.
eapply promise_inj_remove_concrete; eauto.
- des; subst.
destruct kind2; ss.
inv WRITE2; ss. inv WRITE. inv PROMISE. des; subst.
subst.
assert(INJ'': inj loc to1 = Some to2).
{
clear - PROM_INJ INJ INJ_INCR PROMISES PROMISES0.
exploit Memory.lower_get0; [eapply PROMISES | eauto..]. ii; des.
inv PROM_INJ.
eapply SOUND in GET; eauto. des.
dup GET.
eapply INJ_INCR in GET. rewrite GET in INJ. inv INJ. eauto.
}
exploit promise_inj_lower; eauto. ii.
eapply promise_inj_incr in H; eauto.
eapply promise_inj_remove_concrete in H; eauto.
- ss.
Qed.