New page_table mod. Addr -> VirtAddr.

master
WangRunji 7 years ago
parent 8d304da4b4
commit e5e27db4ec

@ -5,3 +5,6 @@ extern crate alloc;
pub mod memory_set; pub mod memory_set;
pub mod swap; pub mod swap;
pub mod page_table;
type VirtAddr = usize;

@ -2,36 +2,47 @@ use alloc::btree_set::BTreeSet;
use super::*; use super::*;
pub struct MockPageTable { pub struct MockPageTable {
mapped_set: BTreeSet<Addr>, mapped_set: BTreeSet<VirtAddr>,
accessed_set: BTreeSet<Addr>, accessed_set: BTreeSet<VirtAddr>,
dirty_set: BTreeSet<Addr>, dirty_set: BTreeSet<VirtAddr>,
page_fault_handler: PageFaultHandler, page_fault_handler: PageFaultHandler,
capacity: usize, capacity: usize,
} }
type PageFaultHandler = fn(&mut MockPageTable, Addr); type PageFaultHandler = fn(&mut MockPageTable, VirtAddr);
impl PageTable for MockPageTable { impl PageTable for MockPageTable {
fn accessed(&self, addr: Addr) -> bool { fn accessed(&self, addr: VirtAddr) -> bool {
self.accessed_set.contains(&addr) self.accessed_set.contains(&addr)
} }
fn dirty(&self, addr: Addr) -> bool { fn dirty(&self, addr: VirtAddr) -> bool {
self.dirty_set.contains(&addr) 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 { impl MockPageTable {
pub fn new(capacity: usize, page_fault_handler: PageFaultHandler) -> Self { pub fn new(capacity: usize, page_fault_handler: PageFaultHandler) -> Self {
MockPageTable { MockPageTable {
mapped_set: BTreeSet::<Addr>::new(), mapped_set: BTreeSet::<VirtAddr>::new(),
accessed_set: BTreeSet::<Addr>::new(), accessed_set: BTreeSet::<VirtAddr>::new(),
dirty_set: BTreeSet::<Addr>::new(), dirty_set: BTreeSet::<VirtAddr>::new(),
page_fault_handler, page_fault_handler,
capacity, 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: VirtAddr) {
while !self.mapped_set.contains(&addr) { while !self.mapped_set.contains(&addr) {
(self.page_fault_handler)(self, 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 /// 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) { while !self.mapped_set.contains(&addr) {
(self.page_fault_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);
} }
/// 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)] #[cfg(test)]
@ -72,7 +71,7 @@ mod test {
#[test] #[test]
fn 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; } unsafe{ PGFAULT_COUNT += 1; }
pt.map(addr); pt.map(addr);
} }

@ -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);
}

@ -3,14 +3,14 @@ use super::*;
struct FifoSwapManager<T: 'static + PageTable> { struct FifoSwapManager<T: 'static + PageTable> {
page_table: &'static T, page_table: &'static T,
deque: VecDeque<Addr>, deque: VecDeque<VirtAddr>,
} }
impl<T: 'static + PageTable> SwapManager<T> for FifoSwapManager<T> { impl<T: 'static + PageTable> SwapManager<T> for FifoSwapManager<T> {
fn new(page_table: &'static T) -> Self { fn new(page_table: &'static T) -> Self {
FifoSwapManager { FifoSwapManager {
page_table, page_table,
deque: VecDeque::<Addr>::new() deque: VecDeque::<VirtAddr>::new()
} }
} }
@ -29,7 +29,7 @@ impl<T: 'static + PageTable> SwapManager<T> for FifoSwapManager<T> {
self.deque.remove(id); self.deque.remove(id);
} }
fn pop(&mut self) -> Option<Addr> { fn pop(&mut self) -> Option<VirtAddr> {
self.deque.pop_front() self.deque.pop_front()
} }
} }
@ -37,7 +37,7 @@ impl<T: 'static + PageTable> SwapManager<T> for FifoSwapManager<T> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use super::mock_page_table::MockPageTable; use page_table::mock_page_table::MockPageTable;
enum MemOp { enum MemOp {
R(usize), W(usize) R(usize), W(usize)
@ -52,7 +52,7 @@ 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 page_fault_handler(pt: &mut MockPageTable, addr: Addr) { fn page_fault_handler(pt: &mut MockPageTable, addr: VirtAddr) {
unsafe{ PGFAULT_COUNT += 1; } unsafe{ PGFAULT_COUNT += 1; }
let fifo = unsafe{ &mut *FIFO }; let fifo = unsafe{ &mut *FIFO };
if !pt.map(addr) { // is full? if !pt.map(addr) { // is full?

@ -1,25 +1,20 @@
use super::*;
use super::page_table::PageTable;
pub mod fifo; pub mod fifo;
mod mock_page_table;
mod mock_swapper; mod mock_swapper;
type Addr = usize;
trait SwapManager<T: PageTable> { trait SwapManager<T: PageTable> {
/// Create and initialize for the swap manager /// Create and initialize for the swap manager
fn new(page_table: &'static T) -> Self; fn new(page_table: &'static T) -> Self;
/// Called when tick interrupt occured /// Called when tick interrupt occured
fn tick(&mut self); fn tick(&mut self);
/// 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: VirtAddr);
/// Called to delete the addr entry from the swap manager /// 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 /// Try to swap out a page, return then victim
fn pop(&mut self) -> Option<Addr>; fn pop(&mut self) -> Option<VirtAddr>;
}
trait PageTable {
fn accessed(&self, addr: Addr) -> bool;
fn dirty(&self, addr: Addr) -> bool;
} }
trait Swapper { trait Swapper {

Loading…
Cancel
Save