mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 08:53:29 +00:00
Disable preemption in page table locks
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
cc49384e96
commit
07a0ea07c0
@ -25,7 +25,9 @@
|
|||||||
//! the initialization of the entity that the PTE points to. This is taken care in this module.
|
//! the initialization of the entity that the PTE points to. This is taken care in this module.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use core::{marker::PhantomData, mem::ManuallyDrop, ops::Range, panic, sync::atomic::Ordering};
|
use core::{
|
||||||
|
fmt, marker::PhantomData, mem::ManuallyDrop, ops::Range, panic, sync::atomic::Ordering,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{nr_subpage_per_huge, page_size, PageTableEntryTrait};
|
use super::{nr_subpage_per_huge, page_size, PageTableEntryTrait};
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -40,6 +42,7 @@ use crate::{
|
|||||||
page_prop::PageProperty,
|
page_prop::PageProperty,
|
||||||
Paddr, PagingConstsTrait, PagingLevel, PAGE_SIZE,
|
Paddr, PagingConstsTrait, PagingLevel, PAGE_SIZE,
|
||||||
},
|
},
|
||||||
|
task::{disable_preempt, DisablePreemptGuard},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The raw handle to a page table node.
|
/// The raw handle to a page table node.
|
||||||
@ -77,6 +80,8 @@ where
|
|||||||
// count is needed.
|
// count is needed.
|
||||||
let page = unsafe { Page::<PageTablePageMeta<E, C>>::from_raw(this.paddr()) };
|
let page = unsafe { Page::<PageTablePageMeta<E, C>>::from_raw(this.paddr()) };
|
||||||
|
|
||||||
|
let disable_preempt = disable_preempt();
|
||||||
|
|
||||||
// Acquire the lock.
|
// Acquire the lock.
|
||||||
while page
|
while page
|
||||||
.meta()
|
.meta()
|
||||||
@ -87,7 +92,10 @@ where
|
|||||||
core::hint::spin_loop();
|
core::hint::spin_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
PageTableNode::<E, C> { page }
|
PageTableNode::<E, C> {
|
||||||
|
page,
|
||||||
|
preempt_guard: disable_preempt,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a copy of the handle.
|
/// Creates a copy of the handle.
|
||||||
@ -175,7 +183,6 @@ where
|
|||||||
/// of the page table. Dropping the page table node will also drop all handles if the page
|
/// of the page table. Dropping the page table node will also drop all handles if the page
|
||||||
/// table node has no references. You can set the page table node as a child of another
|
/// table node has no references. You can set the page table node as a child of another
|
||||||
/// page table node.
|
/// page table node.
|
||||||
#[derive(Debug)]
|
|
||||||
pub(super) struct PageTableNode<
|
pub(super) struct PageTableNode<
|
||||||
E: PageTableEntryTrait = PageTableEntry,
|
E: PageTableEntryTrait = PageTableEntry,
|
||||||
C: PagingConstsTrait = PagingConsts,
|
C: PagingConstsTrait = PagingConsts,
|
||||||
@ -183,6 +190,22 @@ pub(super) struct PageTableNode<
|
|||||||
[(); C::NR_LEVELS as usize]:,
|
[(); C::NR_LEVELS as usize]:,
|
||||||
{
|
{
|
||||||
pub(super) page: Page<PageTablePageMeta<E, C>>,
|
pub(super) page: Page<PageTablePageMeta<E, C>>,
|
||||||
|
preempt_guard: DisablePreemptGuard,
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: We cannot `#[derive(Debug)]` here due to `DisablePreemptGuard`. Should we skip
|
||||||
|
// this field or implement the `Debug` trait also for `DisablePreemptGuard`?
|
||||||
|
impl<E, C> fmt::Debug for PageTableNode<E, C>
|
||||||
|
where
|
||||||
|
E: PageTableEntryTrait,
|
||||||
|
C: PagingConstsTrait,
|
||||||
|
[(); C::NR_LEVELS as usize]:,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("PageTableEntryTrait")
|
||||||
|
.field("page", &self.page)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A child of a page table node.
|
/// A child of a page table node.
|
||||||
@ -224,7 +247,10 @@ where
|
|||||||
unsafe { core::ptr::write_bytes(ptr, 0, PAGE_SIZE) };
|
unsafe { core::ptr::write_bytes(ptr, 0, PAGE_SIZE) };
|
||||||
debug_assert!(E::new_absent().as_bytes().iter().all(|&b| b == 0));
|
debug_assert!(E::new_absent().as_bytes().iter().all(|&b| b == 0));
|
||||||
|
|
||||||
Self { page }
|
Self {
|
||||||
|
page,
|
||||||
|
preempt_guard: disable_preempt(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn level(&self) -> PagingLevel {
|
pub fn level(&self) -> PagingLevel {
|
||||||
@ -233,10 +259,16 @@ where
|
|||||||
|
|
||||||
/// Converts the handle into a raw handle to be stored in a PTE or CPU.
|
/// Converts the handle into a raw handle to be stored in a PTE or CPU.
|
||||||
pub(super) fn into_raw(self) -> RawPageTableNode<E, C> {
|
pub(super) fn into_raw(self) -> RawPageTableNode<E, C> {
|
||||||
let raw = self.page.paddr();
|
let mut this = ManuallyDrop::new(self);
|
||||||
|
|
||||||
self.page.meta().lock.store(0, Ordering::Release);
|
let raw = this.page.paddr();
|
||||||
core::mem::forget(self);
|
|
||||||
|
this.page.meta().lock.store(0, Ordering::Release);
|
||||||
|
// SAFETY: The field will no longer be accessed and we need to drop the field to release
|
||||||
|
// the preempt count.
|
||||||
|
unsafe {
|
||||||
|
core::ptr::drop_in_place(&mut this.preempt_guard);
|
||||||
|
}
|
||||||
|
|
||||||
RawPageTableNode {
|
RawPageTableNode {
|
||||||
raw,
|
raw,
|
||||||
|
Reference in New Issue
Block a user