Pass test for FifoSwapManager. Change interface.

master
WangRunji 7 years ago
parent be6ff50d7f
commit 470d5692fe

@ -22,14 +22,14 @@ impl<T: 'static + PageTable> SwapManager<T> for FifoSwapManager<T> {
self.deque.push_back(addr); self.deque.push_back(addr);
} }
fn pop(&mut self, addr: usize) { fn remove(&mut self, addr: usize) {
let id = self.deque.iter() let id = self.deque.iter()
.position(|&x| x == addr) .position(|&x| x == addr)
.expect("address not found"); .expect("address not found");
self.deque.remove(id); self.deque.remove(id);
} }
fn swap(&mut self) -> Option<Addr> { fn pop(&mut self) -> Option<Addr> {
self.deque.pop_front() self.deque.pop_front()
} }
} }
@ -52,19 +52,20 @@ mod test {
static mut PAGE: *mut MockPageTable = 0 as *mut _; static mut PAGE: *mut MockPageTable = 0 as *mut _;
static mut FIFO: *mut FifoSwapManager<MockPageTable> = 0 as *mut _; static mut FIFO: *mut FifoSwapManager<MockPageTable> = 0 as *mut _;
fn pgfault_handler(pt: &mut MockPageTable, addr: Addr) { fn page_fault_handler(pt: &mut MockPageTable, addr: Addr) {
unsafe{ PGFAULT_COUNT += 1; } unsafe{ PGFAULT_COUNT += 1; }
let fifo = unsafe{ &mut *FIFO }; let fifo = unsafe{ &mut *FIFO };
if let Some(x) = fifo.swap() { if !pt.map(addr) { // is full?
pt.unmap(x); pt.unmap(fifo.pop().unwrap());
pt.map(addr);
} }
pt.map(addr); fifo.push(addr);
} }
#[test] #[test]
fn test() { fn test() {
use self::MemOp::{R, W}; use self::MemOp::{R, W};
let mut pt = MockPageTable::new(pgfault_handler); let mut pt = MockPageTable::new(4, page_fault_handler);
let mut fifo = FifoSwapManager::<MockPageTable>::new( let mut fifo = FifoSwapManager::<MockPageTable>::new(
unsafe{ &*(&pt as *const _) }); unsafe{ &*(&pt as *const _) });
unsafe { unsafe {

@ -5,10 +5,11 @@ pub struct MockPageTable {
mapped_set: BTreeSet<Addr>, mapped_set: BTreeSet<Addr>,
accessed_set: BTreeSet<Addr>, accessed_set: BTreeSet<Addr>,
dirty_set: BTreeSet<Addr>, dirty_set: BTreeSet<Addr>,
pgfault_handler: PgfaultHandler, page_fault_handler: PageFaultHandler,
capacity: usize,
} }
type PgfaultHandler = fn(&mut MockPageTable, Addr); type PageFaultHandler = fn(&mut MockPageTable, Addr);
impl PageTable for MockPageTable { impl PageTable for MockPageTable {
fn accessed(&self, addr: Addr) -> bool { fn accessed(&self, addr: Addr) -> bool {
@ -20,18 +21,19 @@ impl PageTable for MockPageTable {
} }
impl MockPageTable { impl MockPageTable {
pub fn new(pgfault_handler: PgfaultHandler) -> Self { pub fn new(capacity: usize, page_fault_handler: PageFaultHandler) -> Self {
MockPageTable { MockPageTable {
mapped_set: BTreeSet::<Addr>::new(), mapped_set: BTreeSet::<Addr>::new(),
accessed_set: BTreeSet::<Addr>::new(), accessed_set: BTreeSet::<Addr>::new(),
dirty_set: BTreeSet::<Addr>::new(), dirty_set: BTreeSet::<Addr>::new(),
pgfault_handler, page_fault_handler,
capacity,
} }
} }
/// Read memory, mark accessed, trigger page fault if not present /// Read memory, mark accessed, trigger page fault if not present
pub fn read(&mut self, addr: Addr) { pub fn read(&mut self, addr: Addr) {
while !self.mapped_set.contains(&addr) { while !self.mapped_set.contains(&addr) {
(self.pgfault_handler)(self, addr); (self.page_fault_handler)(self, addr);
} }
self.accessed_set.insert(addr); self.accessed_set.insert(addr);
@ -39,14 +41,20 @@ impl MockPageTable {
/// Write memory, mark accessed and dirty, trigger page fault if not present /// 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: Addr) {
while !self.mapped_set.contains(&addr) { while !self.mapped_set.contains(&addr) {
(self.pgfault_handler)(self, addr); (self.page_fault_handler)(self, addr);
} }
self.accessed_set.insert(addr); self.accessed_set.insert(addr);
self.dirty_set.insert(addr); self.dirty_set.insert(addr);
} }
pub fn map(&mut self, addr: 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); self.mapped_set.insert(addr);
true
} }
/// Unmap a page
pub fn unmap(&mut self, addr: Addr) { pub fn unmap(&mut self, addr: Addr) {
self.mapped_set.remove(&addr); self.mapped_set.remove(&addr);
} }
@ -64,11 +72,11 @@ mod test {
#[test] #[test]
fn test() { fn test() {
fn pgfault_handler(pt: &mut MockPageTable, addr: Addr) { fn page_fault_handler(pt: &mut MockPageTable, addr: Addr) {
unsafe{ PGFAULT_COUNT += 1; } unsafe{ PGFAULT_COUNT += 1; }
pt.map(addr); pt.map(addr);
} }
let mut pt = MockPageTable::new(pgfault_handler); let mut pt = MockPageTable::new(2, page_fault_handler);
pt.map(0); pt.map(0);
pt.read(0); pt.read(0);
@ -81,6 +89,8 @@ mod test {
assert!(pt.accessed(1)); assert!(pt.accessed(1));
assert!(pt.dirty(1)); assert!(pt.dirty(1));
assert_eq!(pt.map(2), false);
pt.unmap(0); pt.unmap(0);
pt.read(0); pt.read(0);
assert_pgfault_eq(2); assert_pgfault_eq(2);

@ -11,9 +11,9 @@ trait SwapManager<T: PageTable> {
/// Called when map a swappable page into the memory /// Called when map a swappable page into the memory
fn push(&mut self, addr: Addr); fn push(&mut self, addr: Addr);
/// Called to delete the addr entry from the swap manager /// Called to delete the addr entry from the swap manager
fn pop(&mut self, addr: Addr); fn remove(&mut self, addr: Addr);
/// Try to swap out a page, return then victim /// Try to swap out a page, return then victim
fn swap(&mut self) -> Option<Addr>; fn pop(&mut self) -> Option<Addr>;
} }
trait PageTable { trait PageTable {

Loading…
Cancel
Save