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(feature = "lock_name_tracing")]
10const RAW_MUTEX_SIZE: usize = 32;
11#[cfg(not(feature = "lock_name_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
19 fn cpp_critical_mutex_destroy(mutex: *mut c_void);
20 fn cpp_critical_mutex_acquire(lock: *mut c_void, entry_storage: *mut c_void) -> bool;
21 fn cpp_critical_mutex_release(
22 lock: *mut c_void,
23 entry_storage: *mut c_void,
24 should_clear: bool,
25 );
26}
27
28const MUTEX_MAGIC: u32 = 0x6D757478; const INVALID_CPU: u32 = u32::MAX;
30
31const fn make_mutex_storage() -> [u8; RAW_MUTEX_SIZE] {
32 let mut bytes = [0u8; RAW_MUTEX_SIZE];
33 #[cfg(feature = "lock_name_tracing")]
34 let offset = 8;
35 #[cfg(not(feature = "lock_name_tracing"))]
36 let offset = 0;
37
38 let magic_bytes = MUTEX_MAGIC.to_ne_bytes();
39 let cpu_bytes = INVALID_CPU.to_ne_bytes();
40
41 bytes[offset] = magic_bytes[0];
42 bytes[offset + 1] = magic_bytes[1];
43 bytes[offset + 2] = magic_bytes[2];
44 bytes[offset + 3] = magic_bytes[3];
45
46 bytes[offset + 4] = cpu_bytes[0];
47 bytes[offset + 5] = cpu_bytes[1];
48 bytes[offset + 6] = cpu_bytes[2];
49 bytes[offset + 7] = cpu_bytes[3];
50
51 bytes
52}
53
54#[repr(C, align(8))]
55struct RawMutexStorage(zr::OpaqueBytes<RAW_MUTEX_SIZE>);
56
57#[derive(Default)]
58#[repr(C, align(8))]
59pub struct LockEntryStorage(zr::OpaqueBytes<40>);
60
61#[pin_data(PinnedDrop)]
63#[repr(C)]
64pub struct RawMutex {
65 #[cfg(feature = "lock_dep")]
66 class_id: *const c_void,
67 storage: RawMutexStorage,
68}
69
70impl RawMutex {
71 pub const INIT: Self = Self::const_init(core::ptr::null());
72
73 pub const fn const_init(_class_id: *const c_void) -> Self {
75 Self {
76 #[cfg(feature = "lock_dep")]
77 class_id: _class_id,
78 storage: RawMutexStorage(zr::OpaqueBytes::new(make_mutex_storage())),
79 }
80 }
81
82 #[cfg(any(test, ktest))]
84 #[inline]
85 pub fn raw_storage_slice(&self) -> &[u8] {
86 unsafe { core::slice::from_raw_parts(self.storage.0.get() as *const u8, RAW_MUTEX_SIZE) }
88 }
89}
90
91impl Default for RawMutex {
92 fn default() -> Self {
93 Self::const_init(core::ptr::null())
94 }
95}
96
97unsafe impl Sync for RawMutex {}
99unsafe impl Send for RawMutex {}
100
101zr::unsafe_pinned_drop_ffi!(RawMutex, cpp_mutex_destroy);
102
103pub struct RawMutexPolicy;
104
105impl crate::LockPolicy<RawMutex> for RawMutexPolicy {
106 type AcquireArgs = ();
107 type GuardState = ();
108
109 #[inline]
110 unsafe fn acquire(
111 lock: &RawMutex,
112 entry: *mut LockEntryStorage,
113 _args: (),
114 ) -> Self::GuardState {
115 unsafe {
118 cpp_mutex_acquire(lock.as_mut_ptr(), entry as *mut c_void);
119 }
120 }
121
122 #[inline]
123 unsafe fn reacquire(
124 lock: &RawMutex,
125 entry: *mut LockEntryStorage,
126 state: &mut Self::GuardState,
127 ) {
128 *state = unsafe { Self::acquire(lock, entry, ()) };
129 }
130
131 #[inline]
132 unsafe fn release(lock: &RawMutex, entry: *mut LockEntryStorage, _state: Self::GuardState) {
133 unsafe {
136 cpp_mutex_release(lock.as_mut_ptr(), entry as *mut c_void);
137 }
138 }
139}
140
141impl crate::RawLock for RawMutex {
142 type LockEntry = LockEntryStorage;
143 type DefaultPolicy = RawMutexPolicy;
144
145 #[inline]
146 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
147 unsafe {
149 pin_init_from_closure(move |slot: *mut Self| {
150 slot.write(Self::const_init(class_id));
151 Ok(())
152 })
153 }
154 }
155
156 #[inline]
157 fn as_mut_ptr(&self) -> *mut c_void {
158 self as *const Self as *mut Self as *mut c_void
159 }
160}
161
162#[pin_data(PinnedDrop)]
164#[repr(C)]
165pub struct RawCriticalMutex {
166 #[cfg(feature = "lock_dep")]
167 class_id: *const c_void,
168 storage: RawMutexStorage,
169}
170
171impl RawCriticalMutex {
172 pub const INIT: Self = Self::const_init(core::ptr::null());
173
174 pub const fn const_init(_class_id: *const c_void) -> Self {
176 Self {
177 #[cfg(feature = "lock_dep")]
178 class_id: _class_id,
179 storage: RawMutexStorage(zr::OpaqueBytes::new(make_mutex_storage())),
180 }
181 }
182
183 #[cfg(any(test, ktest))]
185 #[inline]
186 pub fn raw_storage_slice(&self) -> &[u8] {
187 unsafe { core::slice::from_raw_parts(self.storage.0.get() as *const u8, RAW_MUTEX_SIZE) }
189 }
190}
191
192impl Default for RawCriticalMutex {
193 fn default() -> Self {
194 Self::const_init(core::ptr::null())
195 }
196}
197
198unsafe impl Sync for RawCriticalMutex {}
200unsafe impl Send for RawCriticalMutex {}
201
202zr::unsafe_pinned_drop_ffi!(RawCriticalMutex, cpp_critical_mutex_destroy);
203
204pub struct RawCriticalMutexPolicy;
205
206impl crate::LockPolicy<RawCriticalMutex> for RawCriticalMutexPolicy {
207 type AcquireArgs = ();
208 type GuardState = bool;
209
210 #[inline]
211 unsafe fn acquire(
212 lock: &RawCriticalMutex,
213 entry: *mut LockEntryStorage,
214 _args: (),
215 ) -> Self::GuardState {
216 unsafe { cpp_critical_mutex_acquire(lock.as_mut_ptr(), entry as *mut c_void) }
219 }
220
221 #[inline]
222 unsafe fn reacquire(
223 lock: &RawCriticalMutex,
224 entry: *mut LockEntryStorage,
225 state: &mut Self::GuardState,
226 ) {
227 *state = unsafe { Self::acquire(lock, entry, ()) };
228 }
229
230 #[inline]
231 unsafe fn release(
232 lock: &RawCriticalMutex,
233 entry: *mut LockEntryStorage,
234 should_clear: Self::GuardState,
235 ) {
236 unsafe {
239 cpp_critical_mutex_release(lock.as_mut_ptr(), entry as *mut c_void, should_clear);
240 }
241 }
242}
243
244impl crate::RawLock for RawCriticalMutex {
245 type LockEntry = LockEntryStorage;
246 type DefaultPolicy = RawCriticalMutexPolicy;
247
248 #[inline]
249 unsafe fn init(class_id: *const c_void) -> impl PinInit<Self, core::convert::Infallible> {
250 unsafe {
252 pin_init_from_closure(move |slot: *mut Self| {
253 slot.write(Self::const_init(class_id));
254 Ok(())
255 })
256 }
257 }
258
259 #[inline]
260 fn as_mut_ptr(&self) -> *mut c_void {
261 self as *const Self as *mut Self as *mut c_void
262 }
263}
264
265const _: () = {
266 #[cfg(feature = "lock_dep")]
267 const EXPECTED_SIZE: usize = if cfg!(feature = "lock_name_tracing") { 40 } else { 32 };
268 #[cfg(not(feature = "lock_dep"))]
269 const EXPECTED_SIZE: usize = if cfg!(feature = "lock_name_tracing") { 32 } else { 24 };
270
271 assert!(core::mem::size_of::<RawMutex>() == EXPECTED_SIZE);
272 assert!(core::mem::align_of::<RawMutex>() == 8);
273
274 assert!(core::mem::size_of::<RawCriticalMutex>() == EXPECTED_SIZE);
275 assert!(core::mem::align_of::<RawCriticalMutex>() == 8);
276};