Definition resource_decay (nextb: block) (phi1 phi2: rmap) :=
(level phi1 >= level phi2)%nat /\
forall l: address,
((fst l >= nextb)%positive -> phi1 @ l = NO Share.bot bot_unreadable) /\
(resource_fmap (approx (level phi2)) (approx (level phi2)) (phi1 @ l) = (phi2 @ l) \/
(exists sh, exists (wsh: writable0_share sh), exists v, exists v',
resource_fmap (approx (level phi2)) (approx (level phi2)) (phi1 @ l) =
YES sh (writable0_readable wsh) (VAL v) NoneP /\
phi2 @ l = YES sh (writable0_readable wsh) (VAL v') NoneP)
\/ ((fst l >= nextb)%positive /\ exists v, phi2 @ l = YES Share.top readable_share_top (VAL v) NoneP)
\/ (exists v, exists pp, phi1 @ l = YES Share.top readable_share_top (VAL v) pp
/\ phi2 @ l = NO Share.bot bot_unreadable)).
Definition resource_nodecay (nextb: block) (phi1 phi2: rmap) :=
(level phi1 >= level phi2)%nat /\
forall l: address,
((fst l >= nextb)%positive -> phi1 @ l = NO Share.bot bot_unreadable) /\
(resource_fmap (approx (level phi2)) (approx (level phi2)) (phi1 @ l) = (phi2 @ l) \/
(exists sh, exists (wsh: writable0_share sh), exists v, exists v',
resource_fmap (approx (level phi2)) (approx (level phi2)) (phi1 @ l) = YES sh (writable0_readable wsh) (VAL v) NoneP
/\ phi2 @ l = YES sh (writable0_readable wsh) (VAL v') NoneP)).

(* Specifications: *)
Lemma resource_nodecay_decay:
forall b phi1 phi2, resource_nodecay b phi1 phi2 -> resource_decay b phi1 phi2.
Lemma resource_decay_refl: forall b phi,
(forall l, (fst l >= b)%positive -> phi @ l = NO Share.bot bot_unreadable) ->
resource_decay b phi phi.
Lemma resource_decay_trans: forall b b' m1 m2 m3,
(b <= b')%positive ->
resource_decay b m1 m2 -> resource_decay b' m2 m3 -> resource_decay b m1 m3.
Lemma level_store_juicy_mem:
forall jm m ch b i v H, level (store_juicy_mem jm m ch b i v H) = level jm.
Lemma level_storebytes_juicy_mem:
forall jm m b i bytes H, level (storebytes_juicy_mem jm m b i bytes H) = level jm.
Lemma inflate_store_resource_nodecay:
forall (jm: juicy_mem) (m': mem)
(ch: memory_chunk) (b: block) (ofs: Z) (v: val)
(STORE: store ch (m_dry jm) b ofs v = Some m')
(PERM: forall z, ofs <= z < ofs + size_chunk ch ->
perm_order'' (perm_of_res (m_phi jm @ (b,z))) (Some Writable))
phi',
inflate_store m' (m_phi jm) = phi' -> resource_nodecay (nextblock (m_dry jm)) (m_phi jm) phi'.
Lemma inflate_free_resource_decay:
forall (jm :juicy_mem) (m': mem)
(b: block) (lo hi: Z)
(FREE: free (m_dry jm) b lo hi = Some m')
(PERM: forall ofs : Z,
lo <= ofs < hi -> perm_of_res (m_phi jm @ (b, ofs)) = Some Freeable),
resource_decay (nextblock (m_dry jm)) (m_phi jm) (inflate_free jm b lo hi).
Lemma juicy_store_nodecay:
forall jm m' ch b ofs v
(H: store ch (m_dry jm) b ofs v = Some m')
(PERM: forall z, ofs <= z < ofs + size_chunk ch ->
perm_order'' (perm_of_res (m_phi jm @ (b,z))) (Some Writable)),
resource_nodecay (nextblock (m_dry jm)) (m_phi jm) (m_phi (store_juicy_mem jm _ _ _ _ _ H)).
Lemma can_age1_juicy_mem: forall j r,
age (m_phi j) r -> exists j', age1 j = Some j'.
Lemma can_age_jm:
forall jm, age1 (m_phi jm) <> None -> exists jm', age jm jm'.
Lemma age_jm_dry: forall {jm jm'}, age jm jm' -> m_dry jm = m_dry jm'.
Lemma age_jm_phi: forall {jm jm'}, age jm jm' -> age (m_phi jm) (m_phi jm').
(** * Results about aging in juicy memory coherence properties *)
Lemma age1_YES'_1 {phi phi' l rsh sh k P} :
age1 phi = Some phi' ->
phi @ l = YES rsh sh k P ->
(exists P, phi' @ l = YES rsh sh k P).
Lemma age1_YES'_2 {phi phi' l rsh sh k P} :
age1 phi = Some phi' ->
phi' @ l = YES rsh sh k P ->
(exists P, phi @ l = YES rsh sh k P).
Lemma age1_PURE_2 {phi phi' l k P} :
age1 phi = Some phi' ->
phi' @ l = PURE k P ->
(exists P, phi @ l = PURE k P).
Lemma perm_of_res_age x y loc :
age x y -> perm_of_res (x @ loc) = perm_of_res (y @ loc).
Lemma contents_cohere_age m : hereditary age (contents_cohere m).
Lemma access_cohere_age m : hereditary age (access_cohere m).
Lemma max_access_cohere_age m : hereditary age (max_access_cohere m).
Lemma alloc_cohere_age m : hereditary age (alloc_cohere m).
Definition unage {A} {_:ageable A} x y := age y x.