1use crate::lock_token::{LockTokenRead, LockTokenWrite};
6use core::marker::PhantomData;
7
8#[repr(transparent)]
14pub struct KCell<T, Class> {
15 value: core::cell::UnsafeCell<T>,
16 _marker: PhantomData<Class>,
17}
18
19unsafe impl<T: Send, Class> Sync for KCell<T, Class> {}
21unsafe impl<T: Send, Class> Send for KCell<T, Class> {}
23
24impl<T, Class> KCell<T, Class> {
25 #[inline]
27 pub const fn new(value: T) -> Self {
28 Self { value: core::cell::UnsafeCell::new(value), _marker: PhantomData }
29 }
30
31 #[inline]
39 pub unsafe fn get<'b, Token, Idx>(&self, _token: &'b Token) -> &'b T
40 where
41 Token: LockTokenRead<Class, Idx>,
42 {
43 unsafe { &*self.value.get() }
46 }
47
48 #[inline]
56 pub unsafe fn get_mut<'b, Token, Idx>(&self, _token: &'b mut Token) -> &'b mut T
57 where
58 Token: LockTokenWrite<Class, Idx>,
59 {
60 unsafe { &mut *self.value.get() }
64 }
65
66 #[inline]
74 pub unsafe fn get_pinned_mut_locked<'b, Token, Idx>(
75 &self,
76 token: &'b mut Token,
77 ) -> core::pin::Pin<&'b mut T>
78 where
79 Token: LockTokenWrite<Class, Idx>,
80 {
81 unsafe { core::pin::Pin::new_unchecked(self.get_mut(token)) }
84 }
85
86 #[inline]
93 pub unsafe fn as_ptr<Token, Idx>(&self, _token: &Token) -> *const T
94 where
95 Token: LockTokenRead<Class, Idx>,
96 {
97 self.value.get()
98 }
99
100 #[inline]
107 pub unsafe fn as_mut_ptr<Token, Idx>(&self, _token: &mut Token) -> *mut T
108 where
109 Token: LockTokenWrite<Class, Idx>,
110 {
111 self.value.get()
112 }
113
114 #[inline]
117 pub fn get_inner_mut(&mut self) -> &mut T {
118 self.value.get_mut()
119 }
120
121 #[inline]
123 pub fn get_pinned_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut T> {
124 unsafe { self.map_unchecked_mut(|s| s.get_inner_mut()) }
127 }
128
129 pub fn init<I, E>(init: I) -> impl pin_init::Init<Self, E>
131 where
132 I: pin_init::Init<T, E>,
133 {
134 kcell_init(init)
135 }
136
137 pub fn pin_init<I, E>(init: I) -> impl pin_init::PinInit<Self, E>
139 where
140 I: pin_init::PinInit<T, E>,
141 {
142 kcell_init(init)
143 }
144
145 #[inline]
147 pub fn into_inner(self) -> T {
148 self.value.into_inner()
149 }
150}
151
152impl<T: Default, Class> Default for KCell<T, Class> {
153 #[inline]
154 fn default() -> Self {
155 Self::new(T::default())
156 }
157}
158
159impl<T, Class> From<T> for KCell<T, Class> {
160 #[inline]
161 fn from(value: T) -> Self {
162 Self::new(value)
163 }
164}
165
166impl<T, Class> AsMut<T> for KCell<T, Class> {
167 #[inline]
168 fn as_mut(&mut self) -> &mut T {
169 self.get_inner_mut()
170 }
171}
172
173impl<T, Class> core::fmt::Debug for KCell<T, Class> {
174 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
175 f.debug_struct("KCell")
176 .field("value", &"<locked>")
177 .field("class", &core::any::type_name::<Class>())
178 .finish()
179 }
180}
181
182#[inline]
185pub fn kcell_init<I, Class>(init: I) -> KCellInit<I, Class> {
186 KCellInit(init, PhantomData)
187}
188
189pub struct KCellInit<I, Class>(I, PhantomData<Class>);
191
192unsafe impl<T, Class, I, E> pin_init::PinInit<KCell<T, Class>, E> for KCellInit<I, Class>
195where
196 I: pin_init::PinInit<T, E>,
197{
198 unsafe fn __pinned_init(self, slot: *mut KCell<T, Class>) -> Result<(), E> {
199 unsafe { self.0.__pinned_init(slot as *mut T) }
202 }
203}
204
205unsafe impl<T, Class, I, E> pin_init::Init<KCell<T, Class>, E> for KCellInit<I, Class>
207where
208 I: pin_init::Init<T, E>,
209{
210 unsafe fn __init(self, slot: *mut KCell<T, Class>) -> Result<(), E> {
211 unsafe { self.0.__init(slot as *mut T) }
214 }
215}
216
217#[cfg(not(feature = "kernel"))]
218#[cfg(test)]
219mod tests {
220 use super::*;
221 use crate::lock_token::LockToken;
222 use lockdep::LockClass;
223
224 struct MyClass;
225 impl LockClass for MyClass {
226 const ID: *mut core::ffi::c_void = core::ptr::null_mut();
227 }
228
229 #[test]
230 fn test_kcell_default() {
231 let cell: KCell<u32, MyClass> = KCell::default();
232 unsafe {
234 let token = LockToken::new();
235 assert_eq!(*cell.get(&token), 0);
236 }
237 }
238
239 #[test]
240 fn test_kcell_exclusive_access() {
241 let mut cell: KCell<u32, MyClass> = KCell::new(10);
242 *cell.get_inner_mut() = 20;
243 let reference: &mut u32 = cell.as_mut();
244 *reference = 30;
245 let value = cell.into_inner();
246 assert_eq!(value, 30);
247 }
248
249 #[test]
250 fn test_kcell_as_mut_ptr() {
251 let cell: KCell<u32, MyClass> = KCell::new(100u32);
252 unsafe {
254 let mut token = LockToken::new();
255 let ptr = cell.as_mut_ptr(&mut token);
256 assert_eq!(*ptr, 100);
257 }
258 }
259
260 #[test]
261 fn test_kcell_debug() {
262 extern crate std;
263 let cell: KCell<u32, MyClass> = KCell::new(5);
264 let debug_str = std::format!("{:?}", cell);
265 assert!(debug_str.contains("KCell"));
266 assert!(debug_str.contains("<locked>"));
267 assert!(debug_str.contains("MyClass"));
268 }
269
270 #[test]
271 fn test_kcell_init() {
272 let init = unsafe {
274 pin_init::pin_init_from_closure(|slot: *mut u32| {
275 slot.write(42);
276 Ok::<(), core::convert::Infallible>(())
277 })
278 };
279 let cell_init = kcell_init::<_, MyClass>(init);
280
281 pin_init::stack_pin_init!(let cell = cell_init);
282 let cell: core::pin::Pin<&mut KCell<u32, MyClass>> = cell;
283
284 unsafe {
286 let token = LockToken::<MyClass>::new();
287 let val = cell.as_ref().get_ref().get(&token);
288 assert_eq!(*val, 42);
289 }
290
291 #[pin_init::pin_data]
292 struct UnpinnedHolder {
293 cell: KCell<[usize; 4], MyClass>,
294 }
295
296 pin_init::stack_pin_init!(let holder = pin_init::pin_init!(UnpinnedHolder {
297 cell <- KCell::<[usize; 4], MyClass>::init(pin_init::init_zeroed::<[usize; 4]>()),
298 }));
299 unsafe {
301 let token = LockToken::<MyClass>::new();
302 assert_eq!(*holder.as_ref().get_ref().cell.get(&token), [0usize; 4]);
303 }
304 }
305
306 #[test]
307 fn test_kcell_get_pinned_mut_locked() {
308 let cell = core::pin::pin!(KCell::<u32, MyClass>::new(7));
309 let cell: &KCell<u32, MyClass> = cell.as_ref().get_ref();
310
311 unsafe {
313 let mut token = LockToken::<MyClass>::new();
314 let mut pinned: core::pin::Pin<&mut u32> = cell.get_pinned_mut_locked(&mut token);
315 assert_eq!(*pinned, 7);
316 pinned.set(8);
317 *pinned.as_mut().get_mut() += 1;
318 assert_eq!(*cell.get(&token), 9);
319 }
320 }
321
322 struct SecondClass;
323 impl LockClass for SecondClass {
324 const ID: *mut core::ffi::c_void = core::ptr::null_mut();
325 }
326
327 struct ThirdClass;
328 impl LockClass for ThirdClass {
329 const ID: *mut core::ffi::c_void = core::ptr::null_mut();
330 }
331
332 #[test]
333 fn test_kcell_multi_lock() {
334 let cell = core::pin::pin!(KCell::<u32, (MyClass, SecondClass)>::new(10));
335 let cell: &KCell<u32, (MyClass, SecondClass)> = cell.as_ref().get_ref();
336 unsafe {
338 let mut token1 = LockToken::<MyClass>::new();
339 let mut token2 = LockToken::<SecondClass>::new();
340
341 assert_eq!(*cell.get(&token1), 10);
343 assert_eq!(*cell.get(&token2), 10);
344 assert_eq!(*cell.as_ptr(&token1), 10);
345 assert_eq!(*cell.as_ptr(&token2), 10);
346
347 *cell.get_mut(token1.join(&mut token2)) = 20;
349 assert_eq!(*cell.get(&token1), 20);
350
351 *cell.get_mut(token2.join(&mut token1)) = 30;
352 assert_eq!(*cell.get(&token2), 30);
353
354 *cell.as_mut_ptr(token1.join(&mut token2)) = 40;
356 assert_eq!(*cell.get(&token1), 40);
357
358 let mut pinned = cell.get_pinned_mut_locked(token2.join(&mut token1));
359 pinned.set(50);
360 assert_eq!(*cell.get(&token2), 50);
361 }
362
363 let cell3: KCell<u32, (MyClass, SecondClass, ThirdClass)> = KCell::new(100);
364 unsafe {
366 let mut t1 = LockToken::<MyClass>::new();
367 let mut t2 = LockToken::<SecondClass>::new();
368 let mut t3 = LockToken::<ThirdClass>::new();
369
370 assert_eq!(*cell3.get(&t1), 100);
371 assert_eq!(*cell3.get(&t2), 100);
372 assert_eq!(*cell3.get(&t3), 100);
373
374 *cell3.get_mut(t1.join(&mut t2).join(&mut t3)) = 200;
375 assert_eq!(*cell3.get(&t3), 200);
376 }
377 }
378}