From a77e653db60ff6d5e6c74c312b2fb781bee989db Mon Sep 17 00:00:00 2001 From: Chen Chengjun Date: Tue, 25 Mar 2025 22:08:26 +0800 Subject: [PATCH] Bind spin semantics to Guardian --- ostd/src/sync/guard.rs | 22 +++++----- ostd/src/sync/rcu/monitor.rs | 3 +- ostd/src/sync/rwlock.rs | 80 ++++++++++++++++++++++++------------ ostd/src/sync/spin.rs | 41 ++++++++++-------- 4 files changed, 93 insertions(+), 53 deletions(-) diff --git a/ostd/src/sync/guard.rs b/ostd/src/sync/guard.rs index ba58276a9..4891eaae9 100644 --- a/ostd/src/sync/guard.rs +++ b/ostd/src/sync/guard.rs @@ -1,16 +1,18 @@ // SPDX-License-Identifier: MPL-2.0 use crate::{ - task::{disable_preempt, DisabledPreemptGuard}, + task::{atomic_mode::AsAtomicModeGuard, disable_preempt, DisabledPreemptGuard}, trap::{disable_local, DisabledLocalIrqGuard}, }; -/// A guardian that denotes the guard behavior for holding a lock. -pub trait Guardian { - /// 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; +/// A guardian that denotes the guard behavior for holding a spin-based lock. +/// +/// It at least ensures that the atomic mode is maintained while the lock is held. +pub trait SpinGuardian { + /// The guard type for holding a spin lock or a spin-based write lock. + type Guard: AsAtomicModeGuard + GuardTransfer; + /// The guard type for holding a spin-based read lock. + type ReadGuard: AsAtomicModeGuard + GuardTransfer; /// Creates a new guard. fn guard() -> Self::Guard; @@ -32,7 +34,7 @@ pub trait GuardTransfer { /// A guardian that disables preemption while holding a lock. pub struct PreemptDisabled; -impl Guardian for PreemptDisabled { +impl SpinGuardian for PreemptDisabled { type Guard = DisabledPreemptGuard; type ReadGuard = DisabledPreemptGuard; @@ -53,7 +55,7 @@ impl Guardian for PreemptDisabled { /// context, then it is ok not to use this guardian in the process context. pub struct LocalIrqDisabled; -impl Guardian for LocalIrqDisabled { +impl SpinGuardian for LocalIrqDisabled { type Guard = DisabledLocalIrqGuard; type ReadGuard = DisabledLocalIrqGuard; @@ -79,7 +81,7 @@ impl Guardian for LocalIrqDisabled { /// [`SpinLock`]: super::SpinLock pub struct WriteIrqDisabled; -impl Guardian for WriteIrqDisabled { +impl SpinGuardian for WriteIrqDisabled { type Guard = DisabledLocalIrqGuard; type ReadGuard = DisabledPreemptGuard; diff --git a/ostd/src/sync/rcu/monitor.rs b/ostd/src/sync/rcu/monitor.rs index aabfed619..f1e8714e1 100644 --- a/ostd/src/sync/rcu/monitor.rs +++ b/ostd/src/sync/rcu/monitor.rs @@ -10,6 +10,7 @@ use crate::{ cpu::{AtomicCpuSet, CpuId, CpuSet, PinCurrentCpu}, prelude::*, sync::SpinLock, + task::atomic_mode::AsAtomicModeGuard, }; /// A RCU monitor ensures the completion of _grace periods_ by keeping track @@ -42,7 +43,7 @@ impl RcuMonitor { // GP. let callbacks = { let mut state = self.state.disable_irq().lock(); - let cpu = state.guard().current_cpu(); + let cpu = state.as_atomic_mode_guard().current_cpu(); if state.current_gp.is_complete() { return; } diff --git a/ostd/src/sync/rwlock.rs b/ostd/src/sync/rwlock.rs index 699a0376a..49c8e3bc3 100644 --- a/ostd/src/sync/rwlock.rs +++ b/ostd/src/sync/rwlock.rs @@ -1,7 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -#![expect(dead_code)] - use alloc::sync::Arc; use core::{ cell::UnsafeCell, @@ -15,9 +13,10 @@ use core::{ }; use super::{ - guard::{GuardTransfer, Guardian}, + guard::{GuardTransfer, SpinGuardian}, PreemptDisabled, }; +use crate::task::atomic_mode::AsAtomicModeGuard; /// Spin-based Read-write Lock /// @@ -125,7 +124,7 @@ impl RwLock { } } -impl RwLock { +impl RwLock { /// Acquires a read lock and spin-wait until it can be acquired. /// /// The calling thread will spin-wait until there are no writers or @@ -360,29 +359,29 @@ impl fmt::Debug for RwLock { unsafe impl Send for RwLock {} unsafe impl Sync for RwLock {} -impl> + Clone, G: Guardian> !Send +impl> + Clone, G: SpinGuardian> !Send for RwLockWriteGuard_ { } -unsafe impl> + Clone + Sync, G: Guardian> Sync +unsafe impl> + Clone + Sync, G: SpinGuardian> Sync for RwLockWriteGuard_ { } -impl> + Clone, G: Guardian> !Send +impl> + Clone, G: SpinGuardian> !Send for RwLockReadGuard_ { } -unsafe impl> + Clone + Sync, G: Guardian> Sync +unsafe impl> + Clone + Sync, G: SpinGuardian> Sync for RwLockReadGuard_ { } -impl> + Clone, G: Guardian> !Send +impl> + Clone, G: SpinGuardian> !Send for RwLockUpgradeableGuard_ { } -unsafe impl> + Clone + Sync, G: Guardian> Sync +unsafe impl> + Clone + Sync, G: SpinGuardian> Sync for RwLockUpgradeableGuard_ { } @@ -390,18 +389,26 @@ unsafe impl> + Clone + Sync, G: /// A guard that provides immutable data access. #[clippy::has_significant_drop] #[must_use] -pub struct RwLockReadGuard_> + Clone, G: Guardian> { +pub struct RwLockReadGuard_> + Clone, G: SpinGuardian> { guard: G::ReadGuard, inner: R, } +impl> + Clone, G: SpinGuardian> AsAtomicModeGuard + for RwLockReadGuard_ +{ + fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode { + self.guard.as_atomic_mode_guard() + } +} + /// A guard that provides shared read access to the data protected by a [`RwLock`]. pub type RwLockReadGuard<'a, T, G> = RwLockReadGuard_, G>; /// A guard that provides shared read access to the data protected by a `Arc`. pub type ArcRwLockReadGuard = RwLockReadGuard_>, G>; -impl> + Clone, G: Guardian> Deref +impl> + Clone, G: SpinGuardian> Deref for RwLockReadGuard_ { type Target = T; @@ -411,7 +418,7 @@ impl> + Clone, G: Guardian> Deref } } -impl> + Clone, G: Guardian> Drop +impl> + Clone, G: SpinGuardian> Drop for RwLockReadGuard_ { fn drop(&mut self) { @@ -419,7 +426,7 @@ impl> + Clone, G: Guardian> Drop } } -impl> + Clone, G: Guardian> fmt::Debug +impl> + Clone, G: SpinGuardian> fmt::Debug for RwLockReadGuard_ { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -428,17 +435,25 @@ impl> + Clone, G: Guardia } /// A guard that provides mutable data access. -pub struct RwLockWriteGuard_> + Clone, G: Guardian> { +pub struct RwLockWriteGuard_> + Clone, G: SpinGuardian> { guard: G::Guard, inner: R, } +impl> + Clone, G: SpinGuardian> AsAtomicModeGuard + for RwLockWriteGuard_ +{ + fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode { + self.guard.as_atomic_mode_guard() + } +} + /// A guard that provides exclusive write access to the data protected by a [`RwLock`]. pub type RwLockWriteGuard<'a, T, G> = RwLockWriteGuard_, G>; /// A guard that provides exclusive write access to the data protected by a `Arc`. pub type ArcRwLockWriteGuard = RwLockWriteGuard_>, G>; -impl> + Clone, G: Guardian> Deref +impl> + Clone, G: SpinGuardian> Deref for RwLockWriteGuard_ { type Target = T; @@ -448,7 +463,9 @@ impl> + Clone, G: Guardian> Deref } } -impl> + Clone, G: Guardian> RwLockWriteGuard_ { +impl> + Clone, G: SpinGuardian> + RwLockWriteGuard_ +{ /// Atomically downgrades a write guard to an upgradeable reader guard. /// /// This method always succeeds because the lock is exclusively held by the writer. @@ -479,7 +496,7 @@ impl> + Clone, G: Guardian> RwLockWrit } } -impl> + Clone, G: Guardian> DerefMut +impl> + Clone, G: SpinGuardian> DerefMut for RwLockWriteGuard_ { fn deref_mut(&mut self) -> &mut Self::Target { @@ -487,7 +504,7 @@ impl> + Clone, G: Guardian> DerefMut } } -impl> + Clone, G: Guardian> Drop +impl> + Clone, G: SpinGuardian> Drop for RwLockWriteGuard_ { fn drop(&mut self) { @@ -495,7 +512,7 @@ impl> + Clone, G: Guardian> Drop } } -impl> + Clone, G: Guardian> fmt::Debug +impl> + Clone, G: SpinGuardian> fmt::Debug for RwLockWriteGuard_ { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -505,18 +522,29 @@ impl> + Clone, G: Guardia /// A guard that provides immutable data access but can be atomically /// upgraded to `RwLockWriteGuard`. -pub struct RwLockUpgradeableGuard_> + Clone, G: Guardian> -{ +pub struct RwLockUpgradeableGuard_< + T: ?Sized, + R: Deref> + Clone, + G: SpinGuardian, +> { guard: G::Guard, inner: R, } +impl> + Clone, G: SpinGuardian> AsAtomicModeGuard + for RwLockUpgradeableGuard_ +{ + fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode { + self.guard.as_atomic_mode_guard() + } +} + /// A upgradable guard that provides read access to the data protected by a [`RwLock`]. pub type RwLockUpgradeableGuard<'a, T, G> = RwLockUpgradeableGuard_, G>; /// A upgradable guard that provides read access to the data protected by a `Arc`. pub type ArcRwLockUpgradeableGuard = RwLockUpgradeableGuard_>, G>; -impl> + Clone, G: Guardian> +impl> + Clone, G: SpinGuardian> RwLockUpgradeableGuard_ { /// Upgrades this upread guard to a write guard atomically. @@ -554,7 +582,7 @@ impl> + Clone, G: Guardian> } } -impl> + Clone, G: Guardian> Deref +impl> + Clone, G: SpinGuardian> Deref for RwLockUpgradeableGuard_ { type Target = T; @@ -564,7 +592,7 @@ impl> + Clone, G: Guardian> Deref } } -impl> + Clone, G: Guardian> Drop +impl> + Clone, G: SpinGuardian> Drop for RwLockUpgradeableGuard_ { fn drop(&mut self) { @@ -572,7 +600,7 @@ impl> + Clone, G: Guardian> Drop } } -impl> + Clone, G: Guardian> fmt::Debug +impl> + Clone, G: SpinGuardian> fmt::Debug for RwLockUpgradeableGuard_ { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/ostd/src/sync/spin.rs b/ostd/src/sync/spin.rs index 40e62a019..7a4adb71b 100644 --- a/ostd/src/sync/spin.rs +++ b/ostd/src/sync/spin.rs @@ -9,7 +9,8 @@ use core::{ sync::atomic::{AtomicBool, Ordering}, }; -use super::{guard::Guardian, LocalIrqDisabled, PreemptDisabled}; +use super::{guard::SpinGuardian, LocalIrqDisabled, PreemptDisabled}; +use crate::task::atomic_mode::AsAtomicModeGuard; /// A spin lock. /// @@ -67,7 +68,7 @@ impl SpinLock { } } -impl SpinLock { +impl SpinLock { /// Acquires the spin lock. pub fn lock(&self) -> SpinLockGuard { // Notice the guard must be created before acquiring the lock. @@ -152,19 +153,22 @@ pub type ArcSpinLockGuard = SpinLockGuard_>, G>; /// The guard of a spin lock. #[clippy::has_significant_drop] #[must_use] -pub struct SpinLockGuard_>, G: Guardian> { +pub struct SpinLockGuard_>, G: SpinGuardian> { guard: G::Guard, lock: R, } -impl>, G: Guardian> SpinLockGuard_ { - /// Returns a reference to the guard. - pub fn guard(&self) -> &G::Guard { - &self.guard +impl>, G: SpinGuardian> AsAtomicModeGuard + for SpinLockGuard_ +{ + fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode { + self.guard.as_atomic_mode_guard() } } -impl>, G: Guardian> Deref for SpinLockGuard_ { +impl>, G: SpinGuardian> Deref + for SpinLockGuard_ +{ type Target = T; fn deref(&self) -> &T { @@ -172,7 +176,7 @@ impl>, G: Guardian> Deref for SpinLo } } -impl>, G: Guardian> DerefMut +impl>, G: SpinGuardian> DerefMut for SpinLockGuard_ { fn deref_mut(&mut self) -> &mut Self::Target { @@ -180,13 +184,15 @@ impl>, G: Guardian> DerefMut } } -impl>, G: Guardian> Drop for SpinLockGuard_ { +impl>, G: SpinGuardian> Drop + for SpinLockGuard_ +{ fn drop(&mut self) { self.lock.release_lock(); } } -impl>, G: Guardian> fmt::Debug +impl>, G: SpinGuardian> fmt::Debug for SpinLockGuard_ { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -194,11 +200,14 @@ impl>, G: Guardian> fmt } } -impl>, G: Guardian> !Send for SpinLockGuard_ {} - -// SAFETY: `SpinLockGuard_` can be shared between tasks/threads in same CPU. -// As `lock()` is only called when there are no race conditions caused by interrupts. -unsafe impl> + Sync, G: Guardian> Sync +impl>, G: SpinGuardian> !Send + for SpinLockGuard_ +{ +} + +// SAFETY: `SpinLockGuard_` can be shared between tasks/threads in same CPU. +// As `lock()` is only called when there are no race conditions caused by interrupts. +unsafe impl> + Sync, G: SpinGuardian> Sync for SpinLockGuard_ { }