(*+ Composing safety of several threads *)
(** If each thread behaves well (assuming a good oracle) then running those threads in a concurrent machine is safe, too.  The proof builds a good oracle for each thread so that each thread follows the steps of the machine. *)
Definition functions_safe G F :=
forall f, match funspecs G f, F f with
| Some P, Some p =>
forall m oracle, P m -> safe step (G, oracle, m, p)
| None, None => True
| _, _ => False
end.
Ltac funspecs_inv :=
match goal with
| FF : functions_safe ?G ?F |- _ =>
match goal with
| FSf : funspecs G ?f = Some _ |- _ =>
let H := fresh "Hsafe" in
let p := fresh "p" in
let E := fresh "E" in
pose proof FF f as H;
destruct (F f) as [p|] eqn:E;
rewrite FSf in H; [|tauto]
| Ff : F ?f = Some _ |- _ =>
let H := fresh "Hsafe" in
let P := fresh "PRE" in
let E := fresh "E" in
pose proof FF f as H;
destruct (funspecs G f) as [P|] eqn:E;
rewrite Ff in H; [|tauto]
end
end.
(* Our invariant: - resource invariants are precise (no need for them to be positive) - all the functions are safe (given a precondition) - lock pool maps and threads maps are disjoint - lock pool maps match the resource invariants - all threads are safe for n steps *)
Definition P (x : config) :=
match x with (_, F, G, thd, pool) =>
(forall l, precise (resinvs G l)) /\
functions_safe G F /\
selfjoins (reindex thd pool) /\
lockpool_matches pool (resinvs G) /\
(forall i oracle m p,
nth thd i = Some (m, p) ->
safe step (G, oracle, m, p))
end.
(* Progress : the invariant implies we can take a machine step *)

Theorem progress x : P x -> exists y, x ===> y.
Tactic Notation "rewr" :=
match goal with
| H : ?f = _ |- context [?f] => rewrite H
| H : ?f _ = ?f _ |- _ => try (injection H; repeat intros ->)
end.