(*Require Import VST.concurrency.cl_step_lemmas.*)
Set Bullet Behavior "Strict Subproofs".
(** Lemmas common to both parts of the progress/preservation simulation results *)
Definition pures_same phi1 phi2 := forall loc k pp, phi1 @ loc = PURE k pp <-> phi2 @ loc = PURE k pp.
Definition isVAL (r : resource) :=
match r with
| YES _ _ (VAL _) _ => Logic.True
| _ => False
end.
Definition thread_safety {Z} (Jspec : juicy_ext_spec Z) m ge (tp : jstate ge) PHI (mcompat : mem_compatible_with tp m PHI) n
i (cnti : containsThread tp i) := forall (ora : Z),
match getThreadC cnti with
| Krun c => semax.jsafeN Jspec ge n ora c (jm_ cnti mcompat)
| Kblocked c =>
(* The dry memory will change, so when we prove safety after an external we must only inspect the rmap m_phi part of the juicy memory.  This means more proof for each of the synchronisation primitives. *)
jsafe_phi Jspec ge n ora c (getThreadR cnti)
| Kresume c v =>
forall c',
(* [v] is not used here. The problem is probably coming from the definition of JuicyMachine.resume_thread'. *)
cl_after_external None c = Some c' ->
(* same quantification as in Kblocked *)
jsafe_phi_bupd Jspec ge n ora c' (getThreadR cnti)
| Kinit v1 v2 =>
val_inject (Mem.flat_inj (Mem.nextblock m)) v2 v2 /\
exists q_new,
cl_initial_core ge v1 (v2 :: nil) q_new /\
jsafe_phi Jspec ge n ora q_new (getThreadR cnti)
end.

Lemma state_inv_upd1 : forall {Z} (Jspec : juicy_ext_spec Z) Gamma (n : nat)
(m : mem) (ge : genv) (tr : event_trace) (sch : schedule) (tp : ThreadPool.t) (PHI : rmap)
(lev : level PHI = n)
(envcoh : env_coherence Jspec ge Gamma PHI)
(mwellformed: @mem_wellformed ge m)
(mcompat : mem_compatible_with tp m PHI)
(extcompat : joins (ghost_of PHI) (Some (ext_ref tt, NoneP) :: nil))
(lock_sparse : lock_sparsity (lset tp))
(lock_coh : lock_coherence' tp PHI m mcompat)
(safety : exists i (cnti : containsThread tp i), let phi := getThreadR cnti in
(exists k, getThreadC cnti = Krun k /\
forall c, join_sub (Some (ext_ref tt, NoneP) :: nil) c ->
joins (ghost_of phi) (ghost_fmap (approx (level phi)) (approx (level phi)) c) ->
exists b, joins b (ghost_fmap (approx (level phi)) (approx (level phi)) c) /\
exists phi' (Hr : resource_at phi' = resource_at phi), level phi' = level phi /\ ghost_of phi' = b /\
forall ora, jsafeN Jspec ge n ora k
(personal_mem (mem_cohere'_res _ _ _ (compatible_threadRes_cohere cnti (mem_compatible_forget mcompat)) Hr))) /\
forall j (cntj : containsThread tp j), j <> i -> thread_safety Jspec m ge tp PHI mcompat n j cntj)
(wellformed : threads_wellformed tp)
(uniqkrun :  unique_Krun tp sch),
state_bupd (state_invariant Jspec Gamma n) (m, (tr, sch, tp)).