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 load_restrPermMap ge m (tp : jstate ge) Phi b ofs m_any
(compat : mem_compatible_with tp m Phi) :
lock_coherence (lset tp) Phi m_any ->
AMap.find (elt:=option rmap) (b, ofs) (lset tp) <> None ->
Mem.load
Mint32
(restrPermMap (mem_compatible_locks_ltwritable (mem_compatible_forget compat)))
b ofs =
Some (decode_val Mint32 (Mem.getN (size_chunk_nat Mint32) ofs (Mem.mem_contents m) !! b)).
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 access_at_fold m b ofs k :
(mem_access m) !! b ofs k = access_at m (b, ofs) k.
Lemma personal_mem_equiv_spec m m' phi pr pr' :
nextblock m = nextblock m' ->
(forall loc, max_access_at m loc = max_access_at m' loc) ->
(forall loc, isVAL (phi @ loc) -> contents_at m loc = contents_at m' loc) ->
mem_equiv
(m_dry (@personal_mem m phi pr))
(m_dry (@personal_mem m' phi pr')).
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.