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);
22 fn cpp_spinlock_destroy(lock: *mut c_void);
23 fn cpp_spinlock_acquire_irqsave(
24 lock: *mut c_void,
25 lcid: *mut c_void,
26 entry_storage: *mut c_void,
27 ) -> InterruptSavedState;
28 fn cpp_spinlock_release_irqrestore(
29 lock: *mut c_void,
30 entry_storage: *mut c_void,
31 state: InterruptSavedState,
32 );
33}
34
35#[cfg(feature = "spin_lock_tracing")]
36const RAW_SPINLOCK_SIZE: usize = 16;
37#[cfg(not(feature = "spin_lock_tracing"))]
38const RAW_SPINLOCK_SIZE: usize = 4;
39
40#[repr(C, align(8))]
41struct RawSpinlockStorage(zr::OpaqueBytes<RAW_SPINLOCK_SIZE>);
42
43#[pin_data(PinnedDrop)]
45#[repr(C)]
46pub struct RawSpinlock {
47 #[cfg(feature = "lock_dep")]
48 class_id: *const c_void,
49 storage: RawSpinlockStorage,
50}
51
52unsafe impl Sync for RawSpinlock {}
54unsafe impl Send for RawSpinlock {}
55
56zr::unsafe_pinned_drop_ffi!(RawSpinlock, cpp_spinlock_destroy);
57
58impl crate::RawLock for RawSpinlock {
59 type LockEntry = LockEntryStorage;
60 type GuardState = InterruptSavedState;
61
62 #[inline]
63 fn init() -> impl PinInit<Self, core::convert::Infallible> {
64 zr::pin_init_ffi!(cpp_spinlock_init)
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, lcid: *mut c_void, entry: *mut Self::LockEntry) -> Self::GuardState {
74 unsafe { cpp_spinlock_acquire_irqsave(self.as_mut_ptr(), lcid, entry as *mut c_void) }
75 }
76
77 #[inline]
78 unsafe fn release(&self, entry: *mut Self::LockEntry, state: Self::GuardState) {
79 unsafe {
80 cpp_spinlock_release_irqrestore(self.as_mut_ptr(), entry as *mut c_void, state);
81 }
82 }
83}
84
85const _: () = {
86 #[cfg(feature = "lock_dep")]
87 const BASE_SIZE: usize = 8;
88 #[cfg(not(feature = "lock_dep"))]
89 const BASE_SIZE: usize = 0;
90
91 const EXPECTED_SPINLOCK_SIZE: usize = BASE_SIZE + if RAW_SPINLOCK_SIZE == 4 { 8 } else { 16 };
92
93 assert!(core::mem::size_of::<RawSpinlock>() == EXPECTED_SPINLOCK_SIZE);
94 assert!(core::mem::align_of::<RawSpinlock>() == 8);
95};