Definition threads_safety m (tp : jstate ge) PHI (mcompat : mem_compatible_with tp m PHI) n :=
forall i (cnti : containsThread tp i) (ora : ZT),
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 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 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 ge n ora q_new (getThreadR cnti)
end.
Definition threads_wellformed (tp : jstate ge) :=
forall i (cnti : containsThread tp i),
match getThreadC cnti with
| Krun q => Logic.True
| Kblocked q => cl_at_external q <> None
| Kresume q v => cl_at_external q <> None /\ v = Vundef
| Kinit _ _ => Logic.True
end.
(* Havent' move this, but it's already defined in the concurrent_machien... * Probably in the wrong part... * SC: I had to change unique_Krun to include ~ Halted. Because halted * threads are still in Krun. (Although, ass you know right now there are no Hatled * threads...)  *)
Definition unique_Krun (tp : jstate ge) sch :=
(lt 1 tp.(num_threads).(pos.n) -> forall i cnti q,
@getThreadC _ _ _ i tp cnti = Krun q ->
exists sch', sch = i :: sch').
Definition no_Krun (tp : jstate ge) :=
forall i cnti q, @getThreadC _ _ _ i tp cnti <> Krun q.

Lemma no_Krun_stable tp i cnti c' phi' :
(forall q, c' <> Krun q) ->
no_Krun tp ->
no_Krun (@updThread _ _ _ i tp cnti c' phi').