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
41impl RawSpinlockStorage {
42 const fn zeroed() -> Self {
43 Self(zr::OpaqueBytes::new([0; RAW_SPINLOCK_SIZE]))
44 }
45}
46
47#[pin_data(PinnedDrop)]
49#[repr(C)]
50pub struct RawSpinlock {
51 #[cfg(feature = "lock_dep")]
52 class_id: *const c_void,
53 storage: RawSpinlockStorage,
54}
55
56impl RawSpinlock {
57 pub const fn zeroed() -> Self {
59 Self {
60 #[cfg(feature = "lock_dep")]
61 class_id: core::ptr::null(),
62 storage: RawSpinlockStorage::zeroed(),
63 }
64 }
65}
66
67unsafe impl Sync for RawSpinlock {}
69unsafe impl Send for RawSpinlock {}
70
71zr::unsafe_pinned_drop_ffi!(RawSpinlock, cpp_spinlock_destroy);
72
73impl crate::RawLock for RawSpinlock {
74 type LockEntry = LockEntryStorage;
75 type GuardState = InterruptSavedState;
76
77 #[inline]
78 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
79 zr::pin_init_ffi!(cpp_spinlock_init, class_id)
80 }
81
82 #[inline]
83 fn as_mut_ptr(&self) -> *mut c_void {
84 self as *const Self as *mut Self as *mut c_void
85 }
86
87 #[inline]
88 unsafe fn acquire(&self, entry: *mut Self::LockEntry) -> Self::GuardState {
89 unsafe { cpp_spinlock_acquire_irqsave(self.as_mut_ptr(), entry as *mut c_void) }
92 }
93
94 #[inline]
95 unsafe fn release(&self, entry: *mut Self::LockEntry, state: Self::GuardState) {
96 unsafe {
99 cpp_spinlock_release_irqrestore(self.as_mut_ptr(), entry as *mut c_void, state);
100 }
101 }
102}
103
104const _: () = {
105 #[cfg(feature = "lock_dep")]
106 const BASE_SIZE: usize = 8;
107 #[cfg(not(feature = "lock_dep"))]
108 const BASE_SIZE: usize = 0;
109
110 const EXPECTED_SPINLOCK_SIZE: usize = BASE_SIZE + if RAW_SPINLOCK_SIZE == 4 { 8 } else { 16 };
111
112 assert!(core::mem::size_of::<RawSpinlock>() == EXPECTED_SPINLOCK_SIZE);
113 assert!(core::mem::align_of::<RawSpinlock>() == 8);
114};