(* TODO those definitions are also in sync_preds_defs, see if we can include without changing the dep DAG too badly *)
(* The TT branch of the jam below might seem too weak, but we already keep enough control over joining with other rmaps that it should be enough *)
Definition LKspec_ext (R: pred rmap) lksize : spec :=
fun (sh: Share.t) (l: AV.address)  =>
allp (jam (adr_range_dec l lksize)
(fun l' => yesat (SomeP rmaps.Mpred (fun _ => R)) (LK lksize (snd l' - snd l)) sh l')
(fun _ => TT)).
Definition LK_at R lksize sh :=
LKspec_ext R lksize sh.

(* Specifications: *)
Lemma data_at_rmap_makelock CS sh b ofs R phi length :
0 < length ->
writable0_share sh ->
app_pred (@data_at_ CS sh (Tarray (Tpointer Tvoid noattr) length noattr) (Vptr b ofs)) phi ->
exists phi',
rmap_makelock phi phi' (b, Ptrofs.unsigned ofs) R (size_chunk Mptr * length) /\
LK_at R (size_chunk Mptr * length) sh (b, Ptrofs.unsigned ofs) phi'.
Lemma nat_of_Z_nonzero z n: n <> O -> nat_of_Z z = n -> z = Z.of_nat n.
Lemma lock_inv_rmap_freelock CS sh b ofs R phi m :
(align_chunk Mptr | Ptrofs.unsigned ofs) ->
Ptrofs.unsigned ofs + LKSIZE < Ptrofs.modulus ->
writable0_share sh ->
app_pred (@lock_inv sh (Vptr b ofs) R) phi ->
exists phi',
rmap_freelock phi phi' m (b, Ptrofs.unsigned ofs) R LKSIZE /\
app_pred (@data_at_ CS sh (Tarray (Tpointer Tvoid noattr) (LKSIZE/size_chunk Mptr) noattr) (Vptr b ofs)) phi'.
Lemma rmap_makelock_unique phi phi1 phi2 loc R len :
rmap_makelock phi phi1 loc R len ->
rmap_makelock phi phi2 loc R len ->
phi1 = phi2.
Lemma rmap_freelock_unique phi phi1 phi2 m loc R len :
rmap_freelock phi phi1 m loc R len ->
rmap_freelock phi phi2 m loc R len ->
phi1 = phi2.