From e2e9ead17c3419ff05c4533a8a4cbc3e2d6333f2 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 25 Apr 2018 16:17:15 +0800 Subject: [PATCH] Improve MockPageTable. Fix tests. --- .../memory/src/page_table/mock_page_table.rs | 69 +++++++++++-------- crate/memory/src/swap/enhanced_clock.rs | 10 +-- crate/memory/src/swap/fifo.rs | 12 ++-- crate/memory/src/swap/mock_swapper.rs | 18 +++-- 4 files changed, 65 insertions(+), 44 deletions(-) diff --git a/crate/memory/src/page_table/mock_page_table.rs b/crate/memory/src/page_table/mock_page_table.rs index c4aaea0..85954b8 100644 --- a/crate/memory/src/page_table/mock_page_table.rs +++ b/crate/memory/src/page_table/mock_page_table.rs @@ -1,10 +1,14 @@ -use alloc::{boxed::Box, btree_set::BTreeSet}; +use alloc::boxed::Box; use super::*; +const PAGE_COUNT: usize = 16; +const PAGE_SIZE: usize = 4096; + pub struct MockPageTable { - mapped_set: BTreeSet, - accessed_set: BTreeSet, - dirty_set: BTreeSet, + mapped: [bool; PAGE_COUNT], + accessed: [bool; PAGE_COUNT], + dirty: [bool; PAGE_COUNT], + data: [u8; PAGE_SIZE * PAGE_COUNT], page_fault_handler: Option, capacity: usize, } @@ -13,36 +17,38 @@ type PageFaultHandler = Box; impl PageTable for MockPageTable { fn accessed(&self, addr: VirtAddr) -> bool { - self.accessed_set.contains(&addr) + self.accessed[addr / PAGE_SIZE] } fn dirty(&self, addr: VirtAddr) -> bool { - self.dirty_set.contains(&addr) + self.dirty[addr / PAGE_SIZE] } fn clear_accessed(&mut self, addr: usize) { - self.accessed_set.remove(&addr); + self.accessed[addr / PAGE_SIZE] = false; } fn clear_dirty(&mut self, addr: usize) { - self.dirty_set.remove(&addr); + self.dirty[addr / PAGE_SIZE] = false; } /// Map a page, return false if no more space fn map(&mut self, addr: VirtAddr) -> bool { - if self.mapped_set.len() == self.capacity { + if self.mapped.iter().filter(|&&b| b).count() == self.capacity { return false; } - self.mapped_set.insert(addr); + self.mapped[addr / PAGE_SIZE] = true; true } fn unmap(&mut self, addr: VirtAddr) { - self.mapped_set.remove(&addr); + self.mapped[addr / PAGE_SIZE] = false; } } impl MockPageTable { pub fn new(capacity: usize) -> Self { + use core::mem::uninitialized; MockPageTable { - mapped_set: BTreeSet::::new(), - accessed_set: BTreeSet::::new(), - dirty_set: BTreeSet::::new(), + mapped: [false; PAGE_COUNT], + accessed: [false; PAGE_COUNT], + dirty: [false; PAGE_COUNT], + data: unsafe{ uninitialized() }, page_fault_handler: None, capacity, } @@ -51,22 +57,26 @@ impl MockPageTable { self.page_fault_handler = Some(page_fault_handler); } fn trigger_page_fault_if_not_present(&mut self, addr: VirtAddr) { - while !self.mapped_set.contains(&addr) { + let page_id = addr / PAGE_SIZE; + while !self.mapped[page_id] { let self_mut = unsafe{ &mut *(self as *mut Self) }; (self.page_fault_handler.as_mut().unwrap())(self_mut, addr); } } /// Read memory, mark accessed, trigger page fault if not present - pub fn read(&mut self, addr: VirtAddr) { + pub fn read(&mut self, addr: VirtAddr) -> u8 { + let page_id = addr / PAGE_SIZE; self.trigger_page_fault_if_not_present(addr); - self.accessed_set.insert(addr); - + self.accessed[page_id] = true; + self.data[addr] } /// Write memory, mark accessed and dirty, trigger page fault if not present - pub fn write(&mut self, addr: VirtAddr) { + pub fn write(&mut self, addr: VirtAddr, data: u8) { + let page_id = addr / PAGE_SIZE; self.trigger_page_fault_if_not_present(addr); - self.accessed_set.insert(addr); - self.dirty_set.insert(addr); + self.accessed[page_id] = true; + self.dirty[page_id] = true; + self.data[addr] = data; } } @@ -98,15 +108,20 @@ mod test { pt.clear_accessed(0); assert!(!pt.accessed(0)); - pt.write(1); + pt.read(1); + assert_eq!(*page_fault_count.borrow(), 0); + assert!(pt.accessed(0)); + + pt.write(0x1000, 0xff); assert_eq!(*page_fault_count.borrow(), 1); - assert!(pt.accessed(1)); - assert!(pt.dirty(1)); + assert!(pt.accessed(0x1000)); + assert!(pt.dirty(0x1000)); + assert_eq!(pt.read(0x1000), 0xff); - pt.clear_dirty(1); - assert!(!pt.dirty(1)); + pt.clear_dirty(0x1000); + assert!(!pt.dirty(0x1000)); - assert_eq!(pt.map(2), false); + assert_eq!(pt.map(0x2000), false); pt.unmap(0); pt.read(0); diff --git a/crate/memory/src/swap/enhanced_clock.rs b/crate/memory/src/swap/enhanced_clock.rs index ea782a5..64f8a9e 100644 --- a/crate/memory/src/swap/enhanced_clock.rs +++ b/crate/memory/src/swap/enhanced_clock.rs @@ -117,17 +117,17 @@ mod test { let op_seq = [ - R(1), R(2), R(3), R(4), - R(3), W(1), R(4), W(2), R(5), - R(2), W(1), R(2), R(3), R(4)]; + R(0x1000), R(0x2000), R(0x3000), R(0x4000), + R(0x3000), W(0x1000), R(0x4000), W(0x2000), R(0x5000), + R(0x2000), W(0x1000), R(0x2000), R(0x3000), R(0x4000)]; let pgfault_count = [ 1, 2, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 7]; for (op, &count) in op_seq.iter().zip(pgfault_count.iter()) { match op { - R(addr) => pt.read(*addr), - W(addr) => pt.write(*addr), + R(addr) => {pt.read(*addr);}, + W(addr) => pt.write(*addr, 0), } assert_eq!(*(*page_fault_count).borrow(), count); } diff --git a/crate/memory/src/swap/fifo.rs b/crate/memory/src/swap/fifo.rs index ed63980..1550c57 100644 --- a/crate/memory/src/swap/fifo.rs +++ b/crate/memory/src/swap/fifo.rs @@ -67,10 +67,10 @@ mod test { })); let op_seq = [ - R(1), R(2), R(3), R(4), - W(3), W(1), W(4), W(2), W(5), - W(2), W(1), W(2), W(3), W(4), - W(5), R(1), W(1)]; + R(0x1000), R(0x2000), R(0x3000), R(0x4000), + W(0x3000), W(0x1000), W(0x4000), W(0x2000), W(0x5000), + W(0x2000), W(0x1000), W(0x2000), W(0x3000), W(0x4000), + W(0x5000), R(0x1000), W(0x1000)]; let pgfault_count = [ 1, 2, 3, 4, 4, 4, 4, 4, 5, @@ -78,8 +78,8 @@ mod test { 10, 11, 11]; for (op, &count) in op_seq.iter().zip(pgfault_count.iter()) { match op { - R(addr) => pt.read(*addr), - W(addr) => pt.write(*addr), + R(addr) => {pt.read(*addr);}, + W(addr) => pt.write(*addr, 0), } assert_eq!(*(*page_fault_count).borrow(), count); } diff --git a/crate/memory/src/swap/mock_swapper.rs b/crate/memory/src/swap/mock_swapper.rs index f1b9704..8b1bbbc 100644 --- a/crate/memory/src/swap/mock_swapper.rs +++ b/crate/memory/src/swap/mock_swapper.rs @@ -49,25 +49,31 @@ mod test { } #[test] - fn test() { + fn swap_out_in() { let mut swapper = MockSwapper::new(); let mut data: [u8; 4096] = unsafe{ uninitialized() }; let data1: [u8; 4096] = unsafe{ uninitialized() }; let token = swapper.swap_out(&data1).unwrap(); - swapper.swap_in(token, &mut data); + swapper.swap_in(token, &mut data).unwrap(); assert_data_eq(&data, &data1); + } + #[test] + fn swap_update() { + let mut swapper = MockSwapper::new(); + let mut data: [u8; 4096] = unsafe{ uninitialized() }; + let data1: [u8; 4096] = unsafe{ uninitialized() }; let data2: [u8; 4096] = unsafe{ uninitialized() }; - swapper.swap_update(token, &data2); - swapper.swap_in(token, &mut data); + let token = swapper.swap_out(&data1).unwrap(); + swapper.swap_update(token, &data2).unwrap(); + swapper.swap_in(token, &mut data).unwrap(); assert_data_eq(&data, &data2); } #[test] - #[should_panic] fn invalid_token() { let mut swapper = MockSwapper::new(); let mut data: [u8; 4096] = unsafe{ uninitialized() }; - swapper.swap_in(0, &mut data); + assert_eq!(swapper.swap_in(0, &mut data), Err(())); } } \ No newline at end of file