ksync/
raw_kernel_mutex.rs1use crate::lockdep_tracked::LockdepTracked;
6use crate::raw_lock::{ConstRawLock, ExclusiveLockPolicy, LockPolicy, RawLock};
7use core::ffi::c_void;
8use pin_init::{PinInit, pin_data, pin_init_from_closure};
9
10#[cfg(any(feature = "lock_name_tracing", feature = "spin_lock_tracing"))]
11const RAW_MUTEX_SIZE: usize = 32;
12#[cfg(not(any(feature = "lock_name_tracing", feature = "spin_lock_tracing")))]
13const RAW_MUTEX_SIZE: usize = 24;
14
15unsafe extern "C" {
16 fn cpp_mutex_destroy(lock: *mut c_void);
17 fn cpp_mutex_acquire(lock: *mut c_void);
18 fn cpp_mutex_release(lock: *mut c_void);
19 fn cpp_mutex_is_contested(lock: *mut c_void) -> bool;
20
21 fn cpp_critical_mutex_acquire(lock: *mut c_void) -> bool;
22 fn cpp_critical_mutex_release(lock: *mut c_void, should_clear: bool);
23}
24
25const MUTEX_MAGIC: u32 = 0x6D757478; const INVALID_CPU: u32 = u32::MAX;
27
28const fn make_mutex_storage() -> [u8; RAW_MUTEX_SIZE] {
29 let mut bytes = [0u8; RAW_MUTEX_SIZE];
30 #[cfg(any(feature = "lock_name_tracing", feature = "spin_lock_tracing"))]
31 let offset = 8;
32 #[cfg(not(any(feature = "lock_name_tracing", feature = "spin_lock_tracing")))]
33 let offset = 0;
34
35 let magic_bytes = MUTEX_MAGIC.to_ne_bytes();
36 let cpu_bytes = INVALID_CPU.to_ne_bytes();
37
38 bytes[offset] = magic_bytes[0];
39 bytes[offset + 1] = magic_bytes[1];
40 bytes[offset + 2] = magic_bytes[2];
41 bytes[offset + 3] = magic_bytes[3];
42
43 bytes[offset + 4] = cpu_bytes[0];
44 bytes[offset + 5] = cpu_bytes[1];
45 bytes[offset + 6] = cpu_bytes[2];
46 bytes[offset + 7] = cpu_bytes[3];
47
48 bytes
49}
50
51#[pin_data(PinnedDrop)]
53#[repr(C, align(8))]
54pub struct RawMutexStorage {
55 storage: zr::OpaqueBytes<RAW_MUTEX_SIZE>,
56}
57
58impl RawMutexStorage {
59 #[allow(clippy::declare_interior_mutable_const)]
60 pub const INIT: Self = Self::const_init();
61
62 pub const fn const_init() -> Self {
64 Self { storage: zr::OpaqueBytes::new(make_mutex_storage()) }
65 }
66
67 #[inline]
72 pub fn is_contested(&self) -> bool {
73 unsafe { cpp_mutex_is_contested(self.as_mut_ptr()) }
75 }
76
77 #[cfg(any(test, ktest))]
79 #[inline]
80 pub fn raw_storage_slice(&self) -> &[u8] {
81 unsafe { core::slice::from_raw_parts(self.storage.get() as *const u8, RAW_MUTEX_SIZE) }
83 }
84}
85
86impl Default for RawMutexStorage {
87 fn default() -> Self {
88 Self::INIT
89 }
90}
91
92unsafe impl Sync for RawMutexStorage {}
94unsafe impl Send for RawMutexStorage {}
96
97zr::unsafe_pinned_drop_ffi!(RawMutexStorage, cpp_mutex_destroy);
98
99unsafe impl LockPolicy<RawMutexStorage> for RawMutexStorage {
102 type AcquireArgs = ();
103 type GuardState = ();
104
105 #[inline]
106 unsafe fn acquire(lock: &RawMutexStorage, _state: &mut Self::GuardState, _args: ()) {
107 unsafe {
109 cpp_mutex_acquire(lock.as_mut_ptr());
110 }
111 }
112
113 #[inline]
114 unsafe fn reacquire(lock: &RawMutexStorage, state: &mut Self::GuardState) {
115 unsafe {
117 Self::acquire(lock, state, ());
118 }
119 }
120
121 #[inline]
122 unsafe fn release(lock: &RawMutexStorage, _state: &mut Self::GuardState) {
123 unsafe {
126 cpp_mutex_release(lock.as_mut_ptr());
127 }
128 }
129}
130
131unsafe impl ExclusiveLockPolicy<RawMutexStorage> for RawMutexStorage {}
134
135unsafe impl RawLock for RawMutexStorage {
137 type DefaultPolicy = Self;
138
139 #[inline]
140 unsafe fn init(_class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
141 unsafe {
143 pin_init_from_closure(move |slot: *mut Self| {
144 slot.write(Self::const_init());
145 Ok(())
146 })
147 }
148 }
149
150 #[inline]
151 fn as_mut_ptr(&self) -> *mut c_void {
152 self as *const Self as *mut Self as *mut c_void
153 }
154}
155
156impl ConstRawLock for RawMutexStorage {
157 const INIT: Self = Self::INIT;
158}
159
160pub struct RawCriticalMutexPolicy;
162
163unsafe impl LockPolicy<RawMutexStorage> for RawCriticalMutexPolicy {
166 type AcquireArgs = ();
167 type GuardState = bool;
168
169 #[inline]
170 unsafe fn acquire(lock: &RawMutexStorage, state: &mut Self::GuardState, _args: ()) {
171 *state = unsafe { cpp_critical_mutex_acquire(lock.as_mut_ptr()) };
173 }
174
175 #[inline]
176 unsafe fn reacquire(lock: &RawMutexStorage, state: &mut Self::GuardState) {
177 unsafe {
179 Self::acquire(lock, state, ());
180 }
181 }
182
183 #[inline]
184 unsafe fn release(lock: &RawMutexStorage, should_clear: &mut Self::GuardState) {
185 unsafe {
188 cpp_critical_mutex_release(lock.as_mut_ptr(), *should_clear);
189 }
190 }
191}
192
193unsafe impl ExclusiveLockPolicy<RawMutexStorage> for RawCriticalMutexPolicy {}
196
197pub type RawMutex = LockdepTracked<RawMutexStorage>;
199
200pub type RawCriticalMutex = LockdepTracked<RawMutexStorage, RawCriticalMutexPolicy>;
202
203const _: () = {
204 const HAS_NAME_STORAGE: bool =
205 cfg!(any(feature = "lock_name_tracing", feature = "spin_lock_tracing"));
206 #[cfg(any(feature = "lock_dep", feature = "lock_metadata_only"))]
207 const EXPECTED_SIZE: usize = if HAS_NAME_STORAGE { 40 } else { 32 };
208 #[cfg(not(any(feature = "lock_dep", feature = "lock_metadata_only")))]
209 const EXPECTED_SIZE: usize = if HAS_NAME_STORAGE { 32 } else { 24 };
210
211 assert!(core::mem::size_of::<RawMutex>() == EXPECTED_SIZE);
212 assert!(core::mem::align_of::<RawMutex>() == 8);
213
214 assert!(core::mem::size_of::<RawCriticalMutex>() == EXPECTED_SIZE);
215 assert!(core::mem::align_of::<RawCriticalMutex>() == 8);
216};