From a1e9ee36b28a015b5e67cdd9010d45c7dc21d08f Mon Sep 17 00:00:00 2001 From: WangRunji Date: Thu, 19 Apr 2018 11:37:13 +0800 Subject: [PATCH] Basic SwapManager & MockPageTable --- crate/memory/src/lib.rs | 3 +- crate/memory/src/swap/fifo.rs | 50 ++++++++++++++ crate/memory/src/swap/mock_page_table.rs | 88 ++++++++++++++++++++++++ crate/memory/src/swap/mod.rs | 22 ++++++ 4 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 crate/memory/src/swap/fifo.rs create mode 100644 crate/memory/src/swap/mock_page_table.rs create mode 100644 crate/memory/src/swap/mod.rs diff --git a/crate/memory/src/lib.rs b/crate/memory/src/lib.rs index 8eb011e..ffdb24b 100644 --- a/crate/memory/src/lib.rs +++ b/crate/memory/src/lib.rs @@ -3,4 +3,5 @@ extern crate alloc; -pub mod memory_set; \ No newline at end of file +pub mod memory_set; +pub mod swap; \ No newline at end of file diff --git a/crate/memory/src/swap/fifo.rs b/crate/memory/src/swap/fifo.rs new file mode 100644 index 0000000..7e92951 --- /dev/null +++ b/crate/memory/src/swap/fifo.rs @@ -0,0 +1,50 @@ +use alloc::vec_deque::VecDeque; +use super::*; + +struct FifoSwapManager { + deque: VecDeque, +} + +impl SwapManager for FifoSwapManager { + fn new(_page_table: &T) -> Self { + FifoSwapManager { + deque: VecDeque::::new() + } + } + + fn tick(&mut self) { + + } + + fn push(&mut self, addr: usize) { + self.deque.push_back(addr); + } + + fn pop(&mut self, addr: usize) { + let id = self.deque.iter() + .position(|&x| x == addr) + .expect("address not found"); + self.deque.remove(id); + } + + fn swap(&mut self) -> Option { + self.deque.pop_front() + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test() { +// let mut pt = mock_page_table::MockPageTable::new(); +// let mut sm = FifoSwapManager::new(); +// let write_seq = [3, 1, 4, 2, 5, 2, 1, 2, 3, 4, 5, 1, 1]; +// let pgfault_count = [4, 4, 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 11]; +// for i in write_seq { +// pt.write(i); +// } + + } +} \ No newline at end of file diff --git a/crate/memory/src/swap/mock_page_table.rs b/crate/memory/src/swap/mock_page_table.rs new file mode 100644 index 0000000..ba5185f --- /dev/null +++ b/crate/memory/src/swap/mock_page_table.rs @@ -0,0 +1,88 @@ +use alloc::btree_set::BTreeSet; +use super::*; + +pub struct MockPageTable { + mapped_set: BTreeSet, + accessed_set: BTreeSet, + dirty_set: BTreeSet, + pgfault_handler: PgfaultHandler, +} + +type PgfaultHandler = fn(&mut MockPageTable, Addr); + +impl PageTable for MockPageTable { + fn accessed(&self, addr: Addr) -> bool { + self.accessed_set.contains(&addr) + } + fn dirty(&self, addr: Addr) -> bool { + self.dirty_set.contains(&addr) + } +} + +impl MockPageTable { + pub fn new(pgfault_handler: PgfaultHandler) -> Self { + MockPageTable { + mapped_set: BTreeSet::::new(), + accessed_set: BTreeSet::::new(), + dirty_set: BTreeSet::::new(), + pgfault_handler, + } + } + /// Read memory, mark accessed, trigger page fault if not present + pub fn read(&mut self, addr: Addr) { + while !self.mapped_set.contains(&addr) { + (self.pgfault_handler)(self, addr); + } + self.accessed_set.insert(addr); + + } + /// Write memory, mark accessed and dirty, trigger page fault if not present + pub fn write(&mut self, addr: Addr) { + while !self.mapped_set.contains(&addr) { + (self.pgfault_handler)(self, addr); + } + self.accessed_set.insert(addr); + self.dirty_set.insert(addr); + } + pub fn map(&mut self, addr: Addr) { + self.mapped_set.insert(addr); + } + pub fn unmap(&mut self, addr: Addr) { + self.mapped_set.remove(&addr); + } +} + +#[cfg(test)] +mod test { + use super::*; + + static mut PGFAULT_COUNT: usize = 0; + + fn assert_pgfault_eq(x: usize) { + assert_eq!(unsafe{ PGFAULT_COUNT }, x); + } + + #[test] + fn test() { + fn pgfault_handler(pt: &mut MockPageTable, addr: Addr) { + unsafe{ PGFAULT_COUNT += 1; } + pt.map(addr); + } + let mut pt = MockPageTable::new(pgfault_handler); + + pt.map(0); + pt.read(0); + assert_pgfault_eq(0); + assert!(pt.accessed(0)); + assert!(!pt.dirty(0)); + + pt.write(1); + assert_pgfault_eq(1); + assert!(pt.accessed(1)); + assert!(pt.dirty(1)); + + pt.unmap(0); + pt.read(0); + assert_pgfault_eq(2); + } +} \ No newline at end of file diff --git a/crate/memory/src/swap/mod.rs b/crate/memory/src/swap/mod.rs new file mode 100644 index 0000000..8a65921 --- /dev/null +++ b/crate/memory/src/swap/mod.rs @@ -0,0 +1,22 @@ +pub mod fifo; +mod mock_page_table; + +type Addr = usize; + +trait SwapManager { + /// Create and initialize for the swap manager + fn new(page_table: &T) -> Self; + /// Called when tick interrupt occured + fn tick(&mut self); + /// Called when map a swappable page into the memory + fn push(&mut self, addr: Addr); + /// Called to delete the addr entry from the swap manager + fn pop(&mut self, addr: Addr); + /// Try to swap out a page, return then victim + fn swap(&mut self) -> Option; +} + +trait PageTable { + fn accessed(&self, addr: Addr) -> bool; + fn dirty(&self, addr: Addr) -> bool; +} \ No newline at end of file