@@ -57,6 +57,29 @@ pub unsafe trait Backend {
57
57
unsafe fn unlock ( ptr : * mut Self :: State , guard_state : & Self :: GuardState ) ;
58
58
}
59
59
60
+ /// The "backend" of a lock that supports the irq-save variant.
61
+ ///
62
+ /// # Safety
63
+ ///
64
+ /// The same requirements wrt mutual exclusion in [`Backend`] apply for acquiring the lock via
65
+ /// [`IrqSaveBackend::lock_irqsave`].
66
+ ///
67
+ /// Additionally, when [`IrqSaveBackend::lock_irqsave`] is used to acquire the lock, implementers
68
+ /// must disable interrupts on lock, and restore interrupt state on unlock. Implementers may use
69
+ /// [`Backend::GuardState`] to store state needed to keep track of the interrupt state.
70
+ pub unsafe trait IrqSaveBackend : Backend {
71
+ /// Acquires the lock, making the caller its owner.
72
+ ///
73
+ /// Before acquiring the lock, it disables interrupts, and returns the previous interrupt state
74
+ /// as its guard state so that the guard can restore it when it is dropped.
75
+ ///
76
+ /// # Safety
77
+ ///
78
+ /// Callers must ensure that [`Backend::init`] has been previously called.
79
+ #[ must_use]
80
+ unsafe fn lock_irqsave ( ptr : * mut Self :: State ) -> Self :: GuardState ;
81
+ }
82
+
60
83
/// A mutual exclusion primitive.
61
84
///
62
85
/// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock banckend
@@ -109,6 +132,21 @@ impl<T: ?Sized, B: Backend> Lock<T, B> {
109
132
}
110
133
}
111
134
135
+ impl < T : ?Sized , B : IrqSaveBackend > Lock < T , B > {
136
+ /// Acquires the lock and gives the caller access to the data protected by it.
137
+ ///
138
+ /// Before acquiring the lock, it disables interrupts. When the guard is dropped, the interrupt
139
+ /// state (either enabled or disabled) is restored to its state before
140
+ /// [`lock_irqsave`](Self::lock_irqsave) was called.
141
+ pub fn lock_irqsave ( & self ) -> Guard < ' _ , T , B > {
142
+ // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
143
+ // that `init` was called.
144
+ let state = unsafe { B :: lock_irqsave ( self . state . get ( ) ) } ;
145
+ // SAFETY: The lock was just acquired.
146
+ unsafe { Guard :: new ( self , state) }
147
+ }
148
+ }
149
+
112
150
/// A lock guard.
113
151
///
114
152
/// Allows mutual exclusion primitives that implement the `Backend` trait to automatically unlock
0 commit comments