(*+ CSL to progress and preservation *)
(* In this file, we use the same notion of thread safety as in the rest of VST, which is defined using specifications for external functions. In the rest of VST, we derive safety of the concurrent (juicy) machine from [progress] and [preservation] of an invariant.  We give a toy version of those definitions and proofs here, simplifying greatly problems related to step indexing, external calls and spawning. *)
(* standard files distributed with Coq *)
(* local file *)
Definition interp_lock := resourcemaps.interp_lock.
Definition islock (l : nat) (R : map -> Prop) (m : map) :=
exists lock, m l = Some (inr lock) /\ interp_lock lock = R.
intros v R1 R2 m [lock1 [E1 H1]] [lock2 [E2 H2]].
congruence.
Qed.
(*+ Core steps *)
Variable C' : Set.
Variable corestep : C' -> map -> C' -> map -> Prop.
Variable corestep_fun : forall c m c1 m1 c2 m2,
corestep c m c1 m1 ->
corestep c m c2 m2 ->
c1 = c2 /\ m1 = m2.
Variable corestep_sameperms : forall c m c' m', corestep c m c' m' -> sameperms m m'.
Variable corestep_samelocks : forall c m c' m' l lock,
corestep c m c' m' -> (m l = Some (inr lock) <-> m' l = Some (inr lock)).
Variable cancellative : forall m1 m1' m2 m3, join m1 m2 m3 -> join m1' m2 m3 -> m1 = m1'.
(** Concurrent instructions are built on top of those [C'] *)
Inductive C : Set :=
| acquire : nat -> C -> C
| release : nat -> C -> C
| normal : C' -> C.
(*+ Joinability hypotheses *)
(* Those lemmas can be proved if the support set of maps is finite. We omit those for conveninence, here. *)
Variable jointo : forall {A} (maps : A -> map) (m : map), Prop.
(*+ Definition of safety *)
(* We define safety based on specification of externals (acquire and release) *)
(* no need for an oracle, so it is unit *)
Definition Z := unit.
Record ext : Type := mkext {
ext_type : Type;
Pre : ext_type -> Z -> map -> Prop;
Post : ext_type -> Z -> map -> Prop
}.
Definition after_external : C -> option C :=
fun c =>
match c with
| acquire _ k => Some k
| release _ k => Some k
| _ => None
end.
(* [Hrel] is related to step indexing levels, and specify that the PURE of the maps coincide, which is always implied by joinability *)
Variable Hrel : nat -> map -> map -> Prop.
Inductive safeN_ (at_ext : C -> option ext) : nat -> Z -> C -> map -> Prop :=
safeN_0 : forall (z : Z) (c : C) (m : map), safeN_ at_ext 0 z c m
| safeN_step : forall (n : nat) (z : Z) (c c' : C') (m m' : map),
corestep c m c' m' ->
safeN_ at_ext n z (normal c') m' ->
safeN_ at_ext (S n) z (normal c) m
| safeN_external : forall (n : nat) (z : Z) (c : C) (m : map) (e : ext) (x : ext_type e),
at_ext c = Some e ->
Pre e x z m ->
(forall (m' : map) (z' : Z) (n' : nat),
n' <= n ->
Hrel n' m m' ->
Post e x z' m' ->
exists c' : C,
after_external c = Some c' /\
safeN_ at_ext n' z' c' m') ->
safeN_ at_ext (S n) z c m.

Lemma strong_nat_ind (P : nat -> Prop) (IH : forall n, (forall i, i < n -> P i) -> P n) n : P n.