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(any(feature = "lock_dep", feature = "lock_metadata_only"))]
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(any(feature = "lock_dep", feature = "lock_metadata_only"))]
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 {}
95
96zr::unsafe_pinned_drop_ffi!(RawSpinlock, cpp_spinlock_destroy);
97
98#[pin_data(PinnedDrop)]
100#[repr(C)]
101pub struct RawMonitoredSpinlock {
102 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
103 class_id: *const c_void,
104 storage: RawSpinlockStorage,
105}
106
107impl RawMonitoredSpinlock {
108 pub const INIT: Self = Self::const_init(core::ptr::null());
109
110 pub const fn const_init(_class_id: *const c_void) -> Self {
112 Self {
113 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
114 class_id: _class_id,
115 storage: RawSpinlockStorage(zr::OpaqueBytes::new([0u8; RAW_SPINLOCK_SIZE])),
116 }
117 }
118}
119
120impl Default for RawMonitoredSpinlock {
121 fn default() -> Self {
122 Self::INIT
123 }
124}
125
126unsafe impl Sync for RawMonitoredSpinlock {}
128unsafe impl Send for RawMonitoredSpinlock {}
130
131zr::unsafe_pinned_drop_ffi!(RawMonitoredSpinlock, cpp_monitored_spinlock_destroy);
132
133pub struct IrqSavePolicy;
134
135unsafe impl crate::LockPolicy<RawSpinlock> for IrqSavePolicy {
138 type AcquireArgs = ();
139 type GuardState = InterruptSavedState;
140
141 #[inline]
142 unsafe fn acquire(
143 lock: &RawSpinlock,
144 entry: *mut LockEntryStorage,
145 _args: (),
146 ) -> Self::GuardState {
147 unsafe { cpp_spinlock_acquire_irqsave(lock.as_mut_ptr(), entry as *mut c_void) }
150 }
151
152 #[inline]
153 unsafe fn reacquire(
154 lock: &RawSpinlock,
155 entry: *mut LockEntryStorage,
156 state: &mut Self::GuardState,
157 ) {
158 *state = unsafe { Self::acquire(lock, entry, ()) };
160 }
161
162 #[inline]
163 unsafe fn release(lock: &RawSpinlock, entry: *mut LockEntryStorage, state: Self::GuardState) {
164 unsafe {
167 cpp_spinlock_release_irqrestore(lock.as_mut_ptr(), entry as *mut c_void, state);
168 }
169 }
170}
171
172pub struct NoIrqSavePolicy;
173
174unsafe impl crate::LockPolicy<RawSpinlock> for NoIrqSavePolicy {
177 type AcquireArgs = ();
178 type GuardState = ();
179
180 #[inline]
181 unsafe fn acquire(
182 lock: &RawSpinlock,
183 entry: *mut LockEntryStorage,
184 _args: (),
185 ) -> Self::GuardState {
186 unsafe { cpp_spinlock_acquire_no_irqsave(lock.as_mut_ptr(), entry as *mut c_void) }
189 }
190
191 #[inline]
192 unsafe fn reacquire(
193 lock: &RawSpinlock,
194 entry: *mut LockEntryStorage,
195 state: &mut Self::GuardState,
196 ) {
197 *state = unsafe { Self::acquire(lock, entry, ()) };
199 }
200
201 #[inline]
202 unsafe fn release(lock: &RawSpinlock, entry: *mut LockEntryStorage, _state: Self::GuardState) {
203 unsafe {
206 cpp_spinlock_release_no_irqrestore(lock.as_mut_ptr(), entry as *mut c_void);
207 }
208 }
209}
210
211#[derive(Copy, Clone, Default)]
213pub struct MonitoredSpinlockGuardState {
214 pub interrupt_state: InterruptSavedState,
215 pub tag: crate::SourceTag,
216}
217
218unsafe impl crate::LockPolicy<RawMonitoredSpinlock> for IrqSavePolicy {
221 type AcquireArgs = crate::SourceTag;
222 type GuardState = MonitoredSpinlockGuardState;
223
224 #[inline]
225 unsafe fn acquire(
226 lock: &RawMonitoredSpinlock,
227 entry: *mut LockEntryStorage,
228 tag: Self::AcquireArgs,
229 ) -> Self::GuardState {
230 let interrupt_state = unsafe {
233 cpp_monitored_spinlock_acquire_irqsave(
234 lock.as_mut_ptr(),
235 entry as *mut c_void,
236 tag.as_ptr(),
237 )
238 };
239 MonitoredSpinlockGuardState { interrupt_state, tag }
240 }
241
242 #[inline]
243 unsafe fn reacquire(
244 lock: &RawMonitoredSpinlock,
245 entry: *mut LockEntryStorage,
246 state: &mut Self::GuardState,
247 ) {
248 state.interrupt_state = unsafe {
250 cpp_monitored_spinlock_acquire_irqsave(
251 lock.as_mut_ptr(),
252 entry as *mut c_void,
253 state.tag.as_ptr(),
254 )
255 };
256 }
257
258 #[inline]
259 unsafe fn release(
260 lock: &RawMonitoredSpinlock,
261 entry: *mut LockEntryStorage,
262 state: Self::GuardState,
263 ) {
264 unsafe {
267 cpp_monitored_spinlock_release_irqrestore(
268 lock.as_mut_ptr(),
269 entry as *mut c_void,
270 state.interrupt_state,
271 );
272 }
273 }
274}
275
276unsafe impl crate::LockPolicy<RawMonitoredSpinlock> for NoIrqSavePolicy {
280 type AcquireArgs = crate::SourceTag;
281 type GuardState = crate::SourceTag;
282
283 #[inline]
284 unsafe fn acquire(
285 lock: &RawMonitoredSpinlock,
286 entry: *mut LockEntryStorage,
287 tag: Self::AcquireArgs,
288 ) -> Self::GuardState {
289 unsafe {
292 cpp_monitored_spinlock_acquire_no_irqsave(
293 lock.as_mut_ptr(),
294 entry as *mut c_void,
295 tag.as_ptr(),
296 );
297 }
298 tag
299 }
300
301 #[inline]
302 unsafe fn reacquire(
303 lock: &RawMonitoredSpinlock,
304 entry: *mut LockEntryStorage,
305 state: &mut Self::GuardState,
306 ) {
307 unsafe {
309 cpp_monitored_spinlock_acquire_no_irqsave(
310 lock.as_mut_ptr(),
311 entry as *mut c_void,
312 state.as_ptr(),
313 );
314 }
315 }
316
317 #[inline]
318 unsafe fn release(
319 lock: &RawMonitoredSpinlock,
320 entry: *mut LockEntryStorage,
321 _state: Self::GuardState,
322 ) {
323 unsafe {
326 cpp_monitored_spinlock_release_no_irqrestore(lock.as_mut_ptr(), entry as *mut c_void);
327 }
328 }
329}
330
331unsafe impl crate::RawLock for RawSpinlock {
333 const LOCK_FLAGS: lockdep::LockFlags = lockdep::LOCK_FLAGS_IRQ_SAFE;
334
335 type LockEntry = LockEntryStorage;
336 type DefaultPolicy = IrqSavePolicy;
337
338 #[inline]
339 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
340 zr::pin_init_ffi!(cpp_spinlock_init, class_id)
341 }
342
343 #[inline]
344 fn as_mut_ptr(&self) -> *mut c_void {
345 self as *const Self as *mut Self as *mut c_void
346 }
347}
348
349unsafe impl crate::RawLock for RawMonitoredSpinlock {
351 const LOCK_FLAGS: lockdep::LockFlags = lockdep::LOCK_FLAGS_IRQ_SAFE;
352
353 type LockEntry = LockEntryStorage;
354 type DefaultPolicy = IrqSavePolicy;
355
356 #[inline]
357 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
358 zr::pin_init_ffi!(cpp_monitored_spinlock_init, class_id)
359 }
360
361 #[inline]
362 fn as_mut_ptr(&self) -> *mut c_void {
363 self as *const Self as *mut Self as *mut c_void
364 }
365}
366
367const _: () = {
368 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
369 const BASE_SIZE: usize = 8;
370 #[cfg(not(any(feature = "lock_dep", feature = "lock_metadata_only")))]
371 const BASE_SIZE: usize = 0;
372
373 const EXPECTED_SPINLOCK_SIZE: usize = BASE_SIZE + if RAW_SPINLOCK_SIZE == 4 { 8 } else { 16 };
374
375 assert!(core::mem::size_of::<RawSpinlock>() == EXPECTED_SPINLOCK_SIZE);
376 assert!(core::mem::align_of::<RawSpinlock>() == 8);
377 assert!(core::mem::size_of::<RawMonitoredSpinlock>() == EXPECTED_SPINLOCK_SIZE);
378 assert!(core::mem::align_of::<RawMonitoredSpinlock>() == 8);
379};