6
6
//!
7
7
//! See <https://www.kernel.org/doc/Documentation/locking/spinlocks.txt>.
8
8
9
- use super :: { CreatableLock , Guard , Lock } ;
10
- use crate :: { bindings, c_types, str:: CStr , Opaque } ;
9
+ use super :: { mutex :: EmptyGuardContext , CreatableLock , Guard , Lock , LockInfo , WriteLock } ;
10
+ use crate :: { bindings, c_types, str:: CStr , Opaque , True } ;
11
11
use core:: { cell:: UnsafeCell , marker:: PhantomPinned , pin:: Pin } ;
12
12
13
13
/// Safely initialises a [`SpinLock`] with the given name, generating a new lock class.
@@ -108,8 +108,8 @@ impl<T> SpinLock<T> {
108
108
impl < T : ?Sized > SpinLock < T > {
109
109
/// Locks the spinlock and gives the caller access to the data protected by it. Only one thread
110
110
/// at a time is allowed to access the protected data.
111
- pub fn lock ( & self ) -> Guard < ' _ , Self > {
112
- let ctx = self . lock_noguard ( ) ;
111
+ pub fn lock ( & self ) -> Guard < ' _ , Self , WriteLock > {
112
+ let ctx = < Self as Lock < WriteLock > > :: lock_noguard ( self ) ;
113
113
// SAFETY: The spinlock was just acquired.
114
114
unsafe { Guard :: new ( self , ctx) }
115
115
}
@@ -118,15 +118,10 @@ impl<T: ?Sized> SpinLock<T> {
118
118
/// disables interrupts (if they are enabled).
119
119
///
120
120
/// When the lock in unlocked, the interrupt state (enabled/disabled) is restored.
121
- pub fn lock_irqdisable ( & self ) -> Guard < ' _ , Self > {
122
- let ctx = self . internal_lock_irqsave ( ) ;
121
+ pub fn lock_irqdisable ( & self ) -> Guard < ' _ , Self , DisabledInterrupts > {
122
+ let ctx = < Self as Lock < DisabledInterrupts > > :: lock_noguard ( self ) ;
123
123
// SAFETY: The spinlock was just acquired.
124
- unsafe { Guard :: new ( self , Some ( ctx) ) }
125
- }
126
-
127
- fn internal_lock_irqsave ( & self ) -> c_types:: c_ulong {
128
- // SAFETY: `spin_lock` points to valid memory.
129
- unsafe { bindings:: spin_lock_irqsave ( self . spin_lock . get ( ) ) }
124
+ unsafe { Guard :: new ( self , ctx) }
130
125
}
131
126
}
132
127
@@ -147,33 +142,48 @@ impl<T> CreatableLock for SpinLock<T> {
147
142
}
148
143
}
149
144
145
+ /// A type state indicating that interrupts were disabled.
146
+ pub struct DisabledInterrupts ;
147
+ impl LockInfo for DisabledInterrupts {
148
+ type Writable = True ;
149
+ }
150
+
150
151
// SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion.
151
152
unsafe impl < T : ?Sized > Lock for SpinLock < T > {
152
153
type Inner = T ;
153
- type GuardContext = Option < c_types :: c_ulong > ;
154
+ type GuardContext = EmptyGuardContext ;
154
155
155
- fn lock_noguard ( & self ) -> Option < c_types :: c_ulong > {
156
+ fn lock_noguard ( & self ) -> EmptyGuardContext {
156
157
// SAFETY: `spin_lock` points to valid memory.
157
158
unsafe { bindings:: spin_lock ( self . spin_lock . get ( ) ) } ;
158
- None
159
+ EmptyGuardContext
159
160
}
160
161
161
- unsafe fn unlock ( & self , ctx : & mut Option < c_types:: c_ulong > ) {
162
- match ctx {
163
- // SAFETY: The safety requirements of the function ensure that the spinlock is owned by
164
- // the caller.
165
- Some ( v) => unsafe { bindings:: spin_unlock_irqrestore ( self . spin_lock . get ( ) , * v) } ,
166
- // SAFETY: The safety requirements of the function ensure that the spinlock is owned by
167
- // the caller.
168
- None => unsafe { bindings:: spin_unlock ( self . spin_lock . get ( ) ) } ,
169
- }
162
+ unsafe fn unlock ( & self , _: & mut EmptyGuardContext ) {
163
+ // SAFETY: The safety requirements of the function ensure that the spinlock is owned by
164
+ // the caller.
165
+ unsafe { bindings:: spin_unlock ( self . spin_lock . get ( ) ) }
170
166
}
171
167
172
- fn relock ( & self , ctx : & mut Self :: GuardContext ) {
173
- match ctx {
174
- Some ( v) => * v = self . internal_lock_irqsave ( ) ,
175
- None => * ctx = self . lock_noguard ( ) ,
176
- }
168
+ fn locked_data ( & self ) -> & UnsafeCell < T > {
169
+ & self . data
170
+ }
171
+ }
172
+
173
+ // SAFETY: The underlying kernel `spinlock_t` object ensures mutual exclusion.
174
+ unsafe impl < T : ?Sized > Lock < DisabledInterrupts > for SpinLock < T > {
175
+ type Inner = T ;
176
+ type GuardContext = c_types:: c_ulong ;
177
+
178
+ fn lock_noguard ( & self ) -> c_types:: c_ulong {
179
+ // SAFETY: `spin_lock` points to valid memory.
180
+ unsafe { bindings:: spin_lock_irqsave ( self . spin_lock . get ( ) ) }
181
+ }
182
+
183
+ unsafe fn unlock ( & self , ctx : & mut c_types:: c_ulong ) {
184
+ // SAFETY: The safety requirements of the function ensure that the spinlock is owned by
185
+ // the caller.
186
+ unsafe { bindings:: spin_unlock_irqrestore ( self . spin_lock . get ( ) , * ctx) }
177
187
}
178
188
179
189
fn locked_data ( & self ) -> & UnsafeCell < T > {
0 commit comments