Ltac jmstep_inv :=
  match goal with
  | H : JuicyMachine.start_thread _ _ _ _  |- _ => inversion H
  | H : JuicyMachine.resume_thread _ _ _   |- _ => inversion H
  | H : JuicyMachine.threadStep _ _ _ _ _           |- _ => inversion H
  | H : JuicyMachine.suspend_thread _ _ _ |- _ => inversion H
  | H : JuicyMachine.syncStep _ _ _ _ _ _           |- _ => inversion H
(*  | H : JuicyMachine.threadHalted _                   |- _ => inversion H*)
  | H : JuicyMachine.schedfail _         |- _ => inversion H
  end; try subst.Ltac getThread_inv :=
  match goal with
  | [ H : getThreadC ?i _ _ = _ ,
          H2 : getThreadC ?i _ _ = _ |- _ ] =>
    pose proof (getThreadC_fun _ _ _ _ _ _ _ H H2)
  | [ H : getThreadR ?i _ _ = _ ,
          H2 : getThreadR ?i _ _ = _ |- _ ] =>
    pose proof (getThreadR_fun _ _ _ _ _ _ _ H H2)
  end.Ltac substwith x y := assert (x = y) by apply proof_irr; subst x.

(* Specifications: *)
Lemma lock_coh_bound ge (tp : jstate ge) m Phi (compat : mem_compatible_with tp m Phi) (coh : lock_coherence' tp Phi m compat) : lockSet_block_bound (lset tp) (Mem.nextblock m).
Lemma resource_decay_join_identity b phi phi' e e' : resource_decay b phi phi' -> sepalg.joins phi e -> sepalg.joins phi' e' -> identity e -> identity e' -> e' = age_to (level phi') e.
Lemma mem_cohere'_store ge m (tp : jstate ge) m' b ofs j i Phi (cnti : containsThread tp i): forall (Hcmpt : mem_compatible tp m) (lock : lockRes tp (b, Ptrofs.intval ofs) <> None) (Hlt' : permMapLt (setPermBlock (Some Writable) b (Ptrofs.intval ofs) (juice2Perm_locks (getThreadR i tp cnti) m) LKSIZE_nat) (getMaxPerm m)) (Hstore : Mem.store Mint32 (restrPermMap Hlt') b (Ptrofs.intval ofs) (Vint j) = Some m'), mem_compatible_with tp m Phi (* redundant with Hcmpt, but easier *) -> (exists phi, join_sub phi Phi /\ exists sh R, LKspec LKSIZE sh R (b, Ptrofs.intval ofs) phi) -> mem_cohere' m' Phi.
Lemma juicyRestrict_age_to m phi n pr pr' : @juicyRestrict (@age_to n rmap ag_rmap phi) m (@acc_coh m (@age_to n rmap ag_rmap phi) pr) = @juicyRestrict phi m (@acc_coh m phi pr').
Lemma personal_mem_age_to m phi n pr pr' : @personal_mem m (age_to n phi) pr = age_to n (@personal_mem m phi pr').
Lemma jm_updThreadC ge i (tp : jstate ge) ctn c' m Phi cnti pr pr' : @jm_ _ (updThreadC i tp ctn c') m Phi i cnti pr = @jm_ _ tp m Phi i cnti pr'.
Lemma lockSet_Writable_updLockSet_updThread ge m m' i (tp : jstate ge) cnti b ofs ophi ophi' c' phi' z (Hcmpt : mem_compatible tp m) (His_unlocked : AMap.find (elt:=option rmap) (b, Ptrofs.intval ofs) (lset tp) = Some ophi) (Hlt' : permMapLt (setPermBlock (Some Writable) b (Ptrofs.intval ofs) (juice2Perm_locks (getThreadR i tp cnti) m) LKSIZE_nat) (getMaxPerm m)) (Hstore : Mem.store Mint32 (restrPermMap Hlt') b (Ptrofs.intval ofs) (Vint z) = Some m') : lockSet_Writable (lset (updLockSet (updThread i tp cnti c' phi') (b, Ptrofs.intval ofs) ophi')) m'.
Lemma lockSet_Writable_updThread_updLockSet ge m m' i (tp : jstate ge) b ofs ophi ophi' c' phi' z cnti (Hcmpt : mem_compatible tp m) (His_unlocked : AMap.find (elt:=option rmap) (b, Ptrofs.intval ofs) (lset tp) = Some ophi) (Hlt' : permMapLt (setPermBlock (Some Writable) b (Ptrofs.intval ofs) (juice2Perm_locks (getThreadR i tp cnti) m) LKSIZE_nat) (getMaxPerm m)) (Hstore : Mem.store Mint32 (restrPermMap Hlt') b (Ptrofs.intval ofs) (Vint z) = Some m') : lockSet_Writable (lset (updThread i (updLockSet tp (b, Ptrofs.intval ofs) ophi') cnti c' phi')) m'.
Lemma resource_decay_join_all' ge {tp : jstate ge} {m Phi} c' {phi' i} {cnti : containsThread tp i}: rmap_bound (Mem.nextblock m) Phi -> resource_decay (Mem.nextblock m) (getThreadR i tp cnti) phi' /\ level (getThreadR i tp cnti) = level phi' /\ ghost_of phi' = ghost_fmap (approx (level phi')) (approx (level phi')) (ghost_of (getThreadR i tp cnti)) -> join_all tp Phi -> exists Phi', join_all (updThread i (age_tp_to (level phi') tp) (cnt_age' cnti) c' phi') Phi' /\ resource_decay (Mem.nextblock m) Phi Phi' /\ ghost_of Phi' = own.ghost_approx Phi' (ghost_of Phi) /\ level Phi = level Phi'.
Lemma AMap_ext : forall {A} (m1 m2 : AMap.t A), AMap.this m1 = AMap.this m2 -> m1 = m2.
Lemma AMap_find_In : forall {A} m k (v : A), AMap.Raw.find k m = Some v -> In (k, v) m.
Lemma age_tp_to_eq: forall ge (k : nat) (tp : jstate ge) (phi : rmap), join_all tp phi -> k = level phi -> age_tp_to k tp = tp.