Skip to content

Commit 885da21

Browse files
hoshinolinajannau
authored andcommitted
rust: kernel: lock: Add Lock::pin_init()
This allows initializing a lock using pin_init!(), instead of requiring the inner data to be passed through the stack. Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent a49ebe0 commit 885da21

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

rust/kernel/sync/lock.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
init::PinInit,
1111
pin_init,
1212
str::CStr,
13+
try_pin_init,
1314
types::{NotThreadSafe, Opaque, ScopeGuard},
1415
};
1516
use core::{cell::UnsafeCell, marker::PhantomPinned};
@@ -109,6 +110,7 @@ pub struct Lock<T: ?Sized, B: Backend> {
109110
_pin: PhantomPinned,
110111

111112
/// The data protected by the lock.
113+
#[pin]
112114
pub(crate) data: UnsafeCell<T>,
113115
}
114116

@@ -132,6 +134,31 @@ impl<T, B: Backend> Lock<T, B> {
132134
}),
133135
})
134136
}
137+
138+
/// Constructs a new lock initialiser taking an initialiser.
139+
pub fn pin_init<E>(
140+
t: impl PinInit<T, E>,
141+
name: &'static CStr,
142+
key: &'static LockClassKey,
143+
) -> impl PinInit<Self, E>
144+
where
145+
E: core::convert::From<core::convert::Infallible>,
146+
{
147+
try_pin_init!(Self {
148+
// SAFETY: We are just forwarding the initialization across a
149+
// cast away from UnsafeCell, so the pin_init_from_closure and
150+
// __pinned_init() requirements are in sync.
151+
data <- unsafe { crate::init::pin_init_from_closure(move |slot: *mut UnsafeCell<T>| {
152+
t.__pinned_init(slot as *mut T)
153+
})},
154+
_pin: PhantomPinned,
155+
// SAFETY: `slot` is valid while the closure is called and both `name` and `key` have
156+
// static lifetimes so they live indefinitely.
157+
state <- Opaque::ffi_init(|slot| unsafe {
158+
B::init(slot, name.as_char_ptr(), key.as_ptr())
159+
}),
160+
}? E)
161+
}
135162
}
136163

137164
impl<T: ?Sized, B: Backend> Lock<T, B> {

rust/kernel/sync/lock/mutex.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ macro_rules! new_mutex {
1717
}
1818
pub use new_mutex;
1919

20+
/// Creates a [`Mutex`] initialiser with the given name and a newly-created lock class,
21+
/// given an initialiser for the inner type.
22+
///
23+
/// It uses the name if one is given, otherwise it generates one based on the file name and line
24+
/// number.
25+
#[macro_export]
26+
macro_rules! new_mutex_pinned {
27+
($inner:expr $(, $name:literal)? $(,)?) => {
28+
$crate::sync::Mutex::pin_init(
29+
$inner, $crate::optional_name!($($name)?), $crate::static_lock_class!())
30+
};
31+
}
32+
2033
/// A mutual exclusion primitive.
2134
///
2235
/// Exposes the kernel's [`struct mutex`]. When multiple threads attempt to lock the same mutex,

0 commit comments

Comments
 (0)