ostd/sync/guard.rs
1// SPDX-License-Identifier: MPL-2.0
2use vstd::prelude::*;
3
4/// A guardian that denotes the guard behavior for holding a spin-based lock.
5///
6/// It at least ensures that the atomic mode is maintained while the lock is held.
7#[verus_verify]
8pub trait SpinGuardian {
9 /// The guard type for holding a spin lock or a spin-based write lock.
10 //type Guard: AsAtomicModeGuard + GuardTransfer;
11 type Guard;
12 /// The guard type for holding a spin-based read lock.
13 //type ReadGuard: AsAtomicModeGuard + GuardTransfer;
14 type ReadGuard;
15
16 /// Creates a new guard.
17 fn guard() -> Self::Guard;
18 /// Creates a new read guard.
19 fn read_guard() -> Self::ReadGuard;
20}
21
22/*
23/// The Guard can be transferred atomically.
24pub trait GuardTransfer {
25 /// Atomically transfers the current guard to a new instance.
26 ///
27 /// This function ensures that there are no 'gaps' between the destruction of the old guard and
28 /// the creation of the new guard, thereby maintaining the atomicity of guard transitions.
29 ///
30 /// The original guard must be dropped immediately after calling this method.
31 fn transfer_to(&mut self) -> Self;
32}
33
34/// A guardian that disables preemption while holding a lock.
35pub enum PreemptDisabled {}
36
37impl SpinGuardian for PreemptDisabled {
38 type Guard = DisabledPreemptGuard;
39 type ReadGuard = DisabledPreemptGuard;
40
41 fn guard() -> Self::Guard {
42 disable_preempt()
43 }
44 fn read_guard() -> Self::Guard {
45 disable_preempt()
46 }
47}
48*/
49/// A guardian that disables IRQs while holding a lock.
50///
51/// This guardian would incur a certain time overhead over
52/// [`PreemptDisabled`]. So prefer avoiding using this guardian when
53/// IRQ handlers are allowed to get executed while holding the
54/// lock. For example, if a lock is never used in the interrupt
55/// context, then it is ok not to use this guardian in the process context.
56pub enum LocalIrqDisabled {}
57/*
58impl SpinGuardian for LocalIrqDisabled {
59 type Guard = DisabledLocalIrqGuard;
60 type ReadGuard = DisabledLocalIrqGuard;
61
62 fn guard() -> Self::Guard {
63 disable_local()
64 }
65 fn read_guard() -> Self::Guard {
66 disable_local()
67 }
68}
69
70/// A guardian that disables IRQs while holding a write lock.
71///
72/// This guardian should only be used for a [`RwLock`]. Using it with a [`SpinLock`] will behave in
73/// the same way as using [`LocalIrqDisabled`].
74///
75/// When using this guardian with a [`RwLock`], holding the read lock will only disable preemption,
76/// but holding a write lock will disable local IRQs. The user must ensure that the IRQ handlers
77/// never take the write lock, so we can take the read lock without disabling IRQs, but we are
78/// still free of deadlock even if the IRQ handlers are triggered in the middle.
79///
80/// [`RwLock`]: super::RwLock
81/// [`SpinLock`]: super::SpinLock
82pub enum WriteIrqDisabled {}
83
84impl SpinGuardian for WriteIrqDisabled {
85 type Guard = DisabledLocalIrqGuard;
86 type ReadGuard = DisabledPreemptGuard;
87
88 fn guard() -> Self::Guard {
89 disable_local()
90 }
91 fn read_guard() -> Self::ReadGuard {
92 disable_preempt()
93 }
94}
95*/