Skip to content

Commit c69fc2d

Browse files
asahilinaFabo
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 <[email protected]> (cherry picked from commit 05abc1d) Signed-off-by: Fabien Parent <[email protected]>
1 parent ce41d4c commit c69fc2d

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

rust/kernel/sync/lock.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::{
1111
init::PinInit,
1212
pin_init,
1313
str::CStr,
14+
try_pin_init,
1415
types::{NotThreadSafe, Opaque, ScopeGuard},
1516
};
1617
use core::{cell::UnsafeCell, marker::PhantomPinned};
@@ -100,6 +101,7 @@ pub struct Lock<T: ?Sized, B: Backend> {
100101
_pin: PhantomPinned,
101102

102103
/// The data protected by the lock.
104+
#[pin]
103105
pub(crate) data: UnsafeCell<T>,
104106
}
105107

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

128155
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
@@ -19,6 +19,19 @@ macro_rules! new_mutex {
1919
}
2020
pub use new_mutex;
2121

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

0 commit comments

Comments
 (0)