mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-29 04:13:24 +00:00
Implement WriteIrqDisabled
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
29659dbc98
commit
a260411a2a
@ -5,13 +5,17 @@ use crate::{
|
||||
trap::{disable_local, DisabledLocalIrqGuard},
|
||||
};
|
||||
|
||||
/// A guardian that denotes the guard behavior for holding the spin lock.
|
||||
/// A guardian that denotes the guard behavior for holding a lock.
|
||||
pub trait Guardian {
|
||||
/// The guard type.
|
||||
/// The guard type for holding a spin lock or a write lock.
|
||||
type Guard: GuardTransfer;
|
||||
/// The guard type for holding a read lock.
|
||||
type ReadGuard: GuardTransfer;
|
||||
|
||||
/// Creates a new guard.
|
||||
fn guard() -> Self::Guard;
|
||||
/// Creates a new read guard.
|
||||
fn read_guard() -> Self::ReadGuard;
|
||||
}
|
||||
|
||||
/// The Guard can be transferred atomically.
|
||||
@ -25,21 +29,25 @@ pub trait GuardTransfer {
|
||||
fn transfer_to(&mut self) -> Self;
|
||||
}
|
||||
|
||||
/// A guardian that disables preemption while holding the spin lock.
|
||||
/// A guardian that disables preemption while holding a lock.
|
||||
pub struct PreemptDisabled;
|
||||
|
||||
impl Guardian for PreemptDisabled {
|
||||
type Guard = DisabledPreemptGuard;
|
||||
type ReadGuard = DisabledPreemptGuard;
|
||||
|
||||
fn guard() -> Self::Guard {
|
||||
disable_preempt()
|
||||
}
|
||||
fn read_guard() -> Self::Guard {
|
||||
disable_preempt()
|
||||
}
|
||||
}
|
||||
|
||||
/// A guardian that disables IRQs while holding the spin lock.
|
||||
/// A guardian that disables IRQs while holding a lock.
|
||||
///
|
||||
/// This guardian would incur a certain time overhead over
|
||||
/// [`PreemptDisabled']. So prefer avoiding using this guardian when
|
||||
/// [`PreemptDisabled`]. So prefer avoiding using this guardian when
|
||||
/// IRQ handlers are allowed to get executed while holding the
|
||||
/// lock. For example, if a lock is never used in the interrupt
|
||||
/// context, then it is ok not to use this guardian in the process context.
|
||||
@ -47,8 +55,38 @@ pub struct LocalIrqDisabled;
|
||||
|
||||
impl Guardian for LocalIrqDisabled {
|
||||
type Guard = DisabledLocalIrqGuard;
|
||||
type ReadGuard = DisabledLocalIrqGuard;
|
||||
|
||||
fn guard() -> Self::Guard {
|
||||
disable_local()
|
||||
}
|
||||
fn read_guard() -> Self::Guard {
|
||||
disable_local()
|
||||
}
|
||||
}
|
||||
|
||||
/// A guardian that disables IRQs while holding a write lock.
|
||||
///
|
||||
/// This guardian should only be used for a [`RwLock`]. Using it with a [`SpinLock`] will behave in
|
||||
/// the same way as using [`LocalIrqDisabled`].
|
||||
///
|
||||
/// When using this guardian with a [`RwLock`], holding the read lock will only disable preemption,
|
||||
/// but holding a write lock will disable local IRQs. The user must ensure that the IRQ handlers
|
||||
/// never take the write lock, so we can take the read lock without disabling IRQs, but we are
|
||||
/// still free of deadlock even if the IRQ handlers are triggered in the middle.
|
||||
///
|
||||
/// [`RwLock`]: super::RwLock
|
||||
/// [`SpinLock`]: super::SpinLock
|
||||
pub struct WriteIrqDisabled;
|
||||
|
||||
impl Guardian for WriteIrqDisabled {
|
||||
type Guard = DisabledLocalIrqGuard;
|
||||
type ReadGuard = DisabledPreemptGuard;
|
||||
|
||||
fn guard() -> Self::Guard {
|
||||
disable_local()
|
||||
}
|
||||
fn read_guard() -> Self::ReadGuard {
|
||||
disable_preempt()
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ mod wait;
|
||||
// pub use self::rcu::{pass_quiescent_state, OwnerPtr, Rcu, RcuReadGuard, RcuReclaimer};
|
||||
pub(crate) use self::guard::GuardTransfer;
|
||||
pub use self::{
|
||||
guard::{LocalIrqDisabled, PreemptDisabled},
|
||||
guard::{LocalIrqDisabled, PreemptDisabled, WriteIrqDisabled},
|
||||
mutex::{ArcMutexGuard, Mutex, MutexGuard},
|
||||
rwlock::{
|
||||
ArcRwLockReadGuard, ArcRwLockUpgradeableGuard, ArcRwLockWriteGuard, RwLock,
|
||||
|
@ -230,7 +230,7 @@ impl<T: ?Sized, G: Guardian> RwLock<T, G> {
|
||||
///
|
||||
/// This function will never spin-wait and will return immediately.
|
||||
pub fn try_read(&self) -> Option<RwLockReadGuard<T, G>> {
|
||||
let guard = G::guard();
|
||||
let guard = G::read_guard();
|
||||
let lock = self.lock.fetch_add(READER, Acquire);
|
||||
if lock & (WRITER | MAX_READER | BEING_UPGRADED) == 0 {
|
||||
Some(RwLockReadGuard { inner: self, guard })
|
||||
@ -247,7 +247,7 @@ impl<T: ?Sized, G: Guardian> RwLock<T, G> {
|
||||
///
|
||||
/// [`try_read`]: Self::try_read
|
||||
pub fn try_read_arc(self: &Arc<Self>) -> Option<ArcRwLockReadGuard<T, G>> {
|
||||
let guard = G::guard();
|
||||
let guard = G::read_guard();
|
||||
let lock = self.lock.fetch_add(READER, Acquire);
|
||||
if lock & (WRITER | MAX_READER | BEING_UPGRADED) == 0 {
|
||||
Some(ArcRwLockReadGuard {
|
||||
@ -375,7 +375,7 @@ unsafe impl<T: ?Sized + Sync, R: Deref<Target = RwLock<T, G>> + Clone + Sync, G:
|
||||
#[clippy::has_significant_drop]
|
||||
#[must_use]
|
||||
pub struct RwLockReadGuard_<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> {
|
||||
guard: G::Guard,
|
||||
guard: G::ReadGuard,
|
||||
inner: R,
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user