mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 02:21:39 -04:00
rust: pin-init: add raw_init and raw_try_init and recommend over __init
The `__init` method is not designed to be a public API (existence of "__" is a hint for this); but currently there is no other API that allows raw initialization on pointers. Add `raw_init` and `raw_try_init` and recommend people to use this instead if raw pointer initialization is needed. Link: https://patch.msgid.link/20260729-merge-init-v2-3-26adf47109e7@garyguo.net [ Renamed from `ptr_[try_]init` to `raw_[try_]init`. - Gary ] Reviewed-by: Benno Lossin <lossin@kernel.org> Signed-off-by: Gary Guo <gary@garyguo.net>
This commit is contained in:
@@ -59,7 +59,7 @@ fn deref(&self) -> &Self::Target {
|
||||
println!("doing init");
|
||||
let ptr = self.cell.get().cast::<T>();
|
||||
match self.init.take() {
|
||||
Some(f) => unsafe { f.__init(ptr).unwrap() },
|
||||
Some(f) => unsafe { pin_init::raw_init(ptr, f) },
|
||||
None => unsafe { core::hint::unreachable_unchecked() },
|
||||
}
|
||||
self.present.set(true);
|
||||
@@ -74,7 +74,8 @@ unsafe impl PinInit<CMutex<usize>> for CountInit {
|
||||
unsafe fn __init(self, slot: *mut CMutex<usize>) -> Result<(), core::convert::Infallible> {
|
||||
let init = CMutex::new(0);
|
||||
std::thread::sleep(std::time::Duration::from_millis(1000));
|
||||
unsafe { init.__init(slot) }
|
||||
unsafe { pin_init::raw_init(slot, init) };
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -917,7 +917,7 @@ pub unsafe trait PinInit<T: ?Sized, E = Infallible>: Sized {
|
||||
///
|
||||
/// Same as `__init`.
|
||||
#[inline(always)]
|
||||
#[cfg_attr(not(kernel), deprecated = "use `__init` instead")]
|
||||
#[cfg_attr(not(kernel), deprecated = "use `raw_try_init` instead")]
|
||||
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
|
||||
// SAFETY: Per safety requirement.
|
||||
unsafe { self.__init(slot) }
|
||||
@@ -925,6 +925,8 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
|
||||
|
||||
/// Initializes `slot`.
|
||||
///
|
||||
/// It is not recommended to call this directly. Use [`raw_init`] or [`raw_try_init`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `slot` is a valid pointer to uninitialized memory.
|
||||
@@ -960,6 +962,34 @@ fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes `slot` with an initializer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `slot` is a valid pointer to uninitialized memory.
|
||||
/// - `slot` will not move until it is dropped, i.e. it will be pinned.
|
||||
/// If `init` implements `Init<T, E>`, this requirement is cancelled and it may be moved.
|
||||
#[inline(always)]
|
||||
pub unsafe fn raw_init<T>(slot: *mut T, init: impl PinInit<T>) {
|
||||
// SAFETY: Per safety requirement.
|
||||
unsafe { init.__init(slot).unwrap_or_else(|e| match e {}) }
|
||||
}
|
||||
|
||||
/// Fallibly initializes `slot` with an initializer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - `slot` is a valid pointer to uninitialized memory.
|
||||
/// - the caller does not touch `slot` when `Err` is returned, they are only permitted to
|
||||
/// deallocate.
|
||||
/// - `slot` will not move until it is dropped, i.e. it will be pinned.
|
||||
/// If `init` implements `Init<T, E>`, this requirement is cancelled and it may be moved.
|
||||
#[inline(always)]
|
||||
pub unsafe fn raw_try_init<T, E>(slot: *mut T, init: impl PinInit<T, E>) -> Result<(), E> {
|
||||
// SAFETY: Per safety requirement.
|
||||
unsafe { init.__init(slot) }
|
||||
}
|
||||
|
||||
/// An initializer returned by [`PinInit::pin_chain`].
|
||||
pub struct ChainPinInit<I, F, T: ?Sized, E>(I, F, __internal::PhantomInvariant<(E, T)>);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user