1use crate::lockdep_tracked::{LockdepTracked, impl_lockdep_tracked_lock_policy};
6use crate::raw_lock::{ConstRawLock, ExclusiveLockPolicy, LockPolicy, 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_ksync_interrupt_save() -> InterruptSavedState;
22
23 fn cpp_spinlock_init(lock: *mut c_void, class_id: *const c_void);
24 fn cpp_spinlock_destroy(lock: *mut c_void);
25 fn cpp_spinlock_acquire_irqsave(lock: *mut c_void) -> InterruptSavedState;
26 fn cpp_spinlock_release_irqrestore(lock: *mut c_void, state: InterruptSavedState);
27 fn cpp_spinlock_acquire_no_irqsave(lock: *mut c_void);
28 fn cpp_spinlock_release_no_irqrestore(lock: *mut c_void);
29
30 fn cpp_monitored_spinlock_init(lock: *mut c_void, class_id: *const c_void);
31 fn cpp_monitored_spinlock_destroy(lock: *mut c_void);
32 fn cpp_monitored_spinlock_acquire_irqsave(
33 lock: *mut c_void,
34 name: *const core::ffi::c_char,
35 ) -> InterruptSavedState;
36 fn cpp_monitored_spinlock_release_irqrestore(lock: *mut c_void, state: InterruptSavedState);
37 fn cpp_monitored_spinlock_acquire_no_irqsave(lock: *mut c_void, name: *const core::ffi::c_char);
38 fn cpp_monitored_spinlock_release_no_irqrestore(lock: *mut c_void);
39}
40
41#[cfg(feature = "spin_lock_tracing")]
42const RAW_SPINLOCK_SIZE: usize = 16;
43#[cfg(not(feature = "spin_lock_tracing"))]
44const RAW_SPINLOCK_SIZE: usize = 4;
45
46#[pin_data(PinnedDrop)]
54#[repr(C, align(8))]
55pub struct RawSpinlockStorage {
56 storage: zr::OpaqueBytes<RAW_SPINLOCK_SIZE>,
57}
58
59impl RawSpinlockStorage {
60 #[allow(clippy::declare_interior_mutable_const)]
61 pub const INIT: Self = Self::const_init();
62
63 pub const fn const_init() -> Self {
65 Self { storage: zr::OpaqueBytes::new([0u8; RAW_SPINLOCK_SIZE]) }
66 }
67}
68
69impl Default for RawSpinlockStorage {
70 fn default() -> Self {
71 Self::INIT
72 }
73}
74
75unsafe impl Sync for RawSpinlockStorage {}
77unsafe impl Send for RawSpinlockStorage {}
79
80zr::unsafe_pinned_drop_ffi!(RawSpinlockStorage, cpp_spinlock_destroy);
81
82#[pin_data(PinnedDrop)]
87#[repr(C, align(8))]
88pub struct RawMonitoredSpinlockStorage {
89 storage: zr::OpaqueBytes<RAW_SPINLOCK_SIZE>,
90}
91
92impl RawMonitoredSpinlockStorage {
93 #[allow(clippy::declare_interior_mutable_const)]
94 pub const INIT: Self = Self::const_init();
95
96 pub const fn const_init() -> Self {
98 Self { storage: zr::OpaqueBytes::new([0u8; RAW_SPINLOCK_SIZE]) }
99 }
100}
101
102impl Default for RawMonitoredSpinlockStorage {
103 fn default() -> Self {
104 Self::INIT
105 }
106}
107
108unsafe impl Sync for RawMonitoredSpinlockStorage {}
110unsafe impl Send for RawMonitoredSpinlockStorage {}
112
113zr::unsafe_pinned_drop_ffi!(RawMonitoredSpinlockStorage, cpp_monitored_spinlock_destroy);
114
115pub struct IrqSavePolicy;
116
117unsafe impl LockPolicy<RawSpinlockStorage> for IrqSavePolicy {
121 type AcquireArgs = ();
122 type GuardState = InterruptSavedState;
123
124 #[inline]
125 unsafe fn pre_validate(_lock: &RawSpinlockStorage, state: &mut Self::GuardState, _args: ()) {
126 *state = unsafe { cpp_ksync_interrupt_save() };
128 }
129
130 #[inline]
131 unsafe fn pre_reacquire(_lock: &RawSpinlockStorage, state: &mut Self::GuardState) {
132 *state = unsafe { cpp_ksync_interrupt_save() };
134 }
135
136 #[inline]
137 unsafe fn acquire(lock: &RawSpinlockStorage, state: &mut Self::GuardState, _args: ()) {
138 *state = unsafe { cpp_spinlock_acquire_irqsave(lock.as_mut_ptr()) };
140 }
141
142 #[inline]
143 unsafe fn post_validate_acquire(
144 lock: &RawSpinlockStorage,
145 _state: &mut Self::GuardState,
146 _args: (),
147 ) {
148 unsafe {
150 cpp_spinlock_acquire_no_irqsave(lock.as_mut_ptr());
151 }
152 }
153
154 #[inline]
155 unsafe fn reacquire(lock: &RawSpinlockStorage, state: &mut Self::GuardState) {
156 unsafe {
158 Self::acquire(lock, state, ());
159 }
160 }
161
162 #[inline]
163 unsafe fn post_validate_reacquire(lock: &RawSpinlockStorage, _state: &mut Self::GuardState) {
164 unsafe {
166 cpp_spinlock_acquire_no_irqsave(lock.as_mut_ptr());
167 }
168 }
169
170 #[inline]
171 unsafe fn release(lock: &RawSpinlockStorage, state: &mut Self::GuardState) {
172 unsafe {
175 cpp_spinlock_release_irqrestore(lock.as_mut_ptr(), *state);
176 }
177 }
178}
179
180unsafe impl ExclusiveLockPolicy<RawSpinlockStorage> for IrqSavePolicy {}
182
183pub struct NoIrqSavePolicy;
184
185unsafe impl LockPolicy<RawSpinlockStorage> for NoIrqSavePolicy {
188 type AcquireArgs = ();
189 type GuardState = ();
190
191 #[inline]
192 unsafe fn acquire(lock: &RawSpinlockStorage, _state: &mut Self::GuardState, _args: ()) {
193 unsafe { cpp_spinlock_acquire_no_irqsave(lock.as_mut_ptr()) }
195 }
196
197 #[inline]
198 unsafe fn reacquire(lock: &RawSpinlockStorage, state: &mut Self::GuardState) {
199 unsafe {
201 Self::acquire(lock, state, ());
202 }
203 }
204
205 #[inline]
206 unsafe fn release(lock: &RawSpinlockStorage, _state: &mut Self::GuardState) {
207 unsafe {
210 cpp_spinlock_release_no_irqrestore(lock.as_mut_ptr());
211 }
212 }
213}
214
215unsafe impl ExclusiveLockPolicy<RawSpinlockStorage> for NoIrqSavePolicy {}
217
218#[derive(Copy, Clone, Default)]
220pub struct MonitoredSpinlockGuardState {
221 pub interrupt_state: InterruptSavedState,
222 pub tag: crate::SourceTag,
223}
224
225unsafe impl LockPolicy<RawMonitoredSpinlockStorage> for IrqSavePolicy {
229 type AcquireArgs = crate::SourceTag;
230 type GuardState = MonitoredSpinlockGuardState;
231
232 #[inline]
233 unsafe fn pre_validate(
234 _lock: &RawMonitoredSpinlockStorage,
235 state: &mut Self::GuardState,
236 tag: Self::AcquireArgs,
237 ) {
238 let interrupt_state = unsafe { cpp_ksync_interrupt_save() };
240 *state = MonitoredSpinlockGuardState { interrupt_state, tag };
241 }
242
243 #[inline]
244 unsafe fn pre_reacquire(_lock: &RawMonitoredSpinlockStorage, state: &mut Self::GuardState) {
245 state.interrupt_state = unsafe { cpp_ksync_interrupt_save() };
247 }
248
249 #[inline]
250 unsafe fn acquire(
251 lock: &RawMonitoredSpinlockStorage,
252 state: &mut Self::GuardState,
253 tag: Self::AcquireArgs,
254 ) {
255 let interrupt_state =
258 unsafe { cpp_monitored_spinlock_acquire_irqsave(lock.as_mut_ptr(), tag.as_ptr()) };
259 *state = MonitoredSpinlockGuardState { interrupt_state, tag };
260 }
261
262 #[inline]
263 unsafe fn post_validate_acquire(
264 lock: &RawMonitoredSpinlockStorage,
265 _state: &mut Self::GuardState,
266 tag: Self::AcquireArgs,
267 ) {
268 unsafe {
271 cpp_monitored_spinlock_acquire_no_irqsave(lock.as_mut_ptr(), tag.as_ptr());
272 }
273 }
274
275 #[inline]
276 unsafe fn reacquire(lock: &RawMonitoredSpinlockStorage, state: &mut Self::GuardState) {
277 state.interrupt_state = unsafe {
279 cpp_monitored_spinlock_acquire_irqsave(lock.as_mut_ptr(), state.tag.as_ptr())
280 };
281 }
282
283 #[inline]
284 unsafe fn post_validate_reacquire(
285 lock: &RawMonitoredSpinlockStorage,
286 state: &mut Self::GuardState,
287 ) {
288 unsafe {
291 cpp_monitored_spinlock_acquire_no_irqsave(lock.as_mut_ptr(), state.tag.as_ptr());
292 }
293 }
294
295 #[inline]
296 unsafe fn release(lock: &RawMonitoredSpinlockStorage, state: &mut Self::GuardState) {
297 unsafe {
300 cpp_monitored_spinlock_release_irqrestore(lock.as_mut_ptr(), state.interrupt_state);
301 }
302 }
303}
304
305unsafe impl ExclusiveLockPolicy<RawMonitoredSpinlockStorage> for IrqSavePolicy {}
307
308unsafe impl LockPolicy<RawMonitoredSpinlockStorage> for NoIrqSavePolicy {
312 type AcquireArgs = crate::SourceTag;
313 type GuardState = crate::SourceTag;
314
315 #[inline]
316 unsafe fn acquire(
317 lock: &RawMonitoredSpinlockStorage,
318 state: &mut Self::GuardState,
319 tag: Self::AcquireArgs,
320 ) {
321 unsafe {
324 cpp_monitored_spinlock_acquire_no_irqsave(lock.as_mut_ptr(), tag.as_ptr());
325 }
326 *state = tag;
327 }
328
329 #[inline]
330 unsafe fn reacquire(lock: &RawMonitoredSpinlockStorage, state: &mut Self::GuardState) {
331 unsafe {
333 cpp_monitored_spinlock_acquire_no_irqsave(lock.as_mut_ptr(), state.as_ptr());
334 }
335 }
336
337 #[inline]
338 unsafe fn release(lock: &RawMonitoredSpinlockStorage, _state: &mut Self::GuardState) {
339 unsafe {
342 cpp_monitored_spinlock_release_no_irqrestore(lock.as_mut_ptr());
343 }
344 }
345}
346
347unsafe impl ExclusiveLockPolicy<RawMonitoredSpinlockStorage> for NoIrqSavePolicy {}
349
350unsafe impl RawLock for RawSpinlockStorage {
352 type DefaultPolicy = IrqSavePolicy;
353
354 #[inline]
355 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
356 zr::pin_init_ffi!(cpp_spinlock_init, class_id)
357 }
358
359 #[inline]
360 fn as_mut_ptr(&self) -> *mut c_void {
361 self as *const Self as *mut Self as *mut c_void
362 }
363}
364
365impl ConstRawLock for RawSpinlockStorage {
366 const INIT: Self = Self::INIT;
367}
368
369unsafe impl RawLock for RawMonitoredSpinlockStorage {
372 type DefaultPolicy = IrqSavePolicy;
373
374 #[inline]
375 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
376 zr::pin_init_ffi!(cpp_monitored_spinlock_init, class_id)
377 }
378
379 #[inline]
380 fn as_mut_ptr(&self) -> *mut c_void {
381 self as *const Self as *mut Self as *mut c_void
382 }
383}
384
385impl ConstRawLock for RawMonitoredSpinlockStorage {
386 const INIT: Self = Self::INIT;
387}
388
389impl_lockdep_tracked_lock_policy!(IrqSavePolicy);
390impl_lockdep_tracked_lock_policy!(NoIrqSavePolicy);
391
392pub type RawSpinlock =
394 LockdepTracked<RawSpinlockStorage, IrqSavePolicy, { lockdep::LOCK_FLAGS_IRQ_SAFE }>;
395
396pub type RawMonitoredSpinlock =
399 LockdepTracked<RawMonitoredSpinlockStorage, IrqSavePolicy, { lockdep::LOCK_FLAGS_IRQ_SAFE }>;
400
401const _: () = {
402 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
403 const BASE_SIZE: usize = 8;
404 #[cfg(not(any(feature = "lock_dep", feature = "lock_metadata_only")))]
405 const BASE_SIZE: usize = 0;
406
407 const EXPECTED_STORAGE_SIZE: usize = if RAW_SPINLOCK_SIZE == 4 { 8 } else { 16 };
410 const EXPECTED_SPINLOCK_SIZE: usize = BASE_SIZE + EXPECTED_STORAGE_SIZE;
411
412 assert!(core::mem::size_of::<RawSpinlockStorage>() == EXPECTED_STORAGE_SIZE);
413 assert!(core::mem::align_of::<RawSpinlockStorage>() == 8);
414 assert!(core::mem::size_of::<RawMonitoredSpinlockStorage>() == EXPECTED_STORAGE_SIZE);
415 assert!(core::mem::align_of::<RawMonitoredSpinlockStorage>() == 8);
416 assert!(core::mem::size_of::<RawSpinlock>() == EXPECTED_SPINLOCK_SIZE);
417 assert!(core::mem::align_of::<RawSpinlock>() == 8);
418 assert!(core::mem::size_of::<RawMonitoredSpinlock>() == EXPECTED_SPINLOCK_SIZE);
419 assert!(core::mem::align_of::<RawMonitoredSpinlock>() == 8);
420};