mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 17:03:23 +00:00
Reverse the page table unlock order
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
02912e19cb
commit
fef8eebadc
@ -109,11 +109,22 @@ pub(crate) struct Cursor<'a, M: PageTableMode, E: PageTableEntryTrait, C: Paging
|
|||||||
where
|
where
|
||||||
[(); C::NR_LEVELS as usize]:,
|
[(); C::NR_LEVELS as usize]:,
|
||||||
{
|
{
|
||||||
|
/// The lock guards of the cursor. The level 1 page table lock guard is at
|
||||||
|
/// index 0, and the level N page table lock guard is at index N - 1.
|
||||||
|
///
|
||||||
|
/// When destructing the cursor, the locks will be released in the order
|
||||||
|
/// from low to high, exactly the reverse order of the aquisition.
|
||||||
|
/// This behavior is ensured by the default drop implementation of Rust:
|
||||||
|
/// <https://doc.rust-lang.org/reference/destructors.html>.
|
||||||
guards: [Option<PageTableNode<E, C>>; C::NR_LEVELS as usize],
|
guards: [Option<PageTableNode<E, C>>; C::NR_LEVELS as usize],
|
||||||
level: PagingLevel, // current level
|
/// The level of the page table that the cursor points to.
|
||||||
guard_level: PagingLevel, // from guard_level to level, the locks are held
|
level: PagingLevel,
|
||||||
va: Vaddr, // current virtual address
|
/// From `guard_level` to `level`, the locks are held in `guards`.
|
||||||
barrier_va: Range<Vaddr>, // virtual address range that is locked
|
guard_level: PagingLevel,
|
||||||
|
/// The current virtual address that the cursor points to.
|
||||||
|
va: Vaddr,
|
||||||
|
/// The virtual address range that is locked.
|
||||||
|
barrier_va: Range<Vaddr>,
|
||||||
phantom: PhantomData<&'a PageTable<M, E, C>>,
|
phantom: PhantomData<&'a PageTable<M, E, C>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +153,7 @@ where
|
|||||||
|
|
||||||
// Create a guard array that only hold the root node lock.
|
// Create a guard array that only hold the root node lock.
|
||||||
let guards = core::array::from_fn(|i| {
|
let guards = core::array::from_fn(|i| {
|
||||||
if i == 0 {
|
if i == (C::NR_LEVELS - 1) as usize {
|
||||||
Some(pt.root.clone_shallow().lock())
|
Some(pt.root.clone_shallow().lock())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -178,8 +189,8 @@ where
|
|||||||
|
|
||||||
cursor.level_down();
|
cursor.level_down();
|
||||||
|
|
||||||
// Release the guard of the previous level.
|
// Release the guard of the previous (upper) level.
|
||||||
cursor.guards[(C::NR_LEVELS - cursor.level) as usize - 1] = None;
|
cursor.guards[cursor.level as usize] = None;
|
||||||
cursor.guard_level -= 1;
|
cursor.guard_level -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +261,7 @@ where
|
|||||||
///
|
///
|
||||||
/// This method requires locks acquired before calling it. The discarded level will be unlocked.
|
/// This method requires locks acquired before calling it. The discarded level will be unlocked.
|
||||||
fn level_up(&mut self) {
|
fn level_up(&mut self) {
|
||||||
self.guards[(C::NR_LEVELS - self.level) as usize] = None;
|
self.guards[(self.level - 1) as usize] = None;
|
||||||
self.level += 1;
|
self.level += 1;
|
||||||
|
|
||||||
// TODO: Drop page tables if page tables become empty.
|
// TODO: Drop page tables if page tables become empty.
|
||||||
@ -262,16 +273,14 @@ where
|
|||||||
|
|
||||||
if let Child::PageTable(nxt_lvl_ptn) = self.cur_child() {
|
if let Child::PageTable(nxt_lvl_ptn) = self.cur_child() {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
self.guards[(C::NR_LEVELS - self.level) as usize] = Some(nxt_lvl_ptn.lock());
|
self.guards[(self.level - 1) as usize] = Some(nxt_lvl_ptn.lock());
|
||||||
} else {
|
} else {
|
||||||
panic!("Trying to level down when it is not mapped to a page table");
|
panic!("Trying to level down when it is not mapped to a page table");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cur_node(&self) -> &PageTableNode<E, C> {
|
fn cur_node(&self) -> &PageTableNode<E, C> {
|
||||||
self.guards[(C::NR_LEVELS - self.level) as usize]
|
self.guards[(self.level - 1) as usize].as_ref().unwrap()
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cur_idx(&self) -> usize {
|
fn cur_idx(&self) -> usize {
|
||||||
@ -625,7 +634,7 @@ where
|
|||||||
self.0.level_up();
|
self.0.level_up();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.0.guards[0].take()
|
self.0.guards[(C::NR_LEVELS - 1) as usize].take()
|
||||||
|
|
||||||
// Ok to drop the cursor here because we ensure not to access the page table if the current
|
// Ok to drop the cursor here because we ensure not to access the page table if the current
|
||||||
// level is the root level when running the dropping method.
|
// level is the root level when running the dropping method.
|
||||||
@ -642,7 +651,7 @@ where
|
|||||||
self.cur_node_mut()
|
self.cur_node_mut()
|
||||||
.set_child_pt(idx, new_node.clone_raw(), is_tracked);
|
.set_child_pt(idx, new_node.clone_raw(), is_tracked);
|
||||||
self.0.level -= 1;
|
self.0.level -= 1;
|
||||||
self.0.guards[(C::NR_LEVELS - self.0.level) as usize] = Some(new_node);
|
self.0.guards[(self.0.level - 1) as usize] = Some(new_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Goes down a level assuming the current slot is an untracked huge page.
|
/// Goes down a level assuming the current slot is an untracked huge page.
|
||||||
@ -659,12 +668,10 @@ where
|
|||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
self.0.level -= 1;
|
self.0.level -= 1;
|
||||||
self.0.guards[(C::NR_LEVELS - self.0.level) as usize] = Some(new_node.lock());
|
self.0.guards[(self.0.level - 1) as usize] = Some(new_node.lock());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cur_node_mut(&mut self) -> &mut PageTableNode<E, C> {
|
fn cur_node_mut(&mut self) -> &mut PageTableNode<E, C> {
|
||||||
self.0.guards[(C::NR_LEVELS - self.0.level) as usize]
|
self.0.guards[(self.0.level - 1) as usize].as_mut().unwrap()
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user