1use crate::raw_kernel_mutex::LockEntryStorage;
6use core::ffi::c_void;
7use pin_init::{PinInit, pin_data};
8
9#[cfg(target_arch = "x86_64")]
10type InnerSavedState = u64;
11#[cfg(not(target_arch = "x86_64"))]
12type InnerSavedState = bool;
13
14#[repr(transparent)]
16#[derive(Copy, Clone, Default)]
17pub struct InterruptSavedState(InnerSavedState);
18
19unsafe extern "C" {
20 fn cpp_spinlock_init(lock: *mut c_void, class_id: *const c_void);
21 fn cpp_spinlock_destroy(lock: *mut c_void);
22 fn cpp_spinlock_acquire_irqsave(
23 lock: *mut c_void,
24 entry_storage: *mut c_void,
25 ) -> InterruptSavedState;
26 fn cpp_spinlock_release_irqrestore(
27 lock: *mut c_void,
28 entry_storage: *mut c_void,
29 state: InterruptSavedState,
30 );
31}
32
33#[cfg(feature = "spin_lock_tracing")]
34const RAW_SPINLOCK_SIZE: usize = 16;
35#[cfg(not(feature = "spin_lock_tracing"))]
36const RAW_SPINLOCK_SIZE: usize = 4;
37
38#[repr(C, align(8))]
39struct RawSpinlockStorage(zr::OpaqueBytes<RAW_SPINLOCK_SIZE>);
40
41#[pin_data(PinnedDrop)]
43#[repr(C)]
44pub struct RawSpinlock {
45 #[cfg(feature = "lock_dep")]
46 class_id: *const c_void,
47 storage: RawSpinlockStorage,
48}
49
50unsafe impl Sync for RawSpinlock {}
52unsafe impl Send for RawSpinlock {}
53
54zr::unsafe_pinned_drop_ffi!(RawSpinlock, cpp_spinlock_destroy);
55
56impl crate::RawLock for RawSpinlock {
57 const LOCK_FLAGS: lockdep::LockFlags = lockdep::LOCK_FLAGS_IRQ_SAFE;
58
59 type LockEntry = LockEntryStorage;
60 type GuardState = InterruptSavedState;
61
62 #[inline]
63 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
64 zr::pin_init_ffi!(cpp_spinlock_init, class_id)
65 }
66
67 #[inline]
68 fn as_mut_ptr(&self) -> *mut c_void {
69 self as *const Self as *mut Self as *mut c_void
70 }
71
72 #[inline]
73 unsafe fn acquire(&self, entry: *mut Self::LockEntry) -> Self::GuardState {
74 unsafe { cpp_spinlock_acquire_irqsave(self.as_mut_ptr(), entry as *mut c_void) }
77 }
78
79 #[inline]
80 unsafe fn release(&self, entry: *mut Self::LockEntry, state: Self::GuardState) {
81 unsafe {
84 cpp_spinlock_release_irqrestore(self.as_mut_ptr(), entry as *mut c_void, state);
85 }
86 }
87}
88
89const _: () = {
90 #[cfg(feature = "lock_dep")]
91 const BASE_SIZE: usize = 8;
92 #[cfg(not(feature = "lock_dep"))]
93 const BASE_SIZE: usize = 0;
94
95 const EXPECTED_SPINLOCK_SIZE: usize = BASE_SIZE + if RAW_SPINLOCK_SIZE == 4 { 8 } else { 16 };
96
97 assert!(core::mem::size_of::<RawSpinlock>() == EXPECTED_SPINLOCK_SIZE);
98 assert!(core::mem::align_of::<RawSpinlock>() == 8);
99};