diff --git a/ostd/src/sync/guard.rs b/ostd/src/sync/guard.rs new file mode 100644 index 000000000..2dfb9a757 --- /dev/null +++ b/ostd/src/sync/guard.rs @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MPL-2.0 + +use crate::{ + task::{disable_preempt, DisabledPreemptGuard}, + trap::{disable_local, DisabledLocalIrqGuard}, +}; + +/// A guardian that denotes the guard behavior for holding the spin lock. +pub trait Guardian { + /// The guard type. + type Guard: GuardTransfer; + + /// Creates a new guard. + fn guard() -> Self::Guard; +} + +/// The Guard can be transferred atomically. +pub trait GuardTransfer { + /// Atomically transfers the current guard to a new instance. + /// + /// This function ensures that there are no 'gaps' between the destruction of the old guard and + /// the creation of the new guard, thereby maintaining the atomicity of guard transitions. + /// + /// The original guard must be dropped immediately after calling this method. + fn transfer_to(&mut self) -> Self; +} + +/// A guardian that disables preemption while holding the spin lock. +pub struct PreemptDisabled; + +impl Guardian for PreemptDisabled { + type Guard = DisabledPreemptGuard; + + fn guard() -> Self::Guard { + disable_preempt() + } +} + +/// A guardian that disables IRQs while holding the spin lock. +/// +/// This guardian would incur a certain time overhead over +/// [`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. +pub struct LocalIrqDisabled; + +impl Guardian for LocalIrqDisabled { + type Guard = DisabledLocalIrqGuard; + + fn guard() -> Self::Guard { + disable_local() + } +} diff --git a/ostd/src/sync/mod.rs b/ostd/src/sync/mod.rs index 02053f2c7..ec75ba0e3 100644 --- a/ostd/src/sync/mod.rs +++ b/ostd/src/sync/mod.rs @@ -2,6 +2,7 @@ //! Useful synchronization primitives. +mod guard; mod mutex; // TODO: refactor this rcu implementation // Comment out this module since it raises lint error @@ -12,7 +13,9 @@ mod spin; 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}, mutex::{ArcMutexGuard, Mutex, MutexGuard}, rwlock::{ ArcRwLockReadGuard, ArcRwLockUpgradeableGuard, ArcRwLockWriteGuard, RwLock, @@ -22,8 +25,6 @@ pub use self::{ ArcRwMutexReadGuard, ArcRwMutexUpgradeableGuard, ArcRwMutexWriteGuard, RwMutex, RwMutexReadGuard, RwMutexUpgradeableGuard, RwMutexWriteGuard, }, - spin::{ - ArcSpinLockGuard, GuardTransfer, LocalIrqDisabled, PreemptDisabled, SpinLock, SpinLockGuard, - }, + spin::{ArcSpinLockGuard, SpinLock, SpinLockGuard}, wait::{WaitQueue, Waiter, Waker}, }; diff --git a/ostd/src/sync/rwlock.rs b/ostd/src/sync/rwlock.rs index dd73ff812..db6b023f9 100644 --- a/ostd/src/sync/rwlock.rs +++ b/ostd/src/sync/rwlock.rs @@ -14,7 +14,10 @@ use core::{ }, }; -use super::{spin::Guardian, GuardTransfer, PreemptDisabled}; +use super::{ + guard::{GuardTransfer, Guardian}, + PreemptDisabled, +}; /// Spin-based Read-write Lock /// diff --git a/ostd/src/sync/spin.rs b/ostd/src/sync/spin.rs index 3f7b0ab0b..0d9ca9d7d 100644 --- a/ostd/src/sync/spin.rs +++ b/ostd/src/sync/spin.rs @@ -11,10 +11,7 @@ use core::{ sync::atomic::{AtomicBool, Ordering}, }; -use crate::{ - task::{disable_preempt, DisabledPreemptGuard}, - trap::{disable_local, DisabledLocalIrqGuard}, -}; +use super::{guard::Guardian, LocalIrqDisabled, PreemptDisabled}; /// A spin lock. /// @@ -44,54 +41,6 @@ struct SpinLockInner { val: UnsafeCell, } -/// A guardian that denotes the guard behavior for holding the spin lock. -pub trait Guardian { - /// The guard type. - type Guard: GuardTransfer; - - /// Creates a new guard. - fn guard() -> Self::Guard; -} - -/// The Guard can be transferred atomically. -pub trait GuardTransfer { - /// Atomically transfers the current guard to a new instance. - /// - /// This function ensures that there are no 'gaps' between the destruction of the old guard and - /// the creation of the new guard, thereby maintaining the atomicity of guard transitions. - /// - /// The original guard must be dropped immediately after calling this method. - fn transfer_to(&mut self) -> Self; -} - -/// A guardian that disables preemption while holding the spin lock. -pub struct PreemptDisabled; - -impl Guardian for PreemptDisabled { - type Guard = DisabledPreemptGuard; - - fn guard() -> Self::Guard { - disable_preempt() - } -} - -/// A guardian that disables IRQs while holding the spin lock. -/// -/// This guardian would incur a certain time overhead over -/// [`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. -pub struct LocalIrqDisabled; - -impl Guardian for LocalIrqDisabled { - type Guard = DisabledLocalIrqGuard; - - fn guard() -> Self::Guard { - disable_local() - } -} - impl SpinLock { /// Creates a new spin lock. pub const fn new(val: T) -> Self {