Use proper locks for PageInfo.
This commit is contained in:
+21
-12
@@ -780,7 +780,8 @@ impl Grant {
|
||||
};
|
||||
|
||||
if let Some(page_info) = get_page_info(frame) {
|
||||
page_info.add_ref(false);
|
||||
let guard = page_info.lock();
|
||||
guard.add_ref(false);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
@@ -909,7 +910,8 @@ impl Grant {
|
||||
};
|
||||
|
||||
let src_page_info = get_page_info(src_frame).expect("allocated page was not present in the global page array");
|
||||
src_page_info.add_ref(is_cow);
|
||||
let guard = src_page_info.lock();
|
||||
guard.add_ref(is_cow);
|
||||
|
||||
let Some(map_result) = (unsafe { dst_mapper.map_phys(dst_page, src_frame.start_address(), flags.write(flags.has_write() && !is_cow)) }) else {
|
||||
break;
|
||||
@@ -990,7 +992,8 @@ impl Grant {
|
||||
};
|
||||
|
||||
if let Some(info) = get_page_info(frame) {
|
||||
if info.remove_ref(is_cow) == 0 {
|
||||
let guard = info.lock();
|
||||
if guard.remove_ref(is_cow) == 0 {
|
||||
deallocate_frames(frame, 1);
|
||||
};
|
||||
} else {
|
||||
@@ -1330,8 +1333,9 @@ fn cow(dst_mapper: &mut PageMapper, page: Page, old_frame: Frame, info: &PageInf
|
||||
fn init_frame(init_rc: usize, init_borrowed_rc: usize) -> Result<Frame, PfError> {
|
||||
let new_frame = crate::memory::allocate_frames(1).ok_or(PfError::Oom)?;
|
||||
let page_info = get_page_info(new_frame).expect("all allocated frames need an associated page info");
|
||||
page_info.refcount.store(init_rc, Ordering::Relaxed);
|
||||
page_info.borrowed_refcount.store(init_borrowed_rc, Ordering::Relaxed);
|
||||
let guard = page_info.lock();
|
||||
guard.refcount.store(init_rc, Ordering::Relaxed);
|
||||
guard.borrowed_refcount.store(init_borrowed_rc, Ordering::Relaxed);
|
||||
|
||||
Ok(new_frame)
|
||||
}
|
||||
@@ -1421,10 +1425,13 @@ fn correct_inner<'l>(addr_space_lock: &'l RwLock<AddrSpace>, mut addr_space_guar
|
||||
Provider::Allocated { .. } | Provider::AllocatedShared if access == AccessMode::Write => {
|
||||
match faulting_pageinfo_opt {
|
||||
Some((_, None)) => unreachable!("allocated page needs frame to be valid"),
|
||||
Some((frame, Some(info))) => if info.owned_refcount() == 1 {
|
||||
frame
|
||||
} else {
|
||||
cow(&mut addr_space.table.utable, faulting_page, frame, info, grant_flags)?
|
||||
Some((frame, Some(info_lock))) => {
|
||||
let guard = info_lock.lock();
|
||||
if guard.owned_refcount() == 1 {
|
||||
frame
|
||||
} else {
|
||||
cow(&mut addr_space.table.utable, faulting_page, frame, &*guard, grant_flags)?
|
||||
}
|
||||
},
|
||||
_ => map_zeroed(&mut addr_space.table.utable, faulting_page, grant_flags, true)?,
|
||||
}
|
||||
@@ -1433,11 +1440,12 @@ fn correct_inner<'l>(addr_space_lock: &'l RwLock<AddrSpace>, mut addr_space_guar
|
||||
Provider::Allocated { .. } | Provider::AllocatedShared => {
|
||||
match faulting_pageinfo_opt {
|
||||
Some((_, None)) => unreachable!("allocated page needs frame to be valid"),
|
||||
Some((frame, Some(page_info))) => {
|
||||
Some((frame, Some(page_info_lock))) => {
|
||||
let guard = page_info_lock.lock();
|
||||
// Keep in mind that alloc_writable must always be true if this code is reached
|
||||
// for AllocatedShared, since shared pages cannot be mapped lazily (without
|
||||
// using AddrSpace backrefs).
|
||||
allow_writable = page_info.owned_refcount() == 1;
|
||||
allow_writable = guard.owned_refcount() == 1;
|
||||
|
||||
frame
|
||||
}
|
||||
@@ -1481,7 +1489,8 @@ fn correct_inner<'l>(addr_space_lock: &'l RwLock<AddrSpace>, mut addr_space_guar
|
||||
frame
|
||||
};
|
||||
|
||||
let info = get_page_info(src_frame).expect("all allocated frames need a PageInfo");
|
||||
let info_lock = get_page_info(src_frame).expect("all allocated frames need a PageInfo");
|
||||
let info = info_lock.lock();
|
||||
info.add_ref(false);
|
||||
|
||||
src_frame
|
||||
|
||||
+4
-6
@@ -20,7 +20,7 @@ use rmm::{
|
||||
FrameAllocator,
|
||||
FrameCount,
|
||||
};
|
||||
use spin::RwLock;
|
||||
use spin::{RwLock, Mutex};
|
||||
use crate::syscall::flag::{PartialAllocStrategy, PhysallocFlags};
|
||||
use crate::syscall::error::{ENOMEM, Error};
|
||||
|
||||
@@ -196,7 +196,6 @@ pub struct PageInfo {
|
||||
pub borrowed_refcount: AtomicUsize,
|
||||
// TODO: AtomicFlags?
|
||||
pub flags: FrameFlags,
|
||||
pub _padding: usize,
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
@@ -213,7 +212,7 @@ pub static SECTIONS: RwLock<Vec<&'static Section>> = RwLock::new(Vec::new());
|
||||
|
||||
pub struct Section {
|
||||
base: Frame,
|
||||
frames: Box<[PageInfo]>,
|
||||
frames: Box<[Mutex<PageInfo>]>,
|
||||
}
|
||||
|
||||
pub const MAX_SECTION_SIZE_BITS: u32 = 27;
|
||||
@@ -235,7 +234,7 @@ pub fn init_mm() {
|
||||
sections.push(Box::leak(Box::new(Section {
|
||||
base,
|
||||
// TODO: zeroed rather than PageInfo::new()?
|
||||
frames: try_box_slice_new(PageInfo::new, section_page_count).expect("failed to allocate pages array"),
|
||||
frames: try_box_slice_new(|| Mutex::new(PageInfo::new()), section_page_count).expect("failed to allocate pages array"),
|
||||
})) as &'static Section);
|
||||
|
||||
pages_left -= section_page_count;
|
||||
@@ -254,7 +253,6 @@ impl PageInfo {
|
||||
refcount: AtomicUsize::new(0),
|
||||
borrowed_refcount: AtomicUsize::new(0),
|
||||
flags: FrameFlags::NONE,
|
||||
_padding: 0,
|
||||
}
|
||||
}
|
||||
pub fn add_ref(&self, cow: bool) {
|
||||
@@ -278,7 +276,7 @@ impl PageInfo {
|
||||
self.refcount.load(Ordering::SeqCst) - self.borrowed_refcount.load(Ordering::SeqCst)
|
||||
}
|
||||
}
|
||||
pub fn get_page_info(frame: Frame) -> Option<&'static PageInfo> {
|
||||
pub fn get_page_info(frame: Frame) -> Option<&'static Mutex<PageInfo>> {
|
||||
let sections = SECTIONS.read();
|
||||
|
||||
let idx = sections
|
||||
|
||||
Reference in New Issue
Block a user