2023-04-03 10:19:00

by Asahi Lina

[permalink] [raw]
Subject: [PATCH v2 0/2] rust: sync: Arc: Any downcasting and assume_init()

Hi everyone,

This short series is part of the set of dependencies for the drm/asahi
Apple M1/M2 GPU driver.

The two patches simply add two missing features to the kernel Arc
implementation which are present in the Rust std version: `Any`
downcasting and `assume_init()`.

Signed-off-by: Asahi Lina <[email protected]>
---
Changes in v2:
- #1: Moved the new function to a separate file, to keep the licensing
clearer.
- #2: Replaced the safety comment with Benno's, from his pin-init series
(we both wrote the same patch).
- Link to v1: https://lore.kernel.org/r/[email protected]

---
Asahi Lina (2):
rust: sync: arc: Implement Arc<dyn Any + Send + Sync>::downcast()
rust: sync: arc: Add UniqueArc<MaybeUninit<T>::assume_init()
rust/kernel/sync/arc.rs | 13 +++++++++++++
rust/kernel/sync/arc/std_vendor.rs | 28 ++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)
---
base-commit: fe15c26ee26efa11741a7b632e9f23b01aca4cc6
change-id: 20230224-rust-arc-ba3c26ed4e6a

Thank you,
~~ Lina


2023-04-03 10:19:14

by Asahi Lina

[permalink] [raw]
Subject: [PATCH v2 1/2] rust: sync: arc: Implement Arc<dyn Any + Send + Sync>::downcast()

This mirrors the standard library's alloc::sync::Arc::downcast().

Based on the Rust standard library implementation, ver 1.62.0,
licensed under "Apache-2.0 OR MIT", from:

https://github.com/rust-lang/rust/tree/1.62.0/library/alloc/src

For copyright details, please see:

https://github.com/rust-lang/rust/blob/1.62.0/COPYRIGHT

Reviewed-by: Martin Rodriguez Reboredo <[email protected]>
Reviewed-by: Andreas Hindborg <[email protected]>
Reviewed-by: Vincenzo Palazzo <[email protected]>
Reviewed-by: Gary Guo <[email protected]>
Signed-off-by: Asahi Lina <[email protected]>
---
rust/kernel/sync/arc.rs | 2 ++
rust/kernel/sync/arc/std_vendor.rs | 28 ++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)

diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index f2f1c83d72ba..b904ed898d3a 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -522,3 +522,5 @@ impl<T: ?Sized> DerefMut for UniqueArc<T> {
unsafe { &mut self.inner.ptr.as_mut().data }
}
}
+
+mod std_vendor;
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)
+ }
+ }
+}

--
2.40.0

2023-04-03 10:19:29

by Asahi Lina

[permalink] [raw]
Subject: [PATCH v2 2/2] rust: sync: arc: Add UniqueArc<MaybeUninit<T>::assume_init()

We can already create `UniqueArc<MaybeUninit<T>>` instances with
`UniqueArc::try_new_uninit()` and write to them with `write()`. Add
the missing unsafe `assume_init()` function to promote it to
`UniqueArc<T>`, so users can do piece-wise initialization of the
contents instead of doing it all at once as long as they keep the
invariants (the same requirements as `MaybeUninit::assume_init()`).

This mirrors the std `Arc::assume_init()` function. In the kernel,
since we have `UniqueArc`, arguably this only belongs there since most
use cases will initialize it immediately after creating it, before
demoting it to `Arc` to share it.

Co-authored-by: Benno Lossin <[email protected]>
Signed-off-by: Benno Lossin <[email protected]>
Signed-off-by: Asahi Lina <[email protected]>
---
rust/kernel/sync/arc.rs | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index b904ed898d3a..b664b41e473d 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -489,6 +489,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 have just written the contents fully.
+ 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

--
2.40.0

2023-04-03 15:35:42

by Gary Guo

[permalink] [raw]
Subject: Re: [PATCH v2 2/2] rust: sync: arc: Add UniqueArc<MaybeUninit<T>::assume_init()

On Mon, 03 Apr 2023 19:01:12 +0900
Asahi Lina <[email protected]> wrote:

> We can already create `UniqueArc<MaybeUninit<T>>` instances with
> `UniqueArc::try_new_uninit()` and write to them with `write()`. Add
> the missing unsafe `assume_init()` function to promote it to
> `UniqueArc<T>`, so users can do piece-wise initialization of the
> contents instead of doing it all at once as long as they keep the
> invariants (the same requirements as `MaybeUninit::assume_init()`).
>
> This mirrors the std `Arc::assume_init()` function. In the kernel,
> since we have `UniqueArc`, arguably this only belongs there since most
> use cases will initialize it immediately after creating it, before
> demoting it to `Arc` to share it.
>
> Co-authored-by: Benno Lossin <[email protected]>
> Signed-off-by: Benno Lossin <[email protected]>
> Signed-off-by: Asahi Lina <[email protected]>

Reviewed-by: Gary Guo <[email protected]>

> ---
> rust/kernel/sync/arc.rs | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
> index b904ed898d3a..b664b41e473d 100644
> --- a/rust/kernel/sync/arc.rs
> +++ b/rust/kernel/sync/arc.rs
> @@ -489,6 +489,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 have just written the contents fully.
> + 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
>

2023-04-10 03:54:23

by Miguel Ojeda

[permalink] [raw]
Subject: Re: [PATCH v2 0/2] rust: sync: Arc: Any downcasting and assume_init()

On Mon, Apr 3, 2023 at 12:01 PM Asahi Lina <[email protected]> wrote:
>
> Hi everyone,
>
> This short series is part of the set of dependencies for the drm/asahi
> Apple M1/M2 GPU driver.
>
> The two patches simply add two missing features to the kernel Arc
> implementation which are present in the Rust std version: `Any`
> downcasting and `assume_init()`.

Applied to `rust-next`. Thanks!

Cheers,
Miguel