diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2023-04-11 15:21:54 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2023-04-11 15:21:54 +1000 |
commit | fd4ce8b2eada0466b24ccaf4bb002876c4e4656b (patch) | |
tree | c21353eb445df230d4e7010c801c66f92f98844a /rust/kernel/sync | |
parent | 30abc354583145a63a068d853e294aa1a0590739 (diff) | |
parent | 2d0dec625d872a41632a68fce2e69453ed87df91 (diff) | |
download | linux-next-fd4ce8b2eada0466b24ccaf4bb002876c4e4656b.tar.gz |
Merge branch 'rust-next' of https://github.com/Rust-for-Linux/linux.git
Diffstat (limited to 'rust/kernel/sync')
-rw-r--r-- | rust/kernel/sync/arc.rs | 108 | ||||
-rw-r--r-- | rust/kernel/sync/arc/std_vendor.rs | 28 |
2 files changed, 130 insertions, 6 deletions
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs index f2f1c83d72ba..e6d206242465 100644 --- a/rust/kernel/sync/arc.rs +++ b/rust/kernel/sync/arc.rs @@ -17,17 +17,24 @@ use crate::{ bindings, - error::Result, + error::{self, Error}, + init::{self, InPlaceInit, Init, PinInit}, + try_init, types::{ForeignOwnable, Opaque}, }; use alloc::boxed::Box; use core::{ + alloc::AllocError, + fmt, marker::{PhantomData, Unsize}, mem::{ManuallyDrop, MaybeUninit}, ops::{Deref, DerefMut}, pin::Pin, ptr::NonNull, }; +use macros::pin_data; + +mod std_vendor; /// A reference-counted pointer to an instance of `T`. /// @@ -120,6 +127,7 @@ pub struct Arc<T: ?Sized> { _p: PhantomData<ArcInner<T>>, } +#[pin_data] #[repr(C)] struct ArcInner<T: ?Sized> { refcount: Opaque<bindings::refcount_t>, @@ -149,7 +157,7 @@ unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> {} impl<T> Arc<T> { /// Constructs a new reference counted instance of `T`. - pub fn try_new(contents: T) -> Result<Self> { + pub fn try_new(contents: T) -> Result<Self, AllocError> { // INVARIANT: The refcount is initialised to a non-zero value. let value = ArcInner { // SAFETY: There are no safety requirements for this FFI call. @@ -163,6 +171,28 @@ impl<T> Arc<T> { // `Arc` object. Ok(unsafe { Self::from_inner(Box::leak(inner).into()) }) } + + /// Use the given initializer to in-place initialize a `T`. + /// + /// If `T: !Unpin` it will not be able to move afterwards. + #[inline] + pub fn pin_init<E>(init: impl PinInit<T, E>) -> error::Result<Self> + where + Error: From<E>, + { + UniqueArc::pin_init(init).map(|u| u.into()) + } + + /// Use the given initializer to in-place initialize a `T`. + /// + /// This is equivalent to [`pin_init`], since an [`Arc`] is always pinned. + #[inline] + pub fn init<E>(init: impl Init<T, E>) -> error::Result<Self> + where + Error: From<E>, + { + UniqueArc::init(init).map(|u| u.into()) + } } impl<T: ?Sized> Arc<T> { @@ -469,7 +499,7 @@ pub struct UniqueArc<T: ?Sized> { impl<T> UniqueArc<T> { /// Tries to allocate a new [`UniqueArc`] instance. - pub fn try_new(value: T) -> Result<Self> { + pub fn try_new(value: T) -> Result<Self, AllocError> { Ok(Self { // INVARIANT: The newly-created object has a ref-count of 1. inner: Arc::try_new(value)?, @@ -477,10 +507,17 @@ impl<T> UniqueArc<T> { } /// Tries to allocate a new [`UniqueArc`] instance whose contents are not initialised yet. - pub fn try_new_uninit() -> Result<UniqueArc<MaybeUninit<T>>> { - Ok(UniqueArc::<MaybeUninit<T>> { + pub fn try_new_uninit() -> Result<UniqueArc<MaybeUninit<T>>, AllocError> { + // INVARIANT: The refcount is initialised to a non-zero value. + let inner = Box::try_init::<AllocError>(try_init!(ArcInner { + // SAFETY: There are no safety requirements for this FFI call. + refcount: Opaque::new(unsafe { bindings::REFCOUNT_INIT(1) }), + data <- init::uninit::<T, AllocError>(), + }? AllocError))?; + Ok(UniqueArc { // INVARIANT: The newly-created object has a ref-count of 1. - inner: Arc::try_new(MaybeUninit::uninit())?, + // SAFETY: The pointer from the `Box` is valid. + inner: unsafe { Arc::from_inner(Box::leak(inner).into()) }, }) } } @@ -489,6 +526,17 @@ impl<T> UniqueArc<MaybeUninit<T>> { /// Converts a `UniqueArc<MaybeUninit<T>>` into a `UniqueArc<T>` by writing a value into it. pub fn write(mut self, value: T) -> UniqueArc<T> { self.deref_mut().write(value); + // SAFETY: We just wrote the value to be initialized. + unsafe { self.assume_init() } + } + + /// Unsafely assume that `self` is initialized. + /// + /// # Safety + /// + /// The caller guarantees that the value behind this pointer has been initialized. It is + /// *immediate* UB to call this when the value is not initialized. + pub unsafe fn assume_init(self) -> UniqueArc<T> { let inner = ManuallyDrop::new(self).inner.ptr; UniqueArc { // SAFETY: The new `Arc` is taking over `ptr` from `self.inner` (which won't be @@ -496,6 +544,30 @@ impl<T> UniqueArc<MaybeUninit<T>> { inner: unsafe { Arc::from_inner(inner.cast()) }, } } + + /// Initialize `self` using the given initializer. + pub fn init_with<E>(mut self, init: impl Init<T, E>) -> core::result::Result<UniqueArc<T>, E> { + // SAFETY: The supplied pointer is valid for initialization. + match unsafe { init.__init(self.as_mut_ptr()) } { + // SAFETY: Initialization completed successfully. + Ok(()) => Ok(unsafe { self.assume_init() }), + Err(err) => Err(err), + } + } + + /// Pin-initialize `self` using the given pin-initializer. + pub fn pin_init_with<E>( + mut self, + init: impl PinInit<T, E>, + ) -> core::result::Result<Pin<UniqueArc<T>>, E> { + // SAFETY: The supplied pointer is valid for initialization and we will later pin the value + // to ensure it does not move. + match unsafe { init.__pinned_init(self.as_mut_ptr()) } { + // SAFETY: Initialization completed successfully. + Ok(()) => Ok(unsafe { self.assume_init() }.into()), + Err(err) => Err(err), + } + } } impl<T: ?Sized> From<UniqueArc<T>> for Pin<UniqueArc<T>> { @@ -522,3 +594,27 @@ impl<T: ?Sized> DerefMut for UniqueArc<T> { unsafe { &mut self.inner.ptr.as_mut().data } } } + +impl<T: fmt::Display + ?Sized> fmt::Display for UniqueArc<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.deref(), f) + } +} + +impl<T: fmt::Display + ?Sized> fmt::Display for Arc<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.deref(), f) + } +} + +impl<T: fmt::Debug + ?Sized> fmt::Debug for UniqueArc<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.deref(), f) + } +} + +impl<T: fmt::Debug + ?Sized> fmt::Debug for Arc<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.deref(), f) + } +} diff --git a/rust/kernel/sync/arc/std_vendor.rs b/rust/kernel/sync/arc/std_vendor.rs new file mode 100644 index 000000000000..a66a0c2831b3 --- /dev/null +++ b/rust/kernel/sync/arc/std_vendor.rs @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 OR MIT + +//! The contents of this file come from the Rust standard library, hosted in +//! the <https://github.com/rust-lang/rust> repository, licensed under +//! "Apache-2.0 OR MIT" and adapted for kernel use. For copyright details, +//! see <https://github.com/rust-lang/rust/blob/master/COPYRIGHT>. + +use crate::sync::{arc::ArcInner, Arc}; +use core::any::Any; + +impl Arc<dyn Any + Send + Sync> { + /// Attempt to downcast the `Arc<dyn Any + Send + Sync>` to a concrete type. + pub fn downcast<T>(self) -> core::result::Result<Arc<T>, Self> + where + T: Any + Send + Sync, + { + if (*self).is::<T>() { + // SAFETY: We have just checked that the type is correct, so we can cast the pointer. + unsafe { + let ptr = self.ptr.cast::<ArcInner<T>>(); + core::mem::forget(self); + Ok(Arc::from_inner(ptr)) + } + } else { + Err(self) + } + } +} |