(*+ "Clean" specifications not mentioning oracle *)
Definition clean_acquire_spec l : ext :=
mkext
(val * (M -> Prop))
(fun x Ω m =>
match x with
| (lx, Rx) =>
lx = l /\
islock l Rx m
end)
(fun x Ω m =>
match x with
| (lx, Rx) =>
islock lx Rx m
end).
Definition clean_release_spec l : ext :=
mkext
(val * (M -> Prop))
(fun x Ω m =>
match x with
| (lx, Rx) =>
lx = l /\
islock l Rx m
end)
(fun x Ω m =>
match x with
| (lock, Rx) =>
islock lock Rx m
end).
Definition clean_at_ext : C -> option ext :=
fun c =>
match c with
| acquire l _ => Some (clean_acquire_spec l)
| release l _ => Some (clean_release_spec l)
| _ => None
end.
(*+ Proof that clean safety => dirty safety *)
Open Scope list_scope.
(* no need for excluded middle thanks to the trick in the spec (ok <-> R mlock instead of doing the case analysis (e.g. ok = true <-> R mlock) *)

Theorem clean_safeN_implies_safeN_ n Ω c m :
safeN_ clean_at_ext  n Ω c m ->
safeN_ oracle_at_ext n Ω c m.