diff --git a/ROOT b/ROOT index aae8e41..83b28d4 100644 --- a/ROOT +++ b/ROOT @@ -6,3 +6,4 @@ session Split = HOL + Execution Protocol Snapshot + Reuse diff --git a/Reuse.thy b/Reuse.thy new file mode 100644 index 0000000..45fa967 --- /dev/null +++ b/Reuse.thy @@ -0,0 +1,209 @@ +theory Reuse + imports Snapshot +begin + +definition vacant :: "nat \ pager \ nat \ bool" where + "vacant slots s f = list_all (\k. ptable s k \ f) [0.. (\k f)" + by (auto simp: vacant_def list_all_iff) + +definition copy_frame :: "pager \ nat \ nat \ pager" where + "copy_frame s k f = s\ptable := (ptable s)(k := f), + physical := (physical s)(f := view s k), writable := (writable s)(k := True), + frontier := max (frontier s) (Suc f)\" + +definition clear_slot :: "nat \ pager \ nat \ pager" where + "clear_slot pages s k = s\ptable := (ptable s)(k := k mod pages), + physical := (physical s)(ptable s k := (\_. 0)), writable := (writable s)(k := False)\" + +definition pooled :: "nat \ nat \ pager \ nat list \ bool" where + "pooled pages slots s available \ + invariant slots s \ private_frames pages slots s \ distinct available \ + (\f\set available. pages \ f \ f < frontier s \ + vacant slots s f \ physical s f = (\_. 0))" + +definition reserve :: "nat \ nat \ nat \ pager \ nat list \ nat \ (pager \ nat list) option" where + "reserve pages slots capacity s available k = + (let f = (case available of [] \ frontier s | x # xs \ x) in + if 0 < pages \ k < slots \ \ writable s k \ pages \ f \ + f < capacity \ vacant slots s f + then Some (copy_frame s k f, tl available) else None)" + +definition reclaim :: "nat \ nat \ pager \ nat list \ nat \ (pager \ nat list) option" where + "reclaim pages slots s available k = + (if 0 < pages \ k < slots \ writable s k \ pages \ ptable s k \ + ptable s k \ set available \ + list_all (\j. j = k \ ptable s j \ ptable s k) [0.. pooled pages slots (initial pages contents) []" + by (simp add: pooled_def initial_invariant initial_private) + +lemma copy_view: + "vacant slots s f \ j < slots \ view (copy_frame s k f) j = view s j" + by (auto simp: view_def copy_frame_def) + +lemma copy_bounded: + "bounded slots s \ bounded slots (copy_frame s k f)" + by (auto simp: bounded_def copy_frame_def max_def) + +lemma copy_exclusive: + "exclusive slots s \ vacant slots s f \ exclusive slots (copy_frame s k f)" + by (auto simp: exclusive_def copy_frame_def split: if_splits) + +lemma copy_invariant: + "invariant slots s \ vacant slots s f \ invariant slots (copy_frame s k f)" + by (simp add: invariant_def copy_bounded copy_exclusive) + +lemma copy_private: + "private_frames pages slots s \ pages \ f \ + private_frames pages slots (copy_frame s k f)" + by (auto simp: private_frames_def copy_frame_def max_def) + +lemma copy_original: + "pages \ f \ original < pages \ + physical (copy_frame s k f) original = physical s original" + by (auto simp: copy_frame_def) + +lemma clear_bounded: + "0 < pages \ bounded slots s \ pages \ frontier s \ + bounded slots (clear_slot pages s k)" + by (auto simp: bounded_def clear_slot_def intro: less_le_trans[OF mod_less_divisor]) + +lemma clear_exclusive: + "0 < pages \ exclusive slots s \ private_frames pages slots s \ + exclusive slots (clear_slot pages s k)" + by (auto simp: exclusive_def private_frames_def clear_slot_def split: if_splits; metis mod_less_divisor not_le) + +lemma clear_private: + "private_frames pages slots s \ private_frames pages slots (clear_slot pages s k)" + by (auto simp: private_frames_def clear_slot_def) + +lemma clear_invariant: + "0 < pages \ invariant slots s \ private_frames pages slots s \ + invariant slots (clear_slot pages s k)" + by (metis invariant_def private_frames_def clear_bounded clear_exclusive) + +lemma clear_vacant: + "0 < pages \ exclusive slots s \ k < slots \ + writable s k \ pages \ ptable s k \ + vacant slots (clear_slot pages s k) (ptable s k)" + by (auto simp: exclusive_def clear_slot_def; metis mod_less_divisor not_le) + +lemma clear_other_view: + "exclusive slots s \ k < slots \ writable s k \ + j < slots \ j \ k \ view (clear_slot pages s k) j = view s j" + by (auto simp: exclusive_def clear_slot_def view_def) + +lemma clear_target_view: + "0 < pages \ pages \ ptable s k \ + view (clear_slot pages s k) k = physical s (k mod pages)" + by (auto simp: clear_slot_def view_def; metis mod_less_divisor not_le) + +lemma clear_original: + "pages \ ptable s k \ f < pages \ + physical (clear_slot pages s k) f = physical s f" + by (auto simp: clear_slot_def) + +theorem reclaim_zero: + "reclaim pages slots s available k = Some (t, remaining) \ + physical t (ptable s k) = (\_. 0)" + by (auto simp: reclaim_def clear_slot_def split: if_splits) + +theorem reclaim_unmapped: + assumes pool: "pooled pages slots s available" + and step: "reclaim pages slots s available k = Some (t, remaining)" + shows "vacant slots t (ptable s k)" + using pool step + by (auto simp: reclaim_def pooled_def invariant_def split: if_splits; metis clear_vacant vacant_iff) + +theorem reclaim_views: + assumes "pooled pages slots s available" + "reclaim pages slots s available k = Some (t, remaining)" "j < slots" + shows "view t j = (if j = k then physical s (k mod pages) else view s j)" + using assms clear_other_view clear_target_view + by (auto simp: pooled_def reclaim_def invariant_def split: if_splits) + +theorem reclaim_pool: + assumes pool: "pooled pages slots s available" + and step: "reclaim pages slots s available k = Some (t, remaining)" + shows "pooled pages slots t remaining" +proof - + have positive: "0 < pages" and valid: "k < slots" and writable: "writable s k" + and private_frame: "pages \ ptable s k" and fresh: "ptable s k \ set available" + and result: "t = clear_slot pages s k" "remaining = ptable s k # available" + using step by (auto simp: reclaim_def split: if_splits) + have inv: "invariant slots s" and owned: "private_frames pages slots s" + using pool by (auto simp: pooled_def) + have new_inv: "invariant slots t" and new_owned: "private_frames pages slots t" + using clear_invariant[OF positive inv owned] clear_private[OF owned] result by auto + have unused: "vacant slots t (ptable s k)" + using reclaim_unmapped[OF pool step] . + have clean: "physical t (ptable s k) = (\_. 0)" + using reclaim_zero[OF step] . + show ?thesis + using pool fresh result positive valid private_frame inv new_inv new_owned unused clean + by (auto simp: pooled_def clear_slot_def bounded_def invariant_def split: if_splits; metis mod_less_divisor not_le) +qed + +theorem reserve_views: + "reserve pages slots capacity s available k = Some (t, remaining) \ + j < slots \ view t j = view s j" + by (auto simp: reserve_def Let_def split: list.splits if_splits intro: copy_view) + +theorem reserve_pool: + assumes pool: "pooled pages slots s available" + and step: "reserve pages slots capacity s available k = Some (t, remaining)" + shows "pooled pages slots t remaining" +proof (cases available) + case Nil + then have fresh: "vacant slots s (frontier s)" + using pool by (auto simp: pooled_def invariant_def bounded_def) + have owned: "pages \ frontier s" using pool by (auto simp: pooled_def private_frames_def) + show ?thesis + using step pool fresh owned Nil copy_invariant copy_private + by (auto simp: reserve_def Let_def pooled_def split: if_splits) +next + case (Cons f rest) + have fresh: "vacant slots s f" and owned: "pages \ f" + and distinct: "f \ set rest" + using pool Cons by (auto simp: pooled_def) + have result: "t = copy_frame s k f" "remaining = rest" + using step Cons by (auto simp: reserve_def Let_def split: if_splits) + have inv: "invariant slots t" and own: "private_frames pages slots t" + using pool result fresh owned copy_invariant copy_private by (auto simp: pooled_def) + show ?thesis + using pool Cons distinct result inv own + by (auto simp: pooled_def copy_frame_def max_def split: if_splits) +qed + +theorem reserve_original: + "reserve pages slots capacity s available k = Some (t, remaining) \ + f < pages \ physical t f = physical s f" + by (auto simp: reserve_def Let_def split: list.splits if_splits intro: copy_original) + +theorem reclaim_original: + "reclaim pages slots s available k = Some (t, remaining) \ + f < pages \ physical t f = physical s f" + by (auto simp: reclaim_def split: if_splits intro: clear_original) + +theorem pooled_unmapped: + "pooled pages slots s available \ f \ set available \ + j < slots \ ptable s j \ f" + by (auto simp: pooled_def) + +theorem pooled_clean: + "pooled pages slots s available \ f \ set available \ + physical s f offset = 0" + by (auto simp: pooled_def) + +theorem pooled_store: + assumes "pooled pages slots s available" "k < slots" "writable s k" + shows "pooled pages slots (store s k offset byte) available" + using assms write_invariant[of slots s k offset byte] store_private[of pages slots s k offset byte] + by (auto simp: pooled_def store_def prepare_def Let_def) + +end