(* We could also consider an alpha-renaming axiom, although this may be unnecessary. *)

(* Specifications: *)
(* exclusive *)
Lemma weak_exclusive_conflict : forall P,
predicates_hered.derives ((weak_exclusive_mpred P && emp) * P * P) FF.
Lemma exclusive_sepcon1 : forall (P Q : mpred) (HP : exclusive_mpred P), exclusive_mpred (P * Q).
Lemma exclusive_sepcon2 : forall (P Q : mpred) (HP : exclusive_mpred Q), exclusive_mpred (P * Q).
Lemma exclusive_andp1 : forall P Q (HP : exclusive_mpred P), exclusive_mpred (P && Q).
Lemma exclusive_andp2 : forall P Q (HQ : exclusive_mpred Q), exclusive_mpred (P && Q).
Lemma lock_inv_exclusive : forall v sh R, exclusive_mpred (lock_inv sh v R).
Lemma selflock_exclusive : forall R sh v, exclusive_mpred R -> exclusive_mpred (selflock R v sh).
Lemma exclusive_FF : exclusive_mpred FF.
Lemma derives_exclusive : forall P Q (Hderives : P |-- Q) (HQ : exclusive_mpred Q),
exclusive_mpred P.
Lemma mapsto_exclusive : forall (sh : Share.t) (t : type) (v : val),
sepalg.nonunit sh -> exclusive_mpred (EX v2 : _, mapsto sh t v v2).
Lemma field_at__exclusive : forall (cs : compspecs) (sh : Share.t) (t : type) (fld : list gfield) (p : val),
sepalg.nonidentity sh ->
0 < sizeof (nested_field_type t fld) -> exclusive_mpred (field_at_ sh t fld p).
Lemma ex_field_at_exclusive : forall (cs : compspecs) (sh : Share.t) (t : type) (fld : list gfield) (p : val),
sepalg.nonidentity sh ->
0 < sizeof (nested_field_type t fld) -> exclusive_mpred (EX v : _, field_at sh t fld v p).
Corollary field_at_exclusive : forall (cs : compspecs) (sh : Share.t) (t : type) (fld : list gfield) v (p : val),
sepalg.nonidentity sh -> 0 < sizeof (nested_field_type t fld) -> exclusive_mpred (field_at sh t fld v p).
Lemma ex_data_at_exclusive : forall (cs : compspecs) (sh : Share.t) (t : type) (p : val),
sepalg.nonidentity sh -> 0 < sizeof t -> exclusive_mpred (EX v : _, data_at sh t v p).
Corollary data_at_exclusive : forall (cs : compspecs) (sh : Share.t) (t : type) v (p : val),
sepalg.nonidentity sh -> 0 < sizeof t -> exclusive_mpred (data_at sh t v p).
Corollary data_at__exclusive : forall (cs : compspecs) (sh : Share.t) (t : type) (p : val),
sepalg.nonidentity sh -> 0 < sizeof t -> exclusive_mpred (data_at_ sh t p).
Lemma cond_var_exclusive : forall {cs} sh p, sepalg.nonidentity sh ->
exclusive_mpred (@cond_var cs sh p).
Lemma lock_inv_isptr : forall sh v R, lock_inv sh v R = !!isptr v && lock_inv sh v R.
Lemma cond_var_isptr : forall {cs} sh v, @cond_var cs sh v = !! isptr v && cond_var sh v.
Hint Resolve lock_inv_isptr cond_var_isptr : saturate_local.
Lemma cond_var_share_join : forall {cs} sh1 sh2 sh v (Hjoin : sepalg.join sh1 sh2 sh),
@cond_var cs sh1 v * cond_var sh2 v = cond_var sh v.
(* Sometimes, in order to prove precise, we actually need to know that the data is the same as well. *)
(* Do we still need this? Probably not. Lemma mapsto_inj : forall sh t v1 v2 p r1 r2 r (Hsh : readable_share sh) (Hp1 : predicates_hered.app_pred (mapsto sh t p v1) r1) (Hp2 : predicates_hered.app_pred (mapsto sh t p v2) r2) (Hr1 : sepalg.join_sub r1 r) (Hr2 : sepalg.join_sub r2 r) (Hdef1 : v1 <> Vundef) (Hdef2 : v2 <> Vundef), r1 = r2 /\ v1 = v2.  Lemma data_at_int_array_inj : forall {cs} sh z a1 a2 p r1 r2 r (Hsh : readable_share sh) (Hp1 : predicates_hered.app_pred (@data_at_rec cs sh (tarray tint z) a1 p) r1) (Hp2 : predicates_hered.app_pred (@data_at_rec cs sh (tarray tint z) a2 p) r2) (Hr1 : sepalg.join_sub r1 r) (Hr2 : sepalg.join_sub r2 r) (Hdef1 : Forall (fun v => v <> Vundef) a1) (Hdef2 : Forall (fun v => v <> Vundef) a2) (Hlen1 : Zlength a1 = z) (Hlen2 : Zlength a2 = z), r1 = r2 /\ a1 = a2.  Lemma data_at_ptr_array_inj : forall {cs} sh t z a1 a2 p r1 r2 r (Hsh : readable_share sh) (Hp1 : predicates_hered.app_pred (@data_at_rec cs sh (tarray (tptr t) z) a1 p) r1) (Hp2 : predicates_hered.app_pred (@data_at_rec cs sh (tarray (tptr t) z) a2 p) r2) (Hr1 : sepalg.join_sub r1 r) (Hr2 : sepalg.join_sub r2 r) (Hdef1 : Forall (fun v => v <> Vundef) a1) (Hdef2 : Forall (fun v => v <> Vundef) a2) (Hlen1 : Zlength a1 = z) (Hlen2 : Zlength a2 = z), r1 = r2 /\ a1 = a2.  Hint Resolve lock_inv_exclusive selflock_exclusive cond_var_exclusive data_at_exclusive data_at__exclusive field_at_exclusive field_at__exclusive selflock_rec.  Lemma eq_dec_refl : forall {A B} {A_eq : EqDec A} (a : A) (b c : B), (if eq_dec a a then b else c) = b.  (* shares *)
Lemma LKspec_readable lock_size :
0 < lock_size ->
forall R sh p, predicates_hered.derives (res_predicates.LKspec lock_size R sh p)
(!!(readable_share sh)).
Lemma lock_inv_share_join : forall sh1 sh2 sh v R (Hsh1 : readable_share sh1) (Hsh2 : readable_share sh2)
(Hjoin : sepalg.join sh1 sh2 sh),
lock_inv sh1 v R * lock_inv sh2 v R = lock_inv sh v R.
Lemma comp_join_top : forall sh, sepalg.join sh (Share.comp sh) Tsh.
Lemma unreadable_bot : ~readable_share Share.bot.
Hint Resolve unreadable_bot.