mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 08:53:29 +00:00
Don't copy on write if this is the only reference
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
f13e5d12c1
commit
bec2c97637
@ -241,7 +241,14 @@ impl VmMapping {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if self.is_shared {
|
||||
// If the forked child or parent immediately unmaps the page after
|
||||
// the fork without accessing it, we are the only reference to the
|
||||
// frame. We can directly map the frame as writable without
|
||||
// copying. In this case, the reference count of the frame is 2 (
|
||||
// one for the mapping and one for the frame handle itself).
|
||||
let only_reference = frame.reference_count() == 2;
|
||||
|
||||
if self.is_shared || only_reference {
|
||||
cursor.protect(PAGE_SIZE, |p| p.flags |= PageFlags::W);
|
||||
} else {
|
||||
let new_frame = duplicate_frame(&frame)?;
|
||||
|
@ -80,6 +80,21 @@ impl Frame {
|
||||
core::ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.size());
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the reference count of the frame.
|
||||
///
|
||||
/// It returns the number of all references to the page, including all the
|
||||
/// existing page handles ([`Frame`]) and all the mappings in the page
|
||||
/// table that points to the page.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The function is safe to call, but using it requires extra care. The
|
||||
/// reference count can be changed by other threads at any time including
|
||||
/// potentially between calling this method and acting on the result.
|
||||
pub fn reference_count(&self) -> u32 {
|
||||
self.page.reference_count()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Page<FrameMeta>> for Frame {
|
||||
|
@ -164,6 +164,21 @@ impl<M: PageMeta> Page<M> {
|
||||
unsafe { &*(self.ptr as *const M) }
|
||||
}
|
||||
|
||||
/// Get the reference count of the page.
|
||||
///
|
||||
/// It returns the number of all references to the page, including all the
|
||||
/// existing page handles ([`Page`], [`DynPage`]), and all the mappings in the
|
||||
/// page table that points to the page.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The function is safe to call, but using it requires extra care. The
|
||||
/// reference count can be changed by other threads at any time including
|
||||
/// potentially between calling this method and acting on the result.
|
||||
pub fn reference_count(&self) -> u32 {
|
||||
self.ref_count().load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn ref_count(&self) -> &AtomicU32 {
|
||||
unsafe { &(*self.ptr).ref_count }
|
||||
}
|
||||
|
Reference in New Issue
Block a user