ksync/
raw_kernel_mutex.rs1use crate::raw_lock::RawLock;
6use core::ffi::c_void;
7use pin_init::{PinInit, pin_data, pin_init_from_closure};
8
9#[cfg(any(feature = "lock_name_tracing", feature = "spin_lock_tracing"))]
10const RAW_MUTEX_SIZE: usize = 32;
11#[cfg(not(any(feature = "lock_name_tracing", feature = "spin_lock_tracing")))]
12const RAW_MUTEX_SIZE: usize = 24;
13
14unsafe extern "C" {
15 fn cpp_mutex_destroy(mutex: *mut c_void);
16 fn cpp_mutex_acquire(lock: *mut c_void, entry_storage: *mut c_void);
17 fn cpp_mutex_release(lock: *mut c_void, entry_storage: *mut c_void);
18 fn cpp_mutex_is_contested(lock: *mut c_void) -> bool;
19
20 fn cpp_critical_mutex_destroy(mutex: *mut c_void);
21 fn cpp_critical_mutex_acquire(lock: *mut c_void, entry_storage: *mut c_void) -> bool;
22 fn cpp_critical_mutex_release(
23 lock: *mut c_void,
24 entry_storage: *mut c_void,
25 should_clear: bool,
26 );
27 fn cpp_critical_mutex_is_contested(lock: *mut c_void) -> bool;
28}
29
30const MUTEX_MAGIC: u32 = 0x6D757478; const INVALID_CPU: u32 = u32::MAX;
32
33const fn make_mutex_storage() -> [u8; RAW_MUTEX_SIZE] {
34 let mut bytes = [0u8; RAW_MUTEX_SIZE];
35 #[cfg(any(feature = "lock_name_tracing", feature = "spin_lock_tracing"))]
36 let offset = 8;
37 #[cfg(not(any(feature = "lock_name_tracing", feature = "spin_lock_tracing")))]
38 let offset = 0;
39
40 let magic_bytes = MUTEX_MAGIC.to_ne_bytes();
41 let cpu_bytes = INVALID_CPU.to_ne_bytes();
42
43 bytes[offset] = magic_bytes[0];
44 bytes[offset + 1] = magic_bytes[1];
45 bytes[offset + 2] = magic_bytes[2];
46 bytes[offset + 3] = magic_bytes[3];
47
48 bytes[offset + 4] = cpu_bytes[0];
49 bytes[offset + 5] = cpu_bytes[1];
50 bytes[offset + 6] = cpu_bytes[2];
51 bytes[offset + 7] = cpu_bytes[3];
52
53 bytes
54}
55
56#[repr(C, align(8))]
57struct RawMutexStorage(zr::OpaqueBytes<RAW_MUTEX_SIZE>);
58
59#[derive(Default)]
60#[repr(C, align(8))]
61pub struct LockEntryStorage(zr::OpaqueBytes<40>);
62
63#[pin_data(PinnedDrop)]
65#[repr(C)]
66pub struct RawMutex {
67 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
68 class_id: *const c_void,
69 storage: RawMutexStorage,
70}
71
72impl RawMutex {
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: RawMutexStorage(zr::OpaqueBytes::new(make_mutex_storage())),
81 }
82 }
83
84 #[inline]
89 pub fn is_contested(&self) -> bool {
90 unsafe { cpp_mutex_is_contested(self.as_mut_ptr()) }
92 }
93
94 #[cfg(any(test, ktest))]
96 #[inline]
97 pub fn raw_storage_slice(&self) -> &[u8] {
98 unsafe { core::slice::from_raw_parts(self.storage.0.get() as *const u8, RAW_MUTEX_SIZE) }
100 }
101}
102
103impl Default for RawMutex {
104 fn default() -> Self {
105 Self::const_init(core::ptr::null())
106 }
107}
108
109unsafe impl Sync for RawMutex {}
111unsafe impl Send for RawMutex {}
113
114zr::unsafe_pinned_drop_ffi!(RawMutex, cpp_mutex_destroy);
115
116pub struct RawMutexPolicy;
117
118unsafe impl crate::LockPolicy<RawMutex> for RawMutexPolicy {
120 type AcquireArgs = ();
121 type GuardState = ();
122
123 #[inline]
124 unsafe fn acquire(
125 lock: &RawMutex,
126 entry: *mut LockEntryStorage,
127 _args: (),
128 ) -> Self::GuardState {
129 unsafe {
132 cpp_mutex_acquire(lock.as_mut_ptr(), entry as *mut c_void);
133 }
134 }
135
136 #[inline]
137 unsafe fn reacquire(
138 lock: &RawMutex,
139 entry: *mut LockEntryStorage,
140 state: &mut Self::GuardState,
141 ) {
142 *state = unsafe { Self::acquire(lock, entry, ()) };
144 }
145
146 #[inline]
147 unsafe fn release(lock: &RawMutex, entry: *mut LockEntryStorage, _state: Self::GuardState) {
148 unsafe {
151 cpp_mutex_release(lock.as_mut_ptr(), entry as *mut c_void);
152 }
153 }
154}
155
156unsafe impl crate::RawLock for RawMutex {
158 type LockEntry = LockEntryStorage;
159 type DefaultPolicy = RawMutexPolicy;
160
161 #[inline]
162 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
163 unsafe {
165 pin_init_from_closure(move |slot: *mut Self| {
166 slot.write(Self::const_init(class_id));
167 Ok(())
168 })
169 }
170 }
171
172 #[inline]
173 fn as_mut_ptr(&self) -> *mut c_void {
174 self as *const Self as *mut Self as *mut c_void
175 }
176}
177
178#[pin_data(PinnedDrop)]
180#[repr(C)]
181pub struct RawCriticalMutex {
182 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
183 class_id: *const c_void,
184 storage: RawMutexStorage,
185}
186
187impl RawCriticalMutex {
188 pub const INIT: Self = Self::const_init(core::ptr::null());
189
190 pub const fn const_init(_class_id: *const c_void) -> Self {
192 Self {
193 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
194 class_id: _class_id,
195 storage: RawMutexStorage(zr::OpaqueBytes::new(make_mutex_storage())),
196 }
197 }
198
199 #[inline]
204 pub fn is_contested(&self) -> bool {
205 unsafe { cpp_critical_mutex_is_contested(self.as_mut_ptr()) }
207 }
208
209 #[cfg(any(test, ktest))]
211 #[inline]
212 pub fn raw_storage_slice(&self) -> &[u8] {
213 unsafe { core::slice::from_raw_parts(self.storage.0.get() as *const u8, RAW_MUTEX_SIZE) }
215 }
216}
217
218impl Default for RawCriticalMutex {
219 fn default() -> Self {
220 Self::const_init(core::ptr::null())
221 }
222}
223
224unsafe impl Sync for RawCriticalMutex {}
226unsafe impl Send for RawCriticalMutex {}
228
229zr::unsafe_pinned_drop_ffi!(RawCriticalMutex, cpp_critical_mutex_destroy);
230
231pub struct RawCriticalMutexPolicy;
232
233unsafe impl crate::LockPolicy<RawCriticalMutex> for RawCriticalMutexPolicy {
236 type AcquireArgs = ();
237 type GuardState = bool;
238
239 #[inline]
240 unsafe fn acquire(
241 lock: &RawCriticalMutex,
242 entry: *mut LockEntryStorage,
243 _args: (),
244 ) -> Self::GuardState {
245 unsafe { cpp_critical_mutex_acquire(lock.as_mut_ptr(), entry as *mut c_void) }
248 }
249
250 #[inline]
251 unsafe fn reacquire(
252 lock: &RawCriticalMutex,
253 entry: *mut LockEntryStorage,
254 state: &mut Self::GuardState,
255 ) {
256 *state = unsafe { Self::acquire(lock, entry, ()) };
258 }
259
260 #[inline]
261 unsafe fn release(
262 lock: &RawCriticalMutex,
263 entry: *mut LockEntryStorage,
264 should_clear: Self::GuardState,
265 ) {
266 unsafe {
269 cpp_critical_mutex_release(lock.as_mut_ptr(), entry as *mut c_void, should_clear);
270 }
271 }
272}
273
274unsafe impl crate::RawLock for RawCriticalMutex {
276 type LockEntry = LockEntryStorage;
277 type DefaultPolicy = RawCriticalMutexPolicy;
278
279 #[inline]
280 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
281 unsafe {
283 pin_init_from_closure(move |slot: *mut Self| {
284 slot.write(Self::const_init(class_id));
285 Ok(())
286 })
287 }
288 }
289
290 #[inline]
291 fn as_mut_ptr(&self) -> *mut c_void {
292 self as *const Self as *mut Self as *mut c_void
293 }
294}
295
296const _: () = {
297 const HAS_NAME_STORAGE: bool =
298 cfg!(any(feature = "lock_name_tracing", feature = "spin_lock_tracing"));
299 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
300 const EXPECTED_SIZE: usize = if HAS_NAME_STORAGE { 40 } else { 32 };
301 #[cfg(not(any(feature = "lock_dep", feature = "lock_metadata_only")))]
302 const EXPECTED_SIZE: usize = if HAS_NAME_STORAGE { 32 } else { 24 };
303
304 assert!(core::mem::size_of::<RawMutex>() == EXPECTED_SIZE);
305 assert!(core::mem::align_of::<RawMutex>() == 8);
306
307 assert!(core::mem::size_of::<RawCriticalMutex>() == EXPECTED_SIZE);
308 assert!(core::mem::align_of::<RawCriticalMutex>() == 8);
309};