Bind spin semantics to Guardian

This commit is contained in:
Chen Chengjun 2025-03-25 22:08:26 +08:00 committed by Ruihan Li
parent 208d5aa62d
commit a77e653db6
4 changed files with 93 additions and 53 deletions

View File

@ -1,16 +1,18 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use crate::{ use crate::{
task::{disable_preempt, DisabledPreemptGuard}, task::{atomic_mode::AsAtomicModeGuard, disable_preempt, DisabledPreemptGuard},
trap::{disable_local, DisabledLocalIrqGuard}, trap::{disable_local, DisabledLocalIrqGuard},
}; };
/// A guardian that denotes the guard behavior for holding a lock. /// A guardian that denotes the guard behavior for holding a spin-based lock.
pub trait Guardian { ///
/// The guard type for holding a spin lock or a write lock. /// It at least ensures that the atomic mode is maintained while the lock is held.
type Guard: GuardTransfer; pub trait SpinGuardian {
/// The guard type for holding a read lock. /// The guard type for holding a spin lock or a spin-based write lock.
type ReadGuard: GuardTransfer; type Guard: AsAtomicModeGuard + GuardTransfer;
/// The guard type for holding a spin-based read lock.
type ReadGuard: AsAtomicModeGuard + GuardTransfer;
/// Creates a new guard. /// Creates a new guard.
fn guard() -> Self::Guard; fn guard() -> Self::Guard;
@ -32,7 +34,7 @@ pub trait GuardTransfer {
/// A guardian that disables preemption while holding a lock. /// A guardian that disables preemption while holding a lock.
pub struct PreemptDisabled; pub struct PreemptDisabled;
impl Guardian for PreemptDisabled { impl SpinGuardian for PreemptDisabled {
type Guard = DisabledPreemptGuard; type Guard = DisabledPreemptGuard;
type ReadGuard = 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. /// context, then it is ok not to use this guardian in the process context.
pub struct LocalIrqDisabled; pub struct LocalIrqDisabled;
impl Guardian for LocalIrqDisabled { impl SpinGuardian for LocalIrqDisabled {
type Guard = DisabledLocalIrqGuard; type Guard = DisabledLocalIrqGuard;
type ReadGuard = DisabledLocalIrqGuard; type ReadGuard = DisabledLocalIrqGuard;
@ -79,7 +81,7 @@ impl Guardian for LocalIrqDisabled {
/// [`SpinLock`]: super::SpinLock /// [`SpinLock`]: super::SpinLock
pub struct WriteIrqDisabled; pub struct WriteIrqDisabled;
impl Guardian for WriteIrqDisabled { impl SpinGuardian for WriteIrqDisabled {
type Guard = DisabledLocalIrqGuard; type Guard = DisabledLocalIrqGuard;
type ReadGuard = DisabledPreemptGuard; type ReadGuard = DisabledPreemptGuard;

View File

@ -10,6 +10,7 @@ use crate::{
cpu::{AtomicCpuSet, CpuId, CpuSet, PinCurrentCpu}, cpu::{AtomicCpuSet, CpuId, CpuSet, PinCurrentCpu},
prelude::*, prelude::*,
sync::SpinLock, sync::SpinLock,
task::atomic_mode::AsAtomicModeGuard,
}; };
/// A RCU monitor ensures the completion of _grace periods_ by keeping track /// A RCU monitor ensures the completion of _grace periods_ by keeping track
@ -42,7 +43,7 @@ impl RcuMonitor {
// GP. // GP.
let callbacks = { let callbacks = {
let mut state = self.state.disable_irq().lock(); 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() { if state.current_gp.is_complete() {
return; return;
} }

View File

@ -1,7 +1,5 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
#![expect(dead_code)]
use alloc::sync::Arc; use alloc::sync::Arc;
use core::{ use core::{
cell::UnsafeCell, cell::UnsafeCell,
@ -15,9 +13,10 @@ use core::{
}; };
use super::{ use super::{
guard::{GuardTransfer, Guardian}, guard::{GuardTransfer, SpinGuardian},
PreemptDisabled, PreemptDisabled,
}; };
use crate::task::atomic_mode::AsAtomicModeGuard;
/// Spin-based Read-write Lock /// Spin-based Read-write Lock
/// ///
@ -125,7 +124,7 @@ impl<T, G> RwLock<T, G> {
} }
} }
impl<T: ?Sized, G: Guardian> RwLock<T, G> { impl<T: ?Sized, G: SpinGuardian> RwLock<T, G> {
/// Acquires a read lock and spin-wait until it can be acquired. /// Acquires a read lock and spin-wait until it can be acquired.
/// ///
/// The calling thread will spin-wait until there are no writers or /// The calling thread will spin-wait until there are no writers or
@ -360,29 +359,29 @@ impl<T: ?Sized + fmt::Debug, G> fmt::Debug for RwLock<T, G> {
unsafe impl<T: ?Sized + Send, G> Send for RwLock<T, G> {} unsafe impl<T: ?Sized + Send, G> Send for RwLock<T, G> {}
unsafe impl<T: ?Sized + Send + Sync, G> Sync for RwLock<T, G> {} unsafe impl<T: ?Sized + Send + Sync, G> Sync for RwLock<T, G> {}
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> !Send impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> !Send
for RwLockWriteGuard_<T, R, G> for RwLockWriteGuard_<T, R, G>
{ {
} }
unsafe impl<T: ?Sized + Sync, R: Deref<Target = RwLock<T, G>> + Clone + Sync, G: Guardian> Sync unsafe impl<T: ?Sized + Sync, R: Deref<Target = RwLock<T, G>> + Clone + Sync, G: SpinGuardian> Sync
for RwLockWriteGuard_<T, R, G> for RwLockWriteGuard_<T, R, G>
{ {
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> !Send impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> !Send
for RwLockReadGuard_<T, R, G> for RwLockReadGuard_<T, R, G>
{ {
} }
unsafe impl<T: ?Sized + Sync, R: Deref<Target = RwLock<T, G>> + Clone + Sync, G: Guardian> Sync unsafe impl<T: ?Sized + Sync, R: Deref<Target = RwLock<T, G>> + Clone + Sync, G: SpinGuardian> Sync
for RwLockReadGuard_<T, R, G> for RwLockReadGuard_<T, R, G>
{ {
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> !Send impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> !Send
for RwLockUpgradeableGuard_<T, R, G> for RwLockUpgradeableGuard_<T, R, G>
{ {
} }
unsafe impl<T: ?Sized + Sync, R: Deref<Target = RwLock<T, G>> + Clone + Sync, G: Guardian> Sync unsafe impl<T: ?Sized + Sync, R: Deref<Target = RwLock<T, G>> + Clone + Sync, G: SpinGuardian> Sync
for RwLockUpgradeableGuard_<T, R, G> for RwLockUpgradeableGuard_<T, R, G>
{ {
} }
@ -390,18 +389,26 @@ unsafe impl<T: ?Sized + Sync, R: Deref<Target = RwLock<T, G>> + Clone + Sync, G:
/// A guard that provides immutable data access. /// A guard that provides immutable data access.
#[clippy::has_significant_drop] #[clippy::has_significant_drop]
#[must_use] #[must_use]
pub struct RwLockReadGuard_<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> { pub struct RwLockReadGuard_<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> {
guard: G::ReadGuard, guard: G::ReadGuard,
inner: R, inner: R,
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> AsAtomicModeGuard
for RwLockReadGuard_<T, R, G>
{
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`]. /// A guard that provides shared read access to the data protected by a [`RwLock`].
pub type RwLockReadGuard<'a, T, G> = RwLockReadGuard_<T, &'a RwLock<T, G>, G>; pub type RwLockReadGuard<'a, T, G> = RwLockReadGuard_<T, &'a RwLock<T, G>, G>;
/// A guard that provides shared read access to the data protected by a `Arc<RwLock>`. /// A guard that provides shared read access to the data protected by a `Arc<RwLock>`.
pub type ArcRwLockReadGuard<T, G> = RwLockReadGuard_<T, Arc<RwLock<T, G>>, G>; pub type ArcRwLockReadGuard<T, G> = RwLockReadGuard_<T, Arc<RwLock<T, G>>, G>;
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Deref impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> Deref
for RwLockReadGuard_<T, R, G> for RwLockReadGuard_<T, R, G>
{ {
type Target = T; type Target = T;
@ -411,7 +418,7 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Deref
} }
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Drop impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> Drop
for RwLockReadGuard_<T, R, G> for RwLockReadGuard_<T, R, G>
{ {
fn drop(&mut self) { fn drop(&mut self) {
@ -419,7 +426,7 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Drop
} }
} }
impl<T: ?Sized + fmt::Debug, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> fmt::Debug impl<T: ?Sized + fmt::Debug, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> fmt::Debug
for RwLockReadGuard_<T, R, G> for RwLockReadGuard_<T, R, G>
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -428,17 +435,25 @@ impl<T: ?Sized + fmt::Debug, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardia
} }
/// A guard that provides mutable data access. /// A guard that provides mutable data access.
pub struct RwLockWriteGuard_<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> { pub struct RwLockWriteGuard_<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> {
guard: G::Guard, guard: G::Guard,
inner: R, inner: R,
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> AsAtomicModeGuard
for RwLockWriteGuard_<T, R, G>
{
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`]. /// A guard that provides exclusive write access to the data protected by a [`RwLock`].
pub type RwLockWriteGuard<'a, T, G> = RwLockWriteGuard_<T, &'a RwLock<T, G>, G>; pub type RwLockWriteGuard<'a, T, G> = RwLockWriteGuard_<T, &'a RwLock<T, G>, G>;
/// A guard that provides exclusive write access to the data protected by a `Arc<RwLock>`. /// A guard that provides exclusive write access to the data protected by a `Arc<RwLock>`.
pub type ArcRwLockWriteGuard<T, G> = RwLockWriteGuard_<T, Arc<RwLock<T, G>>, G>; pub type ArcRwLockWriteGuard<T, G> = RwLockWriteGuard_<T, Arc<RwLock<T, G>>, G>;
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Deref impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> Deref
for RwLockWriteGuard_<T, R, G> for RwLockWriteGuard_<T, R, G>
{ {
type Target = T; type Target = T;
@ -448,7 +463,9 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Deref
} }
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> RwLockWriteGuard_<T, R, G> { impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian>
RwLockWriteGuard_<T, R, G>
{
/// Atomically downgrades a write guard to an upgradeable reader guard. /// Atomically downgrades a write guard to an upgradeable reader guard.
/// ///
/// This method always succeeds because the lock is exclusively held by the writer. /// This method always succeeds because the lock is exclusively held by the writer.
@ -479,7 +496,7 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> RwLockWrit
} }
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> DerefMut impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> DerefMut
for RwLockWriteGuard_<T, R, G> for RwLockWriteGuard_<T, R, G>
{ {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
@ -487,7 +504,7 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> DerefMut
} }
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Drop impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> Drop
for RwLockWriteGuard_<T, R, G> for RwLockWriteGuard_<T, R, G>
{ {
fn drop(&mut self) { fn drop(&mut self) {
@ -495,7 +512,7 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Drop
} }
} }
impl<T: ?Sized + fmt::Debug, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> fmt::Debug impl<T: ?Sized + fmt::Debug, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> fmt::Debug
for RwLockWriteGuard_<T, R, G> for RwLockWriteGuard_<T, R, G>
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -505,18 +522,29 @@ impl<T: ?Sized + fmt::Debug, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardia
/// A guard that provides immutable data access but can be atomically /// A guard that provides immutable data access but can be atomically
/// upgraded to `RwLockWriteGuard`. /// upgraded to `RwLockWriteGuard`.
pub struct RwLockUpgradeableGuard_<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> pub struct RwLockUpgradeableGuard_<
{ T: ?Sized,
R: Deref<Target = RwLock<T, G>> + Clone,
G: SpinGuardian,
> {
guard: G::Guard, guard: G::Guard,
inner: R, inner: R,
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> AsAtomicModeGuard
for RwLockUpgradeableGuard_<T, R, G>
{
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`]. /// A upgradable guard that provides read access to the data protected by a [`RwLock`].
pub type RwLockUpgradeableGuard<'a, T, G> = RwLockUpgradeableGuard_<T, &'a RwLock<T, G>, G>; pub type RwLockUpgradeableGuard<'a, T, G> = RwLockUpgradeableGuard_<T, &'a RwLock<T, G>, G>;
/// A upgradable guard that provides read access to the data protected by a `Arc<RwLock>`. /// A upgradable guard that provides read access to the data protected by a `Arc<RwLock>`.
pub type ArcRwLockUpgradeableGuard<T, G> = RwLockUpgradeableGuard_<T, Arc<RwLock<T, G>>, G>; pub type ArcRwLockUpgradeableGuard<T, G> = RwLockUpgradeableGuard_<T, Arc<RwLock<T, G>>, G>;
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian>
RwLockUpgradeableGuard_<T, R, G> RwLockUpgradeableGuard_<T, R, G>
{ {
/// Upgrades this upread guard to a write guard atomically. /// Upgrades this upread guard to a write guard atomically.
@ -554,7 +582,7 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian>
} }
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Deref impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> Deref
for RwLockUpgradeableGuard_<T, R, G> for RwLockUpgradeableGuard_<T, R, G>
{ {
type Target = T; type Target = T;
@ -564,7 +592,7 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Deref
} }
} }
impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Drop impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> Drop
for RwLockUpgradeableGuard_<T, R, G> for RwLockUpgradeableGuard_<T, R, G>
{ {
fn drop(&mut self) { fn drop(&mut self) {
@ -572,7 +600,7 @@ impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> Drop
} }
} }
impl<T: ?Sized + fmt::Debug, R: Deref<Target = RwLock<T, G>> + Clone, G: Guardian> fmt::Debug impl<T: ?Sized + fmt::Debug, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> fmt::Debug
for RwLockUpgradeableGuard_<T, R, G> for RwLockUpgradeableGuard_<T, R, G>
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

View File

@ -9,7 +9,8 @@ use core::{
sync::atomic::{AtomicBool, Ordering}, 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. /// A spin lock.
/// ///
@ -67,7 +68,7 @@ impl<T: ?Sized> SpinLock<T, PreemptDisabled> {
} }
} }
impl<T: ?Sized, G: Guardian> SpinLock<T, G> { impl<T: ?Sized, G: SpinGuardian> SpinLock<T, G> {
/// Acquires the spin lock. /// Acquires the spin lock.
pub fn lock(&self) -> SpinLockGuard<T, G> { pub fn lock(&self) -> SpinLockGuard<T, G> {
// Notice the guard must be created before acquiring the lock. // Notice the guard must be created before acquiring the lock.
@ -152,19 +153,22 @@ pub type ArcSpinLockGuard<T, G> = SpinLockGuard_<T, Arc<SpinLock<T, G>>, G>;
/// The guard of a spin lock. /// The guard of a spin lock.
#[clippy::has_significant_drop] #[clippy::has_significant_drop]
#[must_use] #[must_use]
pub struct SpinLockGuard_<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: Guardian> { pub struct SpinLockGuard_<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: SpinGuardian> {
guard: G::Guard, guard: G::Guard,
lock: R, lock: R,
} }
impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: Guardian> SpinLockGuard_<T, R, G> { impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: SpinGuardian> AsAtomicModeGuard
/// Returns a reference to the guard. for SpinLockGuard_<T, R, G>
pub fn guard(&self) -> &G::Guard { {
&self.guard fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode {
self.guard.as_atomic_mode_guard()
} }
} }
impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: Guardian> Deref for SpinLockGuard_<T, R, G> { impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: SpinGuardian> Deref
for SpinLockGuard_<T, R, G>
{
type Target = T; type Target = T;
fn deref(&self) -> &T { fn deref(&self) -> &T {
@ -172,7 +176,7 @@ impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: Guardian> Deref for SpinLo
} }
} }
impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: Guardian> DerefMut impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: SpinGuardian> DerefMut
for SpinLockGuard_<T, R, G> for SpinLockGuard_<T, R, G>
{ {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
@ -180,13 +184,15 @@ impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: Guardian> DerefMut
} }
} }
impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: Guardian> Drop for SpinLockGuard_<T, R, G> { impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: SpinGuardian> Drop
for SpinLockGuard_<T, R, G>
{
fn drop(&mut self) { fn drop(&mut self) {
self.lock.release_lock(); self.lock.release_lock();
} }
} }
impl<T: ?Sized + fmt::Debug, R: Deref<Target = SpinLock<T, G>>, G: Guardian> fmt::Debug impl<T: ?Sized + fmt::Debug, R: Deref<Target = SpinLock<T, G>>, G: SpinGuardian> fmt::Debug
for SpinLockGuard_<T, R, G> for SpinLockGuard_<T, R, G>
{ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -194,11 +200,14 @@ impl<T: ?Sized + fmt::Debug, R: Deref<Target = SpinLock<T, G>>, G: Guardian> fmt
} }
} }
impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: Guardian> !Send for SpinLockGuard_<T, R, G> {} impl<T: ?Sized, R: Deref<Target = SpinLock<T, G>>, G: SpinGuardian> !Send
for SpinLockGuard_<T, R, G>
// 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<T: ?Sized + Sync, R: Deref<Target = SpinLock<T, G>> + Sync, G: Guardian> Sync
// 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<T: ?Sized + Sync, R: Deref<Target = SpinLock<T, G>> + Sync, G: SpinGuardian> Sync
for SpinLockGuard_<T, R, G> for SpinLockGuard_<T, R, G>
{ {
} }