Library tutorial.container.ContainerType
Compcert types and semantics
CertiKOS layer library
This file contains the definitions of the abstract data for the container
layers as well as some auxiliary lemmas. A container is an object that tracks
a process' resource usage. In CertiKOS a pool of containers is maintained,
one per process. Initially, only the root process' container is initialized,
but new ones can be created using the split primitive. This example is a
slightly simplified from the CertiKOS version, but follows it very closely.
The fields and their meanings are:
Open Scope Z_scope.
Some constants used throughout.
Definition NUM_ID : Z := 1024.
Fact NUM_ID_range : 0 < 20 × NUM_ID ≤ Int.max_unsigned.
Proof. cbn; omega. Qed.
Definition MAX_CHILDREN : Z := 8.
Fact MAX_CHILDREN_range : 0 < MAX_CHILDREN ≤ Int.max_unsigned.
Proof. cbv. intuition. Qed.
Definition PAGE_SIZE : Z := 4096.
Fact PAGE_SIZE_range : 0 < PAGE_SIZE ≤ Int.max_unsigned.
Proof. cbv. intuition. Qed.
Definition VM_USERLO : Z := 1073741824.
Fact NUM_ID_range : 0 < 20 × NUM_ID ≤ Int.max_unsigned.
Proof. cbn; omega. Qed.
Definition MAX_CHILDREN : Z := 8.
Fact MAX_CHILDREN_range : 0 < MAX_CHILDREN ≤ Int.max_unsigned.
Proof. cbv. intuition. Qed.
Definition PAGE_SIZE : Z := 4096.
Fact PAGE_SIZE_range : 0 < PAGE_SIZE ≤ Int.max_unsigned.
Proof. cbv. intuition. Qed.
Definition VM_USERLO : Z := 1073741824.
0x40000000
0xF0000000
Fact VM_USERLO_range : 0 ≤ VM_USERLO < VM_USERHI.
Proof. cbv. intuition. Qed.
Fact VM_USERHI_range : VM_USERLO < VM_USERHI ≤ Int.max_unsigned.
Proof. cbv. intuition. Qed.
Definition ROOT_QUOTA : Z := 720896.
Fact ROOT_QUOTA_range : 0 ≤ ROOT_QUOTA ≤ Int.max_unsigned.
Proof. cbv. intuition. Qed.
Fact ROOT_QUOTA_eq : ROOT_QUOTA = (VM_USERHI - VM_USERLO) / PAGE_SIZE.
Proof. reflexivity. Qed.
Proof. cbv. intuition. Qed.
Fact VM_USERHI_range : VM_USERLO < VM_USERHI ≤ Int.max_unsigned.
Proof. cbv. intuition. Qed.
Definition ROOT_QUOTA : Z := 720896.
Fact ROOT_QUOTA_range : 0 ≤ ROOT_QUOTA ≤ Int.max_unsigned.
Proof. cbv. intuition. Qed.
Fact ROOT_QUOTA_eq : ROOT_QUOTA = (VM_USERHI - VM_USERLO) / PAGE_SIZE.
Proof. reflexivity. Qed.
We make these quantities opaque, because their actual values don't matter
so long as the facts we proved about their ranges hold.
Global Opaque NUM_ID.
Global Opaque MAX_CHILDREN.
Global Opaque PAGE_SIZE.
Global Opaque VM_USERLO.
Global Opaque VM_USERHI.
Global Opaque ROOT_QUOTA.
Global Opaque MAX_CHILDREN.
Global Opaque PAGE_SIZE.
Global Opaque VM_USERLO.
Global Opaque VM_USERHI.
Global Opaque ROOT_QUOTA.
The abstract data is almost just a Coq version of the C struct, but
instead of storing just the number of children, we store a list containing
their process ids. This is purely logical; only the length of the list is
actually represented in the implementation.
Record container_abs : Type := mkContainer {
cquota: Z;
cusage: Z;
cparent: Z;
cchildren: list Z;
cused: bool
}.
Definition container_pool := ZMap.t container_abs.
Definition container_unused := mkContainer 0 0 0 nil false.
Definition container_pool_init :=
ZMap.set 0 (mkContainer ROOT_QUOTA 0 0 nil true) (ZMap.init container_unused).
Record container_data : Type := {
init_flag: bool;
cpool: container_pool
}.
Definition container_data_init : container_data :=
{|
init_flag := false;
cpool := ZMap.init container_unused
|}.
cquota: Z;
cusage: Z;
cparent: Z;
cchildren: list Z;
cused: bool
}.
Definition container_pool := ZMap.t container_abs.
Definition container_unused := mkContainer 0 0 0 nil false.
Definition container_pool_init :=
ZMap.set 0 (mkContainer ROOT_QUOTA 0 0 nil true) (ZMap.init container_unused).
Record container_data : Type := {
init_flag: bool;
cpool: container_pool
}.
Definition container_data_init : container_data :=
{|
init_flag := false;
cpool := ZMap.init container_unused
|}.
The offsets of the fields in the struct.
Definition quo_off := 0.
Definition usg_off := 4.
Definition par_off := 8.
Definition nch_off := 12.
Definition use_off := 16.
Definition con_sz := 20.
End CONTAINER_DATA.
Ltac unfold_fields :=
unfold con_sz, quo_off, usg_off, par_off, nch_off, use_off in ×.
Definition usg_off := 4.
Definition par_off := 8.
Definition nch_off := 12.
Definition use_off := 16.
Definition con_sz := 20.
End CONTAINER_DATA.
Ltac unfold_fields :=
unfold con_sz, quo_off, usg_off, par_off, nch_off, use_off in ×.
A 'valid' container must satisfy several properties:
- Only containers for a valid process id can be initialized
- Only the root process has itself as its parent
- The quota must be bounded by the maximum unsigned integer
- The usage must be bounded by the quota
- A process' parent container must also be initialized
- All of a process' children's containers must be intialized
- A process must be in its parent's children (unless it is root)
- A process must be the parent of all of its children
- The sum of a process' children's quotas must be bounded by its usage
- The list of children must not contain duplicates
Inductive child_quotas_bounded : container_pool → list Z → Z → Prop :=
| cqb_nil: ∀ cp n,
0 ≤ n → child_quotas_bounded cp nil n
| cqb_cons: ∀ cp c cs n m,
0 ≤ cquota (ZMap.get c cp) ≤ m →
child_quotas_bounded cp cs n →
child_quotas_bounded cp (c :: cs) (n + m).
Record container_valid (cp: container_pool) : Prop := mkContainerValid {
cvalid_id: ∀ i,
cused (ZMap.get i cp) = true →
0 ≤ i < NUM_ID;
cvalid_root: ∀ i,
cused (ZMap.get i cp) = true →
(i = cparent (ZMap.get i cp) ↔ (i = 0));
cvalid_quota: ∀ i,
cused (ZMap.get i cp) = true →
cquota (ZMap.get i cp) ≤ Int.max_unsigned;
cvalid_usage: ∀ i,
cused (ZMap.get i cp) = true →
0 ≤ cusage (ZMap.get i cp) ≤ cquota (ZMap.get i cp);
cvalid_parent_used: ∀ i,
cused (ZMap.get i cp) = true →
cused (ZMap.get (cparent (ZMap.get i cp)) cp) = true;
cvalid_children_used: ∀ i,
cused (ZMap.get i cp) = true →
Forall (fun j ⇒ cused (ZMap.get j cp) = true) (cchildren (ZMap.get i cp));
cvalid_parents_child: ∀ i,
cused (ZMap.get i cp) = true →
i ≠ 0 →
In i (cchildren (ZMap.get (cparent (ZMap.get i cp)) cp));
cvalid_childrens_parent: ∀ i,
cused (ZMap.get i cp) = true →
Forall (fun j ⇒ cparent (ZMap.get j cp) = i) (cchildren (ZMap.get i cp));
cvalid_cqb: ∀ i,
cused (ZMap.get i cp) = true →
child_quotas_bounded cp (cchildren (ZMap.get i cp)) (cusage (ZMap.get i cp));
cvalid_nodup: ∀ i,
cused (ZMap.get i cp) = true →
NoDup (cchildren (ZMap.get i cp))
}.
End CONTAINER_VALID.
| cqb_nil: ∀ cp n,
0 ≤ n → child_quotas_bounded cp nil n
| cqb_cons: ∀ cp c cs n m,
0 ≤ cquota (ZMap.get c cp) ≤ m →
child_quotas_bounded cp cs n →
child_quotas_bounded cp (c :: cs) (n + m).
Record container_valid (cp: container_pool) : Prop := mkContainerValid {
cvalid_id: ∀ i,
cused (ZMap.get i cp) = true →
0 ≤ i < NUM_ID;
cvalid_root: ∀ i,
cused (ZMap.get i cp) = true →
(i = cparent (ZMap.get i cp) ↔ (i = 0));
cvalid_quota: ∀ i,
cused (ZMap.get i cp) = true →
cquota (ZMap.get i cp) ≤ Int.max_unsigned;
cvalid_usage: ∀ i,
cused (ZMap.get i cp) = true →
0 ≤ cusage (ZMap.get i cp) ≤ cquota (ZMap.get i cp);
cvalid_parent_used: ∀ i,
cused (ZMap.get i cp) = true →
cused (ZMap.get (cparent (ZMap.get i cp)) cp) = true;
cvalid_children_used: ∀ i,
cused (ZMap.get i cp) = true →
Forall (fun j ⇒ cused (ZMap.get j cp) = true) (cchildren (ZMap.get i cp));
cvalid_parents_child: ∀ i,
cused (ZMap.get i cp) = true →
i ≠ 0 →
In i (cchildren (ZMap.get (cparent (ZMap.get i cp)) cp));
cvalid_childrens_parent: ∀ i,
cused (ZMap.get i cp) = true →
Forall (fun j ⇒ cparent (ZMap.get j cp) = i) (cchildren (ZMap.get i cp));
cvalid_cqb: ∀ i,
cused (ZMap.get i cp) = true →
child_quotas_bounded cp (cchildren (ZMap.get i cp)) (cusage (ZMap.get i cp));
cvalid_nodup: ∀ i,
cused (ZMap.get i cp) = true →
NoDup (cchildren (ZMap.get i cp))
}.
End CONTAINER_VALID.
Section CONTAINER_PROP.
Context `{Hmem: BaseMemoryModel}.
Local Ltac zmap_simpl := ((try subst; rewrite ZMap.gss) ||
(rewrite ZMap.gso; [| congruence]) ||
(try subst; rewrite ZMap.set2) ||
(rewrite ZMap.gi)).
Local Ltac zmap_simpl_in H :=
((try subst; rewrite ZMap.gss in H) ||
(rewrite ZMap.gso in H; [| congruence]) ||
(try subst; rewrite ZMap.set2) ||
(rewrite ZMap.gi)).
Context `{Hmem: BaseMemoryModel}.
Local Ltac zmap_simpl := ((try subst; rewrite ZMap.gss) ||
(rewrite ZMap.gso; [| congruence]) ||
(try subst; rewrite ZMap.set2) ||
(rewrite ZMap.gi)).
Local Ltac zmap_simpl_in H :=
((try subst; rewrite ZMap.gss in H) ||
(rewrite ZMap.gso in H; [| congruence]) ||
(try subst; rewrite ZMap.set2) ||
(rewrite ZMap.gi)).
Child Quotas Bounded
Lemma cqb_weaken : ∀ cs cp c n con,
0 ≤ cquota con ≤ cquota (ZMap.get c cp) →
child_quotas_bounded cp cs n →
child_quotas_bounded (ZMap.set c con cp) cs n.
Proof.
induction cs; cbn; intros ? ? ? ? Hquo Hbound; inv Hbound.
- constructor; assumption.
- constructor; auto.
destr_eq a c; zmap_simpl; [omega | auto].
Qed.
Lemma cqb_bound : ∀ cs cp n m,
n ≤ m →
child_quotas_bounded cp cs n →
child_quotas_bounded cp cs m.
Proof.
induction cs; cbn; intros ? ? ? Hnm Hbound; inv Hbound.
- constructor; omega.
- eapply (IHcs _ _ (m - m0)) in H4; try omega.
replace m with (m - m0 + m0) by omega.
constructor; auto.
Qed.
Lemma cqb_notin : ∀ cs cp c n con,
~(In c cs) →
child_quotas_bounded cp cs n →
child_quotas_bounded (ZMap.set c con cp) cs n.
Proof.
induction cs; cbn; intros ? ? ? ? Hnin Hbound; inv Hbound.
- constructor; assumption.
- constructor; auto.
destr_eq a c; zmap_simpl; [tauto | auto].
Qed.
Lemma cqb_reorder : ∀ cs cp c1 c2 con1 con2 n,
c1 ≠ c2 →
child_quotas_bounded (ZMap.set c1 con1 (ZMap.set c2 con2 cp)) cs n →
child_quotas_bounded (ZMap.set c2 con2 (ZMap.set c1 con1 cp)) cs n.
Proof.
induction cs; cbn; intros ? ? ? ? ? ? Hneq Hbound; inv Hbound.
- constructor; assumption.
- constructor; auto.
repeat rewrite ZMap.gsspec; repeat rewrite ZMap.gsspec in H2.
destruct (ZIndexed.eq a c2); destruct (ZIndexed.eq a c1); (auto || congruence).
Qed.
0 ≤ cquota con ≤ cquota (ZMap.get c cp) →
child_quotas_bounded cp cs n →
child_quotas_bounded (ZMap.set c con cp) cs n.
Proof.
induction cs; cbn; intros ? ? ? ? Hquo Hbound; inv Hbound.
- constructor; assumption.
- constructor; auto.
destr_eq a c; zmap_simpl; [omega | auto].
Qed.
Lemma cqb_bound : ∀ cs cp n m,
n ≤ m →
child_quotas_bounded cp cs n →
child_quotas_bounded cp cs m.
Proof.
induction cs; cbn; intros ? ? ? Hnm Hbound; inv Hbound.
- constructor; omega.
- eapply (IHcs _ _ (m - m0)) in H4; try omega.
replace m with (m - m0 + m0) by omega.
constructor; auto.
Qed.
Lemma cqb_notin : ∀ cs cp c n con,
~(In c cs) →
child_quotas_bounded cp cs n →
child_quotas_bounded (ZMap.set c con cp) cs n.
Proof.
induction cs; cbn; intros ? ? ? ? Hnin Hbound; inv Hbound.
- constructor; assumption.
- constructor; auto.
destr_eq a c; zmap_simpl; [tauto | auto].
Qed.
Lemma cqb_reorder : ∀ cs cp c1 c2 con1 con2 n,
c1 ≠ c2 →
child_quotas_bounded (ZMap.set c1 con1 (ZMap.set c2 con2 cp)) cs n →
child_quotas_bounded (ZMap.set c2 con2 (ZMap.set c1 con1 cp)) cs n.
Proof.
induction cs; cbn; intros ? ? ? ? ? ? Hneq Hbound; inv Hbound.
- constructor; assumption.
- constructor; auto.
repeat rewrite ZMap.gsspec; repeat rewrite ZMap.gsspec in H2.
destruct (ZIndexed.eq a c2); destruct (ZIndexed.eq a c1); (auto || congruence).
Qed.
Lemma container_unused_valid : container_valid (ZMap.init container_unused).
Proof.
constructor; intros; rewrite ZMap.gi in *; discriminate.
Qed.
Lemma container_init_valid : container_valid container_pool_init.
Proof.
unfold container_pool_init.
pose proof NUM_ID_range as Hnid_range.
constructor; intros i; destr_eq i 0; repeat zmap_simpl;
(easy || auto || discriminate || omega || now constructor || idtac).
Qed.
Lemma container_alloc_valid : ∀ cp i,
let c := ZMap.get i cp in
container_valid cp →
cused c = true →
cusage c < cquota c →
container_valid (ZMap.set i {| cquota := cquota c;
cusage := cusage c + 1;
cparent := cparent c;
cchildren := cchildren c;
cused := cused c |} cp).
Proof.
intros ? ? ? Hvalid Hused Husg. destruct Hvalid.
constructor; cbn; intro i'.
-
cvalid_id
destr_eq i i'; zmap_simpl; eauto.
-
-
cvalid_root
destr_eq i i'; zmap_simpl; eauto.
-
-
cvalid_quota
destr_eq i i'; zmap_simpl; eauto.
-
-
cvalid_usage
destr_eq i i'; zmap_simpl; eauto.
cbn; intros _. specialize (cvalid_usage0 _ Hused). subst c; omega.
-
cbn; intros _. specialize (cvalid_usage0 _ Hused). subst c; omega.
-
cvalid_parent_used
destr_eq i i'; zmap_simpl; cbn; intros.
+ destr_eq (cparent c) i'; [rewrite Heq |]; zmap_simpl; eauto.
+ destr_eq (cparent (ZMap.get i' cp)) i; zmap_simpl; eauto.
-
+ destr_eq (cparent c) i'; [rewrite Heq |]; zmap_simpl; eauto.
+ destr_eq (cparent (ZMap.get i' cp)) i; zmap_simpl; eauto.
-
cvalid_children_used
rewrite Forall_forall. intros Hused' i'' Hin.
destr_eq i i''; zmap_simpl; auto.
destr_eq i i';
zmap_simpl_in Hin; zmap_simpl_in Hused';
specialize (cvalid_children_used0 _ Hused');
rewrite Forall_forall in cvalid_children_used0; auto.
-
destr_eq i i''; zmap_simpl; auto.
destr_eq i i';
zmap_simpl_in Hin; zmap_simpl_in Hused';
specialize (cvalid_children_used0 _ Hused');
rewrite Forall_forall in cvalid_children_used0; auto.
-
cvalid_parents_child
destr_eq i i'; zmap_simpl; cbn; intros Hused' Hneq0.
+ destr_eq (cparent c) i'; [rewrite Heq |]; zmap_simpl; eauto.
specialize (cvalid_parents_child0 _ Hused Hneq0); subst c.
rewrite Heq in cvalid_parents_child0; auto.
+ destr_eq (cparent (ZMap.get i' cp)) i; zmap_simpl; eauto.
-
+ destr_eq (cparent c) i'; [rewrite Heq |]; zmap_simpl; eauto.
specialize (cvalid_parents_child0 _ Hused Hneq0); subst c.
rewrite Heq in cvalid_parents_child0; auto.
+ destr_eq (cparent (ZMap.get i' cp)) i; zmap_simpl; eauto.
-
cvalid_childrens_parent
rewrite Forall_forall. intros Hused' i'' Hin.
destr_eq i i''; zmap_simpl.
+ destr_eq i' i''; cbn;
zmap_simpl_in Hin; zmap_simpl_in Hused';
specialize (cvalid_childrens_parent0 _ Hused');
rewrite Forall_forall in cvalid_childrens_parent0; subst c; auto.
+ destr_eq i i'; cbn;
zmap_simpl_in Hin; zmap_simpl_in Hused';
specialize (cvalid_childrens_parent0 _ Hused');
rewrite Forall_forall in cvalid_childrens_parent0; subst c; auto.
-
destr_eq i i''; zmap_simpl.
+ destr_eq i' i''; cbn;
zmap_simpl_in Hin; zmap_simpl_in Hused';
specialize (cvalid_childrens_parent0 _ Hused');
rewrite Forall_forall in cvalid_childrens_parent0; subst c; auto.
+ destr_eq i i'; cbn;
zmap_simpl_in Hin; zmap_simpl_in Hused';
specialize (cvalid_childrens_parent0 _ Hused');
rewrite Forall_forall in cvalid_childrens_parent0; subst c; auto.
-
cvalid_cqb
intros Hused'. apply cqb_weaken.
+ specialize (cvalid_usage0 _ Hused); subst c; cbn; omega.
+ destr_eq i i'; zmap_simpl; cbn; [| zmap_simpl_in Hused']; auto.
apply cqb_bound with (n := cusage c); try omega.
subst c; auto.
-
+ specialize (cvalid_usage0 _ Hused); subst c; cbn; omega.
+ destr_eq i i'; zmap_simpl; cbn; [| zmap_simpl_in Hused']; auto.
apply cqb_bound with (n := cusage c); try omega.
subst c; auto.
-
cvalid_nodup
destr_eq i i'; zmap_simpl; auto.
cbn; subst c; auto.
Qed.
Lemma container_split_valid : ∀ cp id q,
let c := ZMap.get id cp in
let chid := id × MAX_CHILDREN + 1 + Z.of_nat (length (cchildren c)) in
let child := {| cquota := q;
cusage := 0;
cparent := id;
cchildren := nil;
cused := true |} in
let c' := {| cquota := cquota c;
cusage := cusage c + q;
cparent := cparent c;
cchildren := chid :: cchildren c;
cused := cused c |} in
0 < chid < NUM_ID →
cused (ZMap.get chid cp) = false →
cused c = true →
0 ≤ q ≤ (cquota c - cusage c) →
container_valid cp →
container_valid (ZMap.set id c' (ZMap.set chid child cp)).
Proof.
intros ? ? ? ? ? ? ? Hchid Hchused Hused Hq Hvalid.
pose proof Hvalid as Hvalid'; destruct Hvalid'.
assert (Hquo: cquota (ZMap.get id cp) ≤ Int.max_unsigned) by auto.
assert (Husg: 0 ≤ cusage (ZMap.get id cp)) by (apply cvalid_usage0; auto).
constructor; cbn; intros id'.
-
cbn; subst c; auto.
Qed.
Lemma container_split_valid : ∀ cp id q,
let c := ZMap.get id cp in
let chid := id × MAX_CHILDREN + 1 + Z.of_nat (length (cchildren c)) in
let child := {| cquota := q;
cusage := 0;
cparent := id;
cchildren := nil;
cused := true |} in
let c' := {| cquota := cquota c;
cusage := cusage c + q;
cparent := cparent c;
cchildren := chid :: cchildren c;
cused := cused c |} in
0 < chid < NUM_ID →
cused (ZMap.get chid cp) = false →
cused c = true →
0 ≤ q ≤ (cquota c - cusage c) →
container_valid cp →
container_valid (ZMap.set id c' (ZMap.set chid child cp)).
Proof.
intros ? ? ? ? ? ? ? Hchid Hchused Hused Hq Hvalid.
pose proof Hvalid as Hvalid'; destruct Hvalid'.
assert (Hquo: cquota (ZMap.get id cp) ≤ Int.max_unsigned) by auto.
assert (Husg: 0 ≤ cusage (ZMap.get id cp)) by (apply cvalid_usage0; auto).
constructor; cbn; intros id'.
-
cvalid_id
destr_eq id id'; zmap_simpl; auto.
destr_eq chid id'; zmap_simpl; (auto || omega).
-
destr_eq chid id'; zmap_simpl; (auto || omega).
-
cvalid_root
subst c; destr_eq chid id'; repeat zmap_simpl; cbn.
+ intros Hused'; split; intros Heq.
× rewrite <- Heq in Hused. rewrite Hused in Hchused; discriminate.
× rewrite Heq in Hchid. omega.
+ destr_eq id id'; repeat zmap_simpl; intros Hused'; subst c'; eauto.
-
+ intros Hused'; split; intros Heq.
× rewrite <- Heq in Hused. rewrite Hused in Hchused; discriminate.
× rewrite Heq in Hchid. omega.
+ destr_eq id id'; repeat zmap_simpl; intros Hused'; subst c'; eauto.
-
cvalid_quota
destr_eq id id'; zmap_simpl; cbn; auto.
destr_eq chid id'; zmap_simpl; cbn; auto.
intros _. cbn in Hquo; subst c; omega.
-
destr_eq chid id'; zmap_simpl; cbn; auto.
intros _. cbn in Hquo; subst c; omega.
-
cvalid_usage
destr_eq id id'; zmap_simpl; cbn.
+ intros Hused'. subst c; omega.
+ destr_eq chid id'; zmap_simpl; cbn; (auto || omega).
-
+ intros Hused'. subst c; omega.
+ destr_eq chid id'; zmap_simpl; cbn; (auto || omega).
-
cvalid_parent_used
destr_eq id id'; zmap_simpl; cbn.
+ destr_eq id' (cparent (ZMap.get id' cp)); [rewrite Heq | subst c];
repeat zmap_simpl; auto.
intros Hused'.
destr_eq chid (cparent (ZMap.get id' cp)); [rewrite Heq |]; zmap_simpl; auto.
+ destr_eq id' chid; repeat zmap_simpl; auto.
destr_eq id (cparent (ZMap.get id' cp)); repeat zmap_simpl; auto.
destr_eq chid (cparent (ZMap.get id' cp)); [rewrite Heq |];
repeat zmap_simpl; auto.
-
+ destr_eq id' (cparent (ZMap.get id' cp)); [rewrite Heq | subst c];
repeat zmap_simpl; auto.
intros Hused'.
destr_eq chid (cparent (ZMap.get id' cp)); [rewrite Heq |]; zmap_simpl; auto.
+ destr_eq id' chid; repeat zmap_simpl; auto.
destr_eq id (cparent (ZMap.get id' cp)); repeat zmap_simpl; auto.
destr_eq chid (cparent (ZMap.get id' cp)); [rewrite Heq |];
repeat zmap_simpl; auto.
-
cvalid_children_used
rewrite Forall_forall. intros Hused' id'' Hin.
destr_eq id id''; zmap_simpl; auto.
destr_eq chid id''; zmap_simpl; auto.
destr_eq id id'; zmap_simpl_in Hin; zmap_simpl_in Hused'.
+ specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
apply cvalid_children_used0.
inv Hin; [contradiction | auto].
+ destr_eq chid id'; zmap_simpl_in Hin; repeat zmap_simpl_in Hused'.
× contradiction.
× specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0; auto.
-
destr_eq id id''; zmap_simpl; auto.
destr_eq chid id''; zmap_simpl; auto.
destr_eq id id'; zmap_simpl_in Hin; zmap_simpl_in Hused'.
+ specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
apply cvalid_children_used0.
inv Hin; [contradiction | auto].
+ destr_eq chid id'; zmap_simpl_in Hin; repeat zmap_simpl_in Hused'.
× contradiction.
× specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0; auto.
-
cvalid_parents_child
destr_eq id id'; zmap_simpl.
+ intros Hused' Hid'.
destr_eq id' (cparent c'); [rewrite Heq |]; zmap_simpl.
× subst c c'; right; cbn; cbn in Heq.
rewrite <- Heq.
replace (ZMap.get id' cp) with
(ZMap.get (cparent (ZMap.get id' cp)) cp) by congruence.
apply cvalid_parents_child0; auto.
× destr_eq chid (cparent c'); [rewrite Heq |]; zmap_simpl; cbn; eauto.
subst c; cbn in Heq. rewrite Heq in Hchused.
apply cvalid_parent_used0 in Hused'. congruence.
+ destr_eq chid id'; repeat zmap_simpl; intros Hused' Hid'; cbn; auto.
destr_eq id (cparent (ZMap.get id' cp)); zmap_simpl; cbn.
× subst c; auto.
× destr_eq chid (cparent (ZMap.get id' cp)); [rewrite Heq |];
zmap_simpl; auto.
rewrite Heq in Hchused. apply cvalid_parent_used0 in Hused'.
congruence.
-
+ intros Hused' Hid'.
destr_eq id' (cparent c'); [rewrite Heq |]; zmap_simpl.
× subst c c'; right; cbn; cbn in Heq.
rewrite <- Heq.
replace (ZMap.get id' cp) with
(ZMap.get (cparent (ZMap.get id' cp)) cp) by congruence.
apply cvalid_parents_child0; auto.
× destr_eq chid (cparent c'); [rewrite Heq |]; zmap_simpl; cbn; eauto.
subst c; cbn in Heq. rewrite Heq in Hchused.
apply cvalid_parent_used0 in Hused'. congruence.
+ destr_eq chid id'; repeat zmap_simpl; intros Hused' Hid'; cbn; auto.
destr_eq id (cparent (ZMap.get id' cp)); zmap_simpl; cbn.
× subst c; auto.
× destr_eq chid (cparent (ZMap.get id' cp)); [rewrite Heq |];
zmap_simpl; auto.
rewrite Heq in Hchused. apply cvalid_parent_used0 in Hused'.
congruence.
-
cvalid_childrens_parent
rewrite Forall_forall.
destr_eq id id'; zmap_simpl.
+ intros Hused' id'' Hin.
specialize (cvalid_childrens_parent0 _ Hused).
rewrite Forall_forall in cvalid_childrens_parent0.
destr_eq id' id''; zmap_simpl; subst c c'; cbn in ×.
× destruct Hin as [Heq | Hin]; [congruence | auto].
× destr_eq chid id''; zmap_simpl; auto.
destruct Hin as [Heq | Hin]; [congruence | auto].
+ destr_eq chid id'; zmap_simpl; intros Hused' id'' Hin; [contradiction |].
specialize (cvalid_childrens_parent0 _ Hused').
rewrite Forall_forall in cvalid_childrens_parent0.
destr_eq id id''; zmap_simpl; try solve [subst c c'; cbn in *; auto].
destr_eq chid id''; zmap_simpl; auto.
specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
specialize (cvalid_children_used0 _ Hin).
congruence.
-
destr_eq id id'; zmap_simpl.
+ intros Hused' id'' Hin.
specialize (cvalid_childrens_parent0 _ Hused).
rewrite Forall_forall in cvalid_childrens_parent0.
destr_eq id' id''; zmap_simpl; subst c c'; cbn in ×.
× destruct Hin as [Heq | Hin]; [congruence | auto].
× destr_eq chid id''; zmap_simpl; auto.
destruct Hin as [Heq | Hin]; [congruence | auto].
+ destr_eq chid id'; zmap_simpl; intros Hused' id'' Hin; [contradiction |].
specialize (cvalid_childrens_parent0 _ Hused').
rewrite Forall_forall in cvalid_childrens_parent0.
destr_eq id id''; zmap_simpl; try solve [subst c c'; cbn in *; auto].
destr_eq chid id''; zmap_simpl; auto.
specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
specialize (cvalid_children_used0 _ Hin).
congruence.
-
cvalid_cqb
destr_eq id id'; zmap_simpl.
+ intros Hused'.
destr_eq chid id'.
× rewrite Heq in Hchused. subst c; cbn in Hused'. congruence.
× constructor; repeat zmap_simpl; cbn; [omega |].
apply cqb_reorder; auto.
subst c c'; cbn in ×.
apply cqb_notin.
-- specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
intros Hin; specialize (cvalid_children_used0 _ Hin).
congruence.
-- apply cqb_weaken; [cbn; omega | eauto].
+ destr_eq chid id'; zmap_simpl; cbn; intros Hused'.
constructor; reflexivity.
destr_eq id chid; [rewrite Heq; zmap_simpl |].
× apply cqb_notin; auto.
specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
intros Hin. specialize (cvalid_children_used0 _ Hin).
congruence.
× apply cqb_reorder; auto.
subst c c'; cbn in ×.
apply cqb_notin.
-- specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
intros Hin. specialize (cvalid_children_used0 _ Hin).
congruence.
-- apply cqb_weaken; [cbn; omega | auto].
-
+ intros Hused'.
destr_eq chid id'.
× rewrite Heq in Hchused. subst c; cbn in Hused'. congruence.
× constructor; repeat zmap_simpl; cbn; [omega |].
apply cqb_reorder; auto.
subst c c'; cbn in ×.
apply cqb_notin.
-- specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
intros Hin; specialize (cvalid_children_used0 _ Hin).
congruence.
-- apply cqb_weaken; [cbn; omega | eauto].
+ destr_eq chid id'; zmap_simpl; cbn; intros Hused'.
constructor; reflexivity.
destr_eq id chid; [rewrite Heq; zmap_simpl |].
× apply cqb_notin; auto.
specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
intros Hin. specialize (cvalid_children_used0 _ Hin).
congruence.
× apply cqb_reorder; auto.
subst c c'; cbn in ×.
apply cqb_notin.
-- specialize (cvalid_children_used0 _ Hused').
rewrite Forall_forall in cvalid_children_used0.
intros Hin. specialize (cvalid_children_used0 _ Hin).
congruence.
-- apply cqb_weaken; [cbn; omega | auto].
-
cvalid_nodup
destr_eq id id'; zmap_simpl.
+ intros Hused'. constructor; eauto.
specialize (cvalid_children_used0 _ Hused).
rewrite Forall_forall in cvalid_children_used0.
intros Hin. specialize (cvalid_children_used0 _ Hin).
congruence.
+ destr_eq chid id'; zmap_simpl; [constructor | auto].
Qed.
+ intros Hused'. constructor; eauto.
specialize (cvalid_children_used0 _ Hused).
rewrite Forall_forall in cvalid_children_used0.
intros Hin. specialize (cvalid_children_used0 _ Hin).
congruence.
+ destr_eq chid id'; zmap_simpl; [constructor | auto].
Qed.
Container Struct Field Offsets
Lemma container_fields_off_rewrite : ∀ foff i,
0 ≤ Int.unsigned i < NUM_ID →
0 ≤ foff < con_sz →
(Ptrofs.unsigned
(Ptrofs.add
(Ptrofs.add Ptrofs.zero
(Ptrofs.mul (Ptrofs.repr con_sz) (Ptrofs.of_intu i)))
(Ptrofs.repr foff))) = con_sz × Int.unsigned i + foff.
Proof.
intros ? ? Hi_range Hoff_range.
pose proof NUM_ID_range as Hnid_range.
pose proof int_ptrofs_max as Hint_ptr.
rewrite Ptrofs.add_zero_l.
unfold Ptrofs.add, Ptrofs.mul, Ptrofs.zero, Ptrofs.of_intu, Ptrofs.of_int.
assert (con_sz ≤ Int.max_unsigned) by auto.
unfold_fields.
repeat rewrite Ptrofs.unsigned_repr; omega.
Qed.
Corollary container_fields_store_ok : ∀ foff m m' b i v,
0 ≤ Int.unsigned i < NUM_ID →
0 ≤ foff < con_sz →
Mem.store Mint32 m b (con_sz × Int.unsigned i + foff) v = Some m' →
Mem.store Mint32 m b
(Ptrofs.unsigned
(Ptrofs.add
(Ptrofs.add Ptrofs.zero
(Ptrofs.mul (Ptrofs.repr con_sz) (Ptrofs.of_intu i)))
(Ptrofs.repr foff))) v = Some m'.
Proof. intros; rewrite container_fields_off_rewrite; auto. Qed.
Corollary container_fields_load_ok : ∀ foff m b i v,
0 ≤ Int.unsigned i < NUM_ID →
0 ≤ foff < con_sz →
Mem.load Mint32 m b (con_sz × Int.unsigned i + foff) = Some v →
Mem.load Mint32 m b
(Ptrofs.unsigned
(Ptrofs.add
(Ptrofs.add Ptrofs.zero
(Ptrofs.mul (Ptrofs.repr con_sz) (Ptrofs.of_intu i)))
(Ptrofs.repr foff))) = Some v.
Proof. intros; rewrite container_fields_off_rewrite; auto. Qed.
We will also need to know that the field offsets are aligned on the size
of an integer (4 bytes).
Lemma container_fields_align : ∀ i off,
(off = quo_off ∨ off = usg_off ∨ off = par_off ∨ off = nch_off ∨ off = use_off) →
(4 | 20 × i + off).
Proof.
intros.
replace (20 × i) with (4 × (5 × i)) by omega.
apply Z.divide_add_r; [apply Z.divide_factor_l |].
destruct H as [? | [? | [? | [? | ?]]]]; subst.
- now ∃ 0.
- now ∃ 1.
- now ∃ 2.
- now ∃ 3.
- now ∃ 4.
Qed.
End CONTAINER_PROP.
(off = quo_off ∨ off = usg_off ∨ off = par_off ∨ off = nch_off ∨ off = use_off) →
(4 | 20 × i + off).
Proof.
intros.
replace (20 × i) with (4 × (5 × i)) by omega.
apply Z.divide_add_r; [apply Z.divide_factor_l |].
destruct H as [? | [? | [? | [? | ?]]]]; subst.
- now ∃ 0.
- now ∃ 1.
- now ∃ 2.
- now ∃ 3.
- now ∃ 4.
Qed.
End CONTAINER_PROP.