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.

(* Specifications: *)
Lemma no_Krun_unique_Krun tp sch : no_Krun tp -> unique_Krun tp sch.
Lemma containsThread_age_tp_to_eq (tp : jstate ge) n : containsThread (age_tp_to n tp) = containsThread tp.
Lemma no_Krun_age_tp_to n tp : no_Krun (age_tp_to n tp) = no_Krun tp.
Lemma unique_Krun_age_tp_to n tp sch : unique_Krun (age_tp_to n tp) sch <-> unique_Krun tp sch.
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').
Lemma no_Krun_stableR tp i cnti phi' : no_Krun tp -> no_Krun (@updThreadR _ _ _ i tp cnti phi').
Lemma no_Krun_unique_Krun_updThread tp i sch cnti q phi' : no_Krun tp -> unique_Krun (@updThread _ _ _ i tp cnti (Krun q) phi') (i :: sch).
Lemma no_Krun_updLockSet tp loc ophi : no_Krun tp -> no_Krun (updLockSet tp loc ophi).
Lemma no_Krun_remLockSet tp loc: no_Krun tp -> no_Krun (remLockSet tp loc).
Lemma ssr_leP_inv i n : is_true (ssrnat.leq i n) -> (i <= n)%nat.
Lemma different_threads_means_several_threads i j (tp : jstate ge) (cnti : containsThread tp i) (cntj : containsThread tp j) : i <> j -> (1 < pos.n (num_threads tp))%nat.
Lemma unique_Krun_no_Krun tp i sch cnti : unique_Krun tp (i :: sch) -> (forall q, @getThreadC _ _ _ i tp cnti <> Krun q) -> no_Krun tp.
Lemma unique_Krun_no_Krun_updThread tp i sch cnti c' phi' : (forall q, c' <> Krun q) -> unique_Krun tp (i :: sch) -> no_Krun (@updThread _ _ _ i tp cnti c' phi').
Lemma unique_Krun_neq i j tp sch (cnti : containsThread tp i) (cntj : containsThread tp j) : i <> j -> unique_Krun tp (i :: sch) -> forall q, @getThreadC _ _ _ j tp cntj <> Krun q.