1use crate::raw_kernel_mutex::LockEntryStorage;
6use crate::raw_lock::RawLock;
7use core::ffi::c_void;
8use pin_init::{PinInit, pin_data};
9
10#[cfg(target_arch = "x86_64")]
11type InnerSavedState = u64;
12#[cfg(not(target_arch = "x86_64"))]
13type InnerSavedState = bool;
14
15#[repr(transparent)]
17#[derive(Copy, Clone, Default)]
18pub struct InterruptSavedState(InnerSavedState);
19
20unsafe extern "C" {
21 fn cpp_spinlock_init(lock: *mut c_void, class_id: *const c_void);
22 fn cpp_spinlock_destroy(lock: *mut c_void);
23 fn cpp_spinlock_acquire_irqsave(
24 lock: *mut c_void,
25 entry_storage: *mut c_void,
26 ) -> InterruptSavedState;
27 fn cpp_spinlock_release_irqrestore(
28 lock: *mut c_void,
29 entry_storage: *mut c_void,
30 state: InterruptSavedState,
31 );
32 fn cpp_spinlock_acquire_no_irqsave(lock: *mut c_void, entry_storage: *mut c_void);
33 fn cpp_spinlock_release_no_irqrestore(lock: *mut c_void, entry_storage: *mut c_void);
34
35 fn cpp_monitored_spinlock_init(lock: *mut c_void, class_id: *const c_void);
36 fn cpp_monitored_spinlock_destroy(lock: *mut c_void);
37 fn cpp_monitored_spinlock_acquire_irqsave(
38 lock: *mut c_void,
39 entry_storage: *mut c_void,
40 name: *const core::ffi::c_char,
41 ) -> InterruptSavedState;
42 fn cpp_monitored_spinlock_release_irqrestore(
43 lock: *mut c_void,
44 entry_storage: *mut c_void,
45 state: InterruptSavedState,
46 );
47 fn cpp_monitored_spinlock_acquire_no_irqsave(
48 lock: *mut c_void,
49 entry_storage: *mut c_void,
50 name: *const core::ffi::c_char,
51 );
52 fn cpp_monitored_spinlock_release_no_irqrestore(lock: *mut c_void, entry_storage: *mut c_void);
53}
54
55#[cfg(feature = "spin_lock_tracing")]
56const RAW_SPINLOCK_SIZE: usize = 16;
57#[cfg(not(feature = "spin_lock_tracing"))]
58const RAW_SPINLOCK_SIZE: usize = 4;
59
60#[repr(C, align(8))]
61struct RawSpinlockStorage(zr::OpaqueBytes<RAW_SPINLOCK_SIZE>);
62
63#[pin_data(PinnedDrop)]
65#[repr(C)]
66pub struct RawSpinlock {
67 #[cfg(feature = "lock_dep")]
68 class_id: *const c_void,
69 storage: RawSpinlockStorage,
70}
71
72impl RawSpinlock {
73 pub const INIT: Self = Self::const_init(core::ptr::null());
74
75 pub const fn const_init(_class_id: *const c_void) -> Self {
77 Self {
78 #[cfg(feature = "lock_dep")]
79 class_id: _class_id,
80 storage: RawSpinlockStorage(zr::OpaqueBytes::new([0u8; RAW_SPINLOCK_SIZE])),
81 }
82 }
83}
84
85impl Default for RawSpinlock {
86 fn default() -> Self {
87 Self::INIT
88 }
89}
90
91unsafe impl Sync for RawSpinlock {}
93unsafe impl Send for RawSpinlock {}
94
95zr::unsafe_pinned_drop_ffi!(RawSpinlock, cpp_spinlock_destroy);
96
97#[pin_data(PinnedDrop)]
99#[repr(C)]
100pub struct RawMonitoredSpinlock {
101 #[cfg(feature = "lock_dep")]
102 class_id: *const c_void,
103 storage: RawSpinlockStorage,
104}
105
106impl RawMonitoredSpinlock {
107 pub const INIT: Self = Self::const_init(core::ptr::null());
108
109 pub const fn const_init(_class_id: *const c_void) -> Self {
111 Self {
112 #[cfg(feature = "lock_dep")]
113 class_id: _class_id,
114 storage: RawSpinlockStorage(zr::OpaqueBytes::new([0u8; RAW_SPINLOCK_SIZE])),
115 }
116 }
117}
118
119impl Default for RawMonitoredSpinlock {
120 fn default() -> Self {
121 Self::INIT
122 }
123}
124
125unsafe impl Sync for RawMonitoredSpinlock {}
127unsafe impl Send for RawMonitoredSpinlock {}
128
129zr::unsafe_pinned_drop_ffi!(RawMonitoredSpinlock, cpp_monitored_spinlock_destroy);
130
131pub struct IrqSavePolicy;
132
133impl crate::LockPolicy<RawSpinlock> for IrqSavePolicy {
134 type AcquireArgs = ();
135 type GuardState = InterruptSavedState;
136
137 #[inline]
138 unsafe fn acquire(
139 lock: &RawSpinlock,
140 entry: *mut LockEntryStorage,
141 _args: (),
142 ) -> Self::GuardState {
143 unsafe { cpp_spinlock_acquire_irqsave(lock.as_mut_ptr(), entry as *mut c_void) }
146 }
147
148 #[inline]
149 unsafe fn reacquire(
150 lock: &RawSpinlock,
151 entry: *mut LockEntryStorage,
152 state: &mut Self::GuardState,
153 ) {
154 *state = unsafe { Self::acquire(lock, entry, ()) };
155 }
156
157 #[inline]
158 unsafe fn release(lock: &RawSpinlock, entry: *mut LockEntryStorage, state: Self::GuardState) {
159 unsafe {
162 cpp_spinlock_release_irqrestore(lock.as_mut_ptr(), entry as *mut c_void, state);
163 }
164 }
165}
166
167pub struct NoIrqSavePolicy;
168
169impl crate::LockPolicy<RawSpinlock> for NoIrqSavePolicy {
170 type AcquireArgs = ();
171 type GuardState = ();
172
173 #[inline]
174 unsafe fn acquire(
175 lock: &RawSpinlock,
176 entry: *mut LockEntryStorage,
177 _args: (),
178 ) -> Self::GuardState {
179 unsafe { cpp_spinlock_acquire_no_irqsave(lock.as_mut_ptr(), entry as *mut c_void) }
182 }
183
184 #[inline]
185 unsafe fn reacquire(
186 lock: &RawSpinlock,
187 entry: *mut LockEntryStorage,
188 state: &mut Self::GuardState,
189 ) {
190 *state = unsafe { Self::acquire(lock, entry, ()) };
191 }
192
193 #[inline]
194 unsafe fn release(lock: &RawSpinlock, entry: *mut LockEntryStorage, _state: Self::GuardState) {
195 unsafe {
198 cpp_spinlock_release_no_irqrestore(lock.as_mut_ptr(), entry as *mut c_void);
199 }
200 }
201}
202
203#[derive(Copy, Clone, Default)]
205pub struct MonitoredSpinlockGuardState {
206 pub interrupt_state: InterruptSavedState,
207 pub tag: crate::SourceTag,
208}
209
210impl crate::LockPolicy<RawMonitoredSpinlock> for IrqSavePolicy {
211 type AcquireArgs = crate::SourceTag;
212 type GuardState = MonitoredSpinlockGuardState;
213
214 #[inline]
215 unsafe fn acquire(
216 lock: &RawMonitoredSpinlock,
217 entry: *mut LockEntryStorage,
218 tag: Self::AcquireArgs,
219 ) -> Self::GuardState {
220 let interrupt_state = unsafe {
223 cpp_monitored_spinlock_acquire_irqsave(
224 lock.as_mut_ptr(),
225 entry as *mut c_void,
226 tag.as_ptr(),
227 )
228 };
229 MonitoredSpinlockGuardState { interrupt_state, tag }
230 }
231
232 #[inline]
233 unsafe fn reacquire(
234 lock: &RawMonitoredSpinlock,
235 entry: *mut LockEntryStorage,
236 state: &mut Self::GuardState,
237 ) {
238 state.interrupt_state = unsafe {
240 cpp_monitored_spinlock_acquire_irqsave(
241 lock.as_mut_ptr(),
242 entry as *mut c_void,
243 state.tag.as_ptr(),
244 )
245 };
246 }
247
248 #[inline]
249 unsafe fn release(
250 lock: &RawMonitoredSpinlock,
251 entry: *mut LockEntryStorage,
252 state: Self::GuardState,
253 ) {
254 unsafe {
257 cpp_monitored_spinlock_release_irqrestore(
258 lock.as_mut_ptr(),
259 entry as *mut c_void,
260 state.interrupt_state,
261 );
262 }
263 }
264}
265
266impl crate::LockPolicy<RawMonitoredSpinlock> for NoIrqSavePolicy {
267 type AcquireArgs = crate::SourceTag;
268 type GuardState = crate::SourceTag;
269
270 #[inline]
271 unsafe fn acquire(
272 lock: &RawMonitoredSpinlock,
273 entry: *mut LockEntryStorage,
274 tag: Self::AcquireArgs,
275 ) -> Self::GuardState {
276 unsafe {
279 cpp_monitored_spinlock_acquire_no_irqsave(
280 lock.as_mut_ptr(),
281 entry as *mut c_void,
282 tag.as_ptr(),
283 );
284 }
285 tag
286 }
287
288 #[inline]
289 unsafe fn reacquire(
290 lock: &RawMonitoredSpinlock,
291 entry: *mut LockEntryStorage,
292 state: &mut Self::GuardState,
293 ) {
294 unsafe {
296 cpp_monitored_spinlock_acquire_no_irqsave(
297 lock.as_mut_ptr(),
298 entry as *mut c_void,
299 state.as_ptr(),
300 );
301 }
302 }
303
304 #[inline]
305 unsafe fn release(
306 lock: &RawMonitoredSpinlock,
307 entry: *mut LockEntryStorage,
308 _state: Self::GuardState,
309 ) {
310 unsafe {
313 cpp_monitored_spinlock_release_no_irqrestore(lock.as_mut_ptr(), entry as *mut c_void);
314 }
315 }
316}
317
318impl crate::RawLock for RawSpinlock {
319 const LOCK_FLAGS: lockdep::LockFlags = lockdep::LOCK_FLAGS_IRQ_SAFE;
320
321 type LockEntry = LockEntryStorage;
322 type DefaultPolicy = IrqSavePolicy;
323
324 #[inline]
325 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
326 zr::pin_init_ffi!(cpp_spinlock_init, class_id)
327 }
328
329 #[inline]
330 fn as_mut_ptr(&self) -> *mut c_void {
331 self as *const Self as *mut Self as *mut c_void
332 }
333}
334
335impl crate::RawLock for RawMonitoredSpinlock {
336 const LOCK_FLAGS: lockdep::LockFlags = lockdep::LOCK_FLAGS_IRQ_SAFE;
337
338 type LockEntry = LockEntryStorage;
339 type DefaultPolicy = IrqSavePolicy;
340
341 #[inline]
342 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
343 zr::pin_init_ffi!(cpp_monitored_spinlock_init, class_id)
344 }
345
346 #[inline]
347 fn as_mut_ptr(&self) -> *mut c_void {
348 self as *const Self as *mut Self as *mut c_void
349 }
350}
351
352const _: () = {
353 #[cfg(feature = "lock_dep")]
354 const BASE_SIZE: usize = 8;
355 #[cfg(not(feature = "lock_dep"))]
356 const BASE_SIZE: usize = 0;
357
358 const EXPECTED_SPINLOCK_SIZE: usize = BASE_SIZE + if RAW_SPINLOCK_SIZE == 4 { 8 } else { 16 };
359
360 assert!(core::mem::size_of::<RawSpinlock>() == EXPECTED_SPINLOCK_SIZE);
361 assert!(core::mem::align_of::<RawSpinlock>() == 8);
362 assert!(core::mem::size_of::<RawMonitoredSpinlock>() == EXPECTED_SPINLOCK_SIZE);
363 assert!(core::mem::align_of::<RawMonitoredSpinlock>() == 8);
364};