(*Require Import VST.concurrency.cl_step_lemmas. Require Import VST.concurrency.resource_decay_lemmas. Require Import VST.concurrency.resource_decay_join.*)
Local Arguments getThreadR {_} {_} {_} _ _ _.
Local Arguments getThreadC {_} {_} {_} _ _ _.
Local Arguments personal_mem : clear implicits.
Local Arguments updThread {_} {_} {_} _ _ _ _ _.
Local Arguments updThreadR {_} {_} {_} _ _ _ _.
Local Arguments updThreadC {_} {_} {_} _ _ _ _.
Local Arguments juicyRestrict : clear implicits.
Set Bullet Behavior "Strict Subproofs".
Open Scope string_scope.
(* to make the proof faster, we avoid unfolding of those definitions *)
Definition Jspec'_juicy_mem_equiv_def CS ext_link :=
ext_spec_stable juicy_mem_equiv (JE_spec _ ( @OK_spec (Concurrent_Espec unit CS ext_link))).
Definition Jspec'_hered_def CS ext_link :=
ext_spec_stable age (JE_spec _ ( @OK_spec (Concurrent_Espec unit CS ext_link))).
Opaque containsThread.

(* Weaker statement than preservation for freelock, enough to prove safety *)
Lemma safety_induction_freelock ge Gamma n state
(CS : compspecs)
(ext_link : string -> ident)
(ext_link_inj : forall s1 s2, ext_link s1 = ext_link s2 -> s1 = s2)
(Jspec' := @OK_spec (Concurrent_Espec unit CS ext_link))
(Jspec'_juicy_mem_equiv : Jspec'_juicy_mem_equiv_def CS ext_link)
(Jspec'_hered : Jspec'_hered_def CS ext_link)
(personal_mem_equiv_spec :
forall (m m' : Mem.mem') (phi : rmap) (pr : mem_cohere' m phi) (pr' : mem_cohere' m' phi),
Mem.nextblock m = Mem.nextblock m' ->
(forall loc : address, max_access_at m loc = max_access_at m' loc) ->
(forall loc : AV.address, 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'))) :
blocked_at_external state FREE_LOCK ->
state_invariant Jspec' Gamma (S n) state ->
exists state',
state_step(ge := ge) state state' /\
(state_invariant Jspec' Gamma n state' \/
state_invariant Jspec' Gamma (S n) state').