(*Lemma permDisjoint_sub: forall r1 r2 p, join_sub r2 r1 -> permDisjoint (perm_of_res r1) p -> permDisjoint (perm_of_res r2) p.  Lemma permMapsDisjoint_permDisjoint: forall r1 r2 b ofs, permMapsDisjoint r1 r2 -> permDisjoint (r1 !! b ofs) (r2 !! b ofs). intros. destruct  (H b ofs) as [k H']. exists k; assumption. Qed.  Lemma empty_disjoint': forall pmap, permMapsDisjoint empty_map pmap. intros pmap b ofs. exists (pmap !! b ofs). rewrite empty_map_spec; reflexivity. Qed. Lemma empty_disjoint: permMapsDisjoint empty_map empty_map. unfold permMapsDisjoint. unfold empty_map; intros; simpl. unfold Maps.PMap.get; simpl. rewrite Maps.PTree.gempty; simpl. exists None; reflexivity. Qed.  Lemma permMapsDisjoint_comm : forall pmap1 pmap2 (Hdis: permMapsDisjoint pmap1 pmap2), permMapsDisjoint pmap2 pmap1.  Lemma permMapsDisjoint2_comm: forall pmaps pmaps', permMapsDisjoint2 pmaps pmaps' <-> permMapsDisjoint2 pmaps' pmaps.  Lemma disjoint_norace: forall (mi mj : mem) (b : block) (ofs : Z) (Hdisjoint: permMapsDisjoint (getCurPerm mi) (getCurPerm mj)) (Hpermj: Mem.perm mj b ofs Cur Readable) (Hpermi: Mem.perm mi b ofs Cur Writable), False.  Definition isCanonical (pmap : access_map) := pmap.1 = fun _ => None. Import Maps. Definition TreeMaxIndex {A} (t:Maps.PTree.t A): positive:= compcert.lib.Coqlib.list_fold_left (fun a => [eta Pos.max a.1]) 1%positive (Maps.PTree.elements t) . Lemma fold_max_monoton: forall  {A} (ls: seq.seq (positive * A)), forall i, (Coqlib.list_fold_left (fun a => [eta Pos.max a.1]) i ls >= i)%positive. Lemma fold_max_monoton': forall  {A} (ls: seq.seq (positive * A)), forall i j, (i >= j)%positive -> (compcert.lib.Coqlib.list_fold_left (fun a => [eta Pos.max a.1]) i ls >= compcert.lib.Coqlib.list_fold_left (fun a => [eta Pos.max a.1]) j ls)%positive. Lemma TreeMaxIndex_help: forall {A} (ls: seq.seq (positive * A)), forall i v, In (i, v) ls -> (compcert.lib.Coqlib.list_fold_left (fun a => [eta Pos.max a.1]) 1%positive ls >= i)%positive.  Lemma max_works: forall A (t:PTree.t A) m, (m > TreeMaxIndex t)%positive -> t ! m = None.  Lemma Cur_isCanonical: forall m, isCanonical (getCurPerm m). unfold isCanonical. intros. pose (BigNumber:= Pos.max (Pos.succ( TreeMaxIndex (getCurPerm m).2) ) (Mem.nextblock m)). assert (HH: (BigNumber >= (Pos.succ ( TreeMaxIndex (getCurPerm m).2)))%positive ) by (unfold BigNumber; apply Pos.le_ge; apply Pos.le_max_l). apply Pos.ge_le in HH; apply Pos.le_succ_l in HH. apply Pos.lt_gt in HH; eapply max_works in HH. extensionality x. pose (property:= Mem.nextblock_noaccess m BigNumber x Cur). rewrite <- property. - replace ((Mem.mem_access m) !! BigNumber x Cur) with (permission_at m BigNumber x Cur); try reflexivity. rewrite <- getCurPerm_correct. unfold PMap.get. rewrite HH. reflexivity. - apply Pos.le_nlt. unfold BigNumber. apply Pos.le_max_r. Qed.  Lemma Max_isCanonical: forall m, isCanonical (getMaxPerm m). unfold isCanonical. intros. pose (BigNumber:= Pos.max (Pos.succ( TreeMaxIndex (getMaxPerm m).2) ) (Mem.nextblock m)). assert (HH: (BigNumber >= (Pos.succ ( TreeMaxIndex (getMaxPerm m).2)))%positive ) by (unfold BigNumber; apply Pos.le_ge; apply Pos.le_max_l). apply Pos.ge_le in HH; apply Pos.le_succ_l in HH. apply Pos.lt_gt in HH; eapply max_works in HH. extensionality x. pose (property:= Mem.nextblock_noaccess m BigNumber x Max). rewrite <- property. - replace ((Mem.mem_access m) !! BigNumber x Max) with (permission_at m BigNumber x Max); try reflexivity. rewrite <- getMaxPerm_correct. unfold PMap.get. rewrite HH. reflexivity. - apply Pos.le_nlt. unfold BigNumber. apply Pos.le_max_r. Qed.  Definition permMapLt (pmap1 pmap2 : access_map) : Prop := forall b ofs, Mem.perm_order'' (Maps.PMap.get b pmap2 ofs) (Maps.PMap.get b pmap1 ofs).  Lemma empty_LT: forall pmap, permMapLt empty_map pmap. intros pmap b ofs. rewrite empty_map_spec. destruct (pmap !! b ofs); simpl; exact I. Qed.  Lemma canonical_lt : forall p' m (Hlt: permMapLt p' (getMaxPerm m)), isCanonical p'.  Lemma invalid_block_empty: forall pmap m (Hlt: permMapLt pmap (getMaxPerm m)), forall b, ~ Mem.valid_block m b -> forall ofs, pmap !! b ofs = None.  Definition setPerm (p : option permission) (b : block) (ofs : Z) (pmap : access_map) : access_map := Maps.PMap.set b (fun ofs' => if compcert.lib.Coqlib.zeq ofs ofs' then p else Maps.PMap.get b pmap ofs') pmap.  Fixpoint setPermBlock (p : option permission) (b : block) (ofs : Z) (pmap : access_map) (length: nat): access_map := match length with 0 => pmap | S len => setPerm p b (ofs + (Z_of_nat len))%Z (setPermBlock p b ofs pmap len) end.  Lemma setPermBlock_same: forall p b ofs ofs' pmap sz (Hofs: (ofs <= ofs' < ofs + (Z.of_nat sz))%Z), (Maps.PMap.get b (setPermBlock p b ofs pmap sz)) ofs' = p.  Lemma setPermBlock_other_1: forall p b ofs ofs' pmap sz (Hofs: (ofs' < ofs)%Z \/ (ofs' >= ofs + (Z.of_nat sz))%Z), (Maps.PMap.get b (setPermBlock p b ofs pmap sz)) ofs' = Maps.PMap.get b pmap ofs'.  Lemma setPermBlock_other_2: forall p b b' ofs ofs' pmap sz, b <> b' -> (Maps.PMap.get b' (setPermBlock p b ofs pmap sz)) ofs' = Maps.PMap.get b' pmap ofs'.  Lemma setPermBlock_or: forall p b ofs sz pmap b' ofs', (setPermBlock p b ofs pmap sz) !! b' ofs' = p \/ (setPermBlock p b ofs pmap sz) !! b' ofs' = pmap !! b' ofs'.  Fixpoint setPermBlock_var (fp : nat -> option permission) (b : block) (ofs : Z) (pmap : access_map) (length: nat): access_map := match length with 0 => pmap | S len => setPerm (fp length) b (ofs + (Z_of_nat len))%Z (setPermBlock_var fp b ofs pmap len) end.  Lemma setPermBlock_var_other_2: forall p b b' ofs ofs' pmap sz, b <> b' -> (Maps.PMap.get b' (setPermBlock_var p b ofs pmap sz)) ofs' = Maps.PMap.get b' pmap ofs'.  Lemma setPermBlock_var_other_1: forall p b ofs ofs' pmap sz (Hofs: (ofs' < ofs)%Z \/ (ofs' >= ofs + (Z.of_nat sz))%Z), (Maps.PMap.get b (setPermBlock_var p b ofs pmap sz)) ofs' = Maps.PMap.get b pmap ofs'.  Lemma setPermBlock_var_same: forall p b ofs ofs' pmap sz (Hofs: (ofs <= ofs' < ofs + (Z.of_nat sz))%Z), (Maps.PMap.get b (setPermBlock_var p b ofs pmap sz)) ofs' = p (compcert.lib.Coqlib.nat_of_Z (ofs' - ofs +1)).  Lemma setPermBlock_setPermBlock_var: forall b ofs sz pmap p, setPermBlock p b ofs pmap sz = setPermBlock_var (fun _ => p) b ofs pmap sz.    (*Lemma setPermBlock_var_or: forall p b ofs sz pmap b' ofs', (setPermBlock_var p b ofs pmap sz) !! b' ofs' = p \/ (setPermBlock_var p b ofs pmap sz) !! b' ofs' = pmap !! b' ofs'.    Lemma permMapCoherence_increase: forall pmap pmap' b ofs sz_nat sz (Hsz: sz = Z.of_nat (sz_nat)) (Hcoh: permMapCoherence pmap pmap') (Hreadable: forall ofs', Intv.In ofs' (ofs, ofs + sz)%Z -> Mem.perm_order' (pmap' !! b ofs') Readable), permMapCoherence pmap (setPermBlock (Some Writable) b ofs pmap' sz_nat).  (*setPermBlock with a function*)
Fixpoint setPermBlockFunc (fp : Z -> option permission) (b : block)
(ofs : Z) (pmap : access_map) (length: nat): access_map :=
match length with
0 => pmap
| S len =>
setPerm (fp (ofs + (Z_of_nat len))%Z) b (ofs + (Z_of_nat len))%Z (setPermBlockFunc fp b ofs pmap len)
end.

(* Specifications: *)
Lemma setPermBlockFunc_same:
forall fp b ofs ofs' pmap sz
(Hofs: (ofs <= ofs' < ofs + (Z.of_nat sz))%Z),
(Maps.PMap.get b (setPermBlockFunc fp b ofs pmap sz)) ofs' = fp ofs'.
Lemma setPermBlockFunc_other_1:
forall fp b ofs ofs' pmap sz
(Hofs: (ofs' < ofs)%Z \/ (ofs' >= ofs + (Z.of_nat sz))%Z),
(Maps.PMap.get b (setPermBlock fp b ofs pmap sz)) ofs' =
Maps.PMap.get b pmap ofs'.
Lemma setPermBlockFunc_other_2:
forall fp b b' ofs ofs' pmap sz,
b <> b' ->
(Maps.PMap.get b' (setPermBlock fp b ofs pmap sz)) ofs' =
Maps.PMap.get b' pmap ofs'.
Lemma setPermBlock_coherent:
forall pmap pmap' b ofs sz
(Hcoh: permMapCoherence pmap pmap')
(Hnonempty: forall ofs', Intv.In ofs' (ofs, ofs + Z.of_nat sz)%Z ->
~ Mem.perm_order' (pmap !! b ofs') Readable),
permMapCoherence pmap (setPermBlock (Some Writable) b ofs pmap' sz).