diff --git a/crate/memory/src/lib.rs b/crate/memory/src/lib.rs index ffdb24b..4f08587 100644 --- a/crate/memory/src/lib.rs +++ b/crate/memory/src/lib.rs @@ -4,4 +4,7 @@ extern crate alloc; pub mod memory_set; -pub mod swap; \ No newline at end of file +pub mod swap; +pub mod page_table; + +type VirtAddr = usize; \ No newline at end of file diff --git a/crate/memory/src/swap/mock_page_table.rs b/crate/memory/src/page_table/mock_page_table.rs similarity index 74% rename from crate/memory/src/swap/mock_page_table.rs rename to crate/memory/src/page_table/mock_page_table.rs index b3f0088..b26e6c0 100644 --- a/crate/memory/src/swap/mock_page_table.rs +++ b/crate/memory/src/page_table/mock_page_table.rs @@ -2,36 +2,47 @@ use alloc::btree_set::BTreeSet; use super::*; pub struct MockPageTable { - mapped_set: BTreeSet, - accessed_set: BTreeSet, - dirty_set: BTreeSet, + mapped_set: BTreeSet, + accessed_set: BTreeSet, + dirty_set: BTreeSet, page_fault_handler: PageFaultHandler, capacity: usize, } -type PageFaultHandler = fn(&mut MockPageTable, Addr); +type PageFaultHandler = fn(&mut MockPageTable, VirtAddr); impl PageTable for MockPageTable { - fn accessed(&self, addr: Addr) -> bool { + fn accessed(&self, addr: VirtAddr) -> bool { self.accessed_set.contains(&addr) } - fn dirty(&self, addr: Addr) -> bool { + fn dirty(&self, addr: VirtAddr) -> bool { self.dirty_set.contains(&addr) } + /// Map a page, return false if no more space + fn map(&mut self, addr: VirtAddr) -> bool { + if self.mapped_set.len() == self.capacity { + return false; + } + self.mapped_set.insert(addr); + true + } + fn unmap(&mut self, addr: VirtAddr) { + self.mapped_set.remove(&addr); + } } impl MockPageTable { pub fn new(capacity: usize, page_fault_handler: PageFaultHandler) -> Self { MockPageTable { - mapped_set: BTreeSet::::new(), - accessed_set: BTreeSet::::new(), - dirty_set: BTreeSet::::new(), + mapped_set: BTreeSet::::new(), + accessed_set: BTreeSet::::new(), + dirty_set: BTreeSet::::new(), page_fault_handler, capacity, } } /// Read memory, mark accessed, trigger page fault if not present - pub fn read(&mut self, addr: Addr) { + pub fn read(&mut self, addr: VirtAddr) { while !self.mapped_set.contains(&addr) { (self.page_fault_handler)(self, addr); } @@ -39,25 +50,13 @@ impl MockPageTable { } /// Write memory, mark accessed and dirty, trigger page fault if not present - pub fn write(&mut self, addr: Addr) { + pub fn write(&mut self, addr: VirtAddr) { while !self.mapped_set.contains(&addr) { (self.page_fault_handler)(self, addr); } self.accessed_set.insert(addr); self.dirty_set.insert(addr); } - /// Map a page, return false if no more space - pub fn map(&mut self, addr: Addr) -> bool { - if self.mapped_set.len() == self.capacity { - return false; - } - self.mapped_set.insert(addr); - true - } - /// Unmap a page - pub fn unmap(&mut self, addr: Addr) { - self.mapped_set.remove(&addr); - } } #[cfg(test)] @@ -72,7 +71,7 @@ mod test { #[test] fn test() { - fn page_fault_handler(pt: &mut MockPageTable, addr: Addr) { + fn page_fault_handler(pt: &mut MockPageTable, addr: VirtAddr) { unsafe{ PGFAULT_COUNT += 1; } pt.map(addr); } diff --git a/crate/memory/src/page_table/mod.rs b/crate/memory/src/page_table/mod.rs new file mode 100644 index 0000000..245311a --- /dev/null +++ b/crate/memory/src/page_table/mod.rs @@ -0,0 +1,10 @@ +use super::*; + +pub mod mock_page_table; + +pub trait PageTable { + fn accessed(&self, addr: VirtAddr) -> bool; + fn dirty(&self, addr: VirtAddr) -> bool; + fn map(&mut self, addr: VirtAddr) -> bool; + fn unmap(&mut self, addr: VirtAddr); +} \ No newline at end of file diff --git a/crate/memory/src/swap/fifo.rs b/crate/memory/src/swap/fifo.rs index 4a006ee..fd7c912 100644 --- a/crate/memory/src/swap/fifo.rs +++ b/crate/memory/src/swap/fifo.rs @@ -3,14 +3,14 @@ use super::*; struct FifoSwapManager { page_table: &'static T, - deque: VecDeque, + deque: VecDeque, } impl SwapManager for FifoSwapManager { fn new(page_table: &'static T) -> Self { FifoSwapManager { page_table, - deque: VecDeque::::new() + deque: VecDeque::::new() } } @@ -29,7 +29,7 @@ impl SwapManager for FifoSwapManager { self.deque.remove(id); } - fn pop(&mut self) -> Option { + fn pop(&mut self) -> Option { self.deque.pop_front() } } @@ -37,7 +37,7 @@ impl SwapManager for FifoSwapManager { #[cfg(test)] mod test { use super::*; - use super::mock_page_table::MockPageTable; + use page_table::mock_page_table::MockPageTable; enum MemOp { R(usize), W(usize) @@ -52,7 +52,7 @@ mod test { static mut PAGE: *mut MockPageTable = 0 as *mut _; static mut FIFO: *mut FifoSwapManager = 0 as *mut _; - fn page_fault_handler(pt: &mut MockPageTable, addr: Addr) { + fn page_fault_handler(pt: &mut MockPageTable, addr: VirtAddr) { unsafe{ PGFAULT_COUNT += 1; } let fifo = unsafe{ &mut *FIFO }; if !pt.map(addr) { // is full? diff --git a/crate/memory/src/swap/mod.rs b/crate/memory/src/swap/mod.rs index 214779c..6d1c350 100644 --- a/crate/memory/src/swap/mod.rs +++ b/crate/memory/src/swap/mod.rs @@ -1,25 +1,20 @@ +use super::*; +use super::page_table::PageTable; + pub mod fifo; -mod mock_page_table; mod mock_swapper; -type Addr = usize; - trait SwapManager { /// Create and initialize for the swap manager fn new(page_table: &'static 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); + fn push(&mut self, addr: VirtAddr); /// Called to delete the addr entry from the swap manager - fn remove(&mut self, addr: Addr); + fn remove(&mut self, addr: VirtAddr); /// Try to swap out a page, return then victim - fn pop(&mut self) -> Option; -} - -trait PageTable { - fn accessed(&self, addr: Addr) -> bool; - fn dirty(&self, addr: Addr) -> bool; + fn pop(&mut self) -> Option; } trait Swapper {