mmap write back

master
Harry Cheng 5 years ago
parent 384f6dd1c3
commit d2d6afc4de

@ -8,13 +8,16 @@ pub struct File<F, T> {
pub file_start: usize, pub file_start: usize,
pub file_end: usize, pub file_end: usize,
pub allocator: T, pub allocator: T,
pub write_back: bool,
} }
pub trait Read: Clone + Send + Sync + 'static { pub trait MappedFile: Clone + Send + Sync + 'static {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize; fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize;
fn write_at(&self, offset: usize, buf: &[u8]) -> usize;
fn sync_all(&self);
} }
impl<F: Read, T: FrameAllocator> MemoryHandler for File<F, T> { impl<F: MappedFile, T: FrameAllocator> MemoryHandler for File<F, T> {
fn box_clone(&self) -> Box<dyn MemoryHandler> { fn box_clone(&self) -> Box<dyn MemoryHandler> {
Box::new(self.clone()) Box::new(self.clone())
} }
@ -33,6 +36,9 @@ impl<F: Read, T: FrameAllocator> MemoryHandler for File<F, T> {
// PageTable::unmap requires page to be present // PageTable::unmap requires page to be present
entry.set_present(true); entry.set_present(true);
if self.write_back && entry.dirty() {
self.write_data(pt, addr);
}
pt.unmap(addr); pt.unmap(addr);
} }
@ -73,7 +79,7 @@ impl<F: Read, T: FrameAllocator> MemoryHandler for File<F, T> {
} }
} }
impl<F: Read, T: FrameAllocator> File<F, T> { impl<F: MappedFile, T: FrameAllocator> File<F, T> {
fn fill_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) { fn fill_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) {
let data = pt.get_page_slice_mut(addr); let data = pt.get_page_slice_mut(addr);
let file_offset = addr + self.file_start - self.mem_start; let file_offset = addr + self.file_start - self.mem_start;
@ -85,6 +91,16 @@ impl<F: Read, T: FrameAllocator> File<F, T> {
data[read_size..].iter_mut().for_each(|x| *x = 0); data[read_size..].iter_mut().for_each(|x| *x = 0);
} }
} }
fn write_data(&self, pt: &mut dyn PageTable, addr: VirtAddr) {
let data = pt.get_page_slice_mut(addr);
let file_offset = addr + self.file_start - self.mem_start;
let write_size = (self.file_end as isize - file_offset as isize)
.min(PAGE_SIZE as isize)
.max(0) as usize;
let written_size = self.file.write_at(file_offset, &mut data[..write_size]);
assert!(write_size == written_size);
}
} }
impl<F, T> Debug for File<F, T> { impl<F, T> Debug for File<F, T> {

@ -1,7 +1,8 @@
use super::*; use super::*;
use core::any::Any;
// here may be a interesting part for lab // here may be a interesting part for lab
pub trait MemoryHandler: Debug + Send + Sync + 'static { pub trait MemoryHandler: Any + Debug + Send + Sync + 'static {
fn box_clone(&self) -> Box<dyn MemoryHandler>; fn box_clone(&self) -> Box<dyn MemoryHandler>;
/// Map `addr` in the page table /// Map `addr` in the page table
@ -44,5 +45,5 @@ mod linear;
pub use self::byframe::ByFrame; pub use self::byframe::ByFrame;
pub use self::delay::Delay; pub use self::delay::Delay;
pub use self::file::{File, Read}; pub use self::file::{File, MappedFile};
pub use self::linear::Linear; pub use self::linear::Linear;

@ -15,7 +15,7 @@ use xmas_elf::{
use crate::arch::interrupt::{Context, TrapFrame}; use crate::arch::interrupt::{Context, TrapFrame};
use crate::fs::{FileHandle, FileLike, OpenOptions, FOLLOW_MAX_DEPTH}; use crate::fs::{FileHandle, FileLike, OpenOptions, FOLLOW_MAX_DEPTH};
use crate::memory::{ use crate::memory::{
ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, Read, ByFrame, Delay, File, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet, MappedFile,
}; };
use crate::sync::{Condvar, SpinNoIrqLock as Mutex}; use crate::sync::{Condvar, SpinNoIrqLock as Mutex};
@ -471,6 +471,7 @@ impl ElfExt for ElfFile<'_> {
file_start: ph.offset() as usize, file_start: ph.offset() as usize,
file_end: ph.offset() as usize + ph.file_size() as usize, file_end: ph.offset() as usize + ph.file_size() as usize,
allocator: GlobalFrameAlloc, allocator: GlobalFrameAlloc,
write_back: false,
}, },
"elf", "elf",
); );
@ -519,8 +520,16 @@ impl ElfExt for ElfFile<'_> {
#[derive(Clone)] #[derive(Clone)]
pub struct INodeForMap(pub Arc<dyn INode>); pub struct INodeForMap(pub Arc<dyn INode>);
impl Read for INodeForMap { impl MappedFile for INodeForMap {
fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize { fn read_at(&self, offset: usize, buf: &mut [u8]) -> usize {
self.0.read_at(offset, buf).unwrap() self.0.read_at(offset, buf).unwrap()
} }
fn write_at(&self, offset: usize, buf: &[u8]) -> usize {
self.0.write_at(offset, buf).unwrap()
}
fn sync_all(&self) {
self.0.sync_all().unwrap();
}
} }

@ -82,6 +82,7 @@ impl Syscall<'_> {
file_start: offset, file_start: offset,
file_end: offset + len, file_end: offset + len,
allocator: GlobalFrameAlloc, allocator: GlobalFrameAlloc,
write_back: flags.contains(MmapFlags::SHARED),
}, },
"mmap_file", "mmap_file",
); );
@ -116,7 +117,25 @@ impl Syscall<'_> {
self.vm().pop_with_split(addr, addr + len); self.vm().pop_with_split(addr, addr + len);
Ok(0) Ok(0)
} }
pub fn sys_msync(&mut self, addr: usize, len: usize, flags: usize) -> SysResult {
let flags = MsyncFlags::from_bits_truncate(flags);
if flags.contains(MsyncFlags::SYNC | MsyncFlags::ASYNC) {
return Err(SysError::EINVAL);
}
Ok(0)
}
} }
bitflags! {
pub struct MsyncFlags: usize {
const ASYNC = 1;
const INVALIDATE = 2;
const SYNC = 4;
}
}
bitflags! { bitflags! {
pub struct MmapProt: usize { pub struct MmapProt: usize {
/// Data cannot be accessed /// Data cannot be accessed

@ -170,6 +170,7 @@ impl Syscall<'_> {
SYS_MPROTECT => self.sys_mprotect(args[0], args[1], args[2]), SYS_MPROTECT => self.sys_mprotect(args[0], args[1], args[2]),
SYS_MUNMAP => self.sys_munmap(args[0], args[1]), SYS_MUNMAP => self.sys_munmap(args[0], args[1]),
SYS_MADVISE => self.unimplemented("madvise", Ok(0)), SYS_MADVISE => self.unimplemented("madvise", Ok(0)),
SYS_MSYNC => self.sys_msync(args[0], args[1], args[2]),
// signal // signal
SYS_RT_SIGACTION => self.unimplemented("sigaction", Ok(0)), SYS_RT_SIGACTION => self.unimplemented("sigaction", Ok(0)),

Loading…
Cancel
Save