rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benno Lossin <benno.lossin@proton.me>
To: Alice Ryhl <aliceryhl@google.com>,
	Miguel Ojeda <ojeda@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>
Cc: "Alex Gaynor" <alex.gaynor@gmail.com>,
	"Wedson Almeida Filho" <wedsonaf@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Andreas Hindborg" <a.hindborg@samsung.com>,
	"Marco Elver" <elver@google.com>,
	"Kees Cook" <keescook@chromium.org>, "Coly Li" <colyli@suse.de>,
	"Paolo Abeni" <pabeni@redhat.com>,
	"Pierre Gondois" <pierre.gondois@arm.com>,
	"Ingo Molnar" <mingo@kernel.org>,
	"Jakub Kicinski" <kuba@kernel.org>,
	"Wei Yang" <richard.weiyang@gmail.com>,
	"Matthew Wilcox" <willy@infradead.org>,
	linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org
Subject: Re: [PATCH 9/9] rust: list: add ListArcField
Date: Thu, 04 Apr 2024 15:47:49 +0000	[thread overview]
Message-ID: <86ac172a-4ad5-4cc5-844e-7b928d0765bd@proton.me> (raw)
In-Reply-To: <20240402-linked-list-v1-9-b1c59ba7ae3b@google.com>

On 02.04.24 14:17, Alice Ryhl wrote:
> One way to explain what `ListArc` does is that it controls exclusive
> access to the prev/next pointer field in a refcounted object. The
> feature of having a special reference to a refcounted object with
> exclusive access to specific fields is useful for other things, so
> provide a general utility for that.
> 
> This is used by Rust Binder to keep track of which processes have a
> reference to a given node. This involves an object for each process/node
> pair, that is referenced by both the process and the node. For some
> fields in this object, only the process's reference needs to access
> them (and it needs mutable access), so Binder uses a ListArc to give the
> process's reference exclusive access.

This pattern screams "field projection" :)

> 
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
>  rust/kernel/list.rs           |  3 ++
>  rust/kernel/list/arc_field.rs | 94 +++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 97 insertions(+)
> 
> diff --git a/rust/kernel/list.rs b/rust/kernel/list.rs
> index 68d03b100863..a59b35b67e9b 100644
> --- a/rust/kernel/list.rs
> +++ b/rust/kernel/list.rs
> @@ -23,6 +23,9 @@
>      impl_list_arc_safe, AtomicListArcTracker, ListArc, ListArcSafe, TryNewListArc,
>  };
> 
> +mod arc_field;
> +pub use self::arc_field::{define_list_arc_field_getter, ListArcField};
> +
>  /// A linked list.
>  ///
>  /// All elements in this linked list will be [`ListArc`] references to the value. Since a value can
> diff --git a/rust/kernel/list/arc_field.rs b/rust/kernel/list/arc_field.rs
> new file mode 100644
> index 000000000000..936fd97bc5ac
> --- /dev/null
> +++ b/rust/kernel/list/arc_field.rs
> @@ -0,0 +1,94 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +// Copyright (C) 2024 Google LLC.
> +
> +//! A field that is exclusively owned by a [`ListArc`].
> +//!
> +//! This can be used to have reference counted struct where one of the reference counted pointers
> +//! has exclusive access to a field of the struct.
> +//!
> +//! [`ListArc`]: crate::list::ListArc
> +
> +use core::cell::UnsafeCell;
> +
> +/// A field owned by a specific `ListArc`.

Missing doc link.

> +pub struct ListArcField<T, const ID: u64 = 0> {
> +    value: UnsafeCell<T>,
> +}
> +
> +// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.
> +unsafe impl<T: Send + Sync, const ID: u64> Send for ListArcField<T, ID> {}
> +// SAFETY: If the inner type is thread-safe, then it's also okay for `ListArc` to be thread-safe.
> +unsafe impl<T: Send + Sync, const ID: u64> Sync for ListArcField<T, ID> {}
> +
> +impl<T, const ID: u64> ListArcField<T, ID> {
> +    /// Creates a new `ListArcField`.
> +    pub fn new(value: T) -> Self {
> +        Self {
> +            value: UnsafeCell::new(value),
> +        }
> +    }
> +
> +    /// Access the value when we have exclusive access to the `ListArcField`.
> +    ///
> +    /// This allows access to the field using an `UniqueArc` instead of a `ListArc`.
> +    pub fn get_mut(&mut self) -> &mut T {
> +        self.value.get_mut()
> +    }
> +
> +    /// Unsafely assert that you have shared access to the `ListArc` for this field.
> +    ///
> +    /// # Safety
> +    ///
> +    /// The caller must have shared access to the `ListArc<ID>` containing the struct with this
> +    /// field for the duration of the returned reference.
> +    pub unsafe fn assert_ref(&self) -> &T {
> +        // SAFETY: The caller has shared access to the `ListArc`, so they also have shared access
> +        // to this field.
> +        unsafe { &*self.value.get() }
> +    }
> +
> +    /// Unsafely assert that you have mutable access to the `ListArc` for this field.
> +    ///
> +    /// # Safety
> +    ///
> +    /// The caller must have mutable access to the `ListArc<ID>` containing the struct with this
> +    /// field for the duration of the returned reference.
> +    #[allow(clippy::mut_from_ref)]
> +    pub unsafe fn assert_mut(&self) -> &mut T {
> +        // SAFETY: The caller has exclusive access to the `ListArc`, so they also have exclusive
> +        // access to this field.
> +        unsafe { &mut *self.value.get() }
> +    }
> +}
> +
> +/// Defines.

Missing docs.

-- 
Cheers,
Benno

> +#[macro_export]
> +macro_rules! define_list_arc_field_getter {
> +    ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }
> +     $($rest:tt)*
> +    ) => {
> +        $pub fn $name<'a>(self: &'a $crate::list::ListArc<Self $(, $id)?>) -> &'a $typ {
> +            let field = &(&**self).$field;
> +            // SAFETY: We have a shared reference to the `ListArc`.
> +            unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_ref(field) }
> +        }
> +
> +        $crate::list::define_list_arc_field_getter!($($rest)*);
> +    };
> +
> +    ($pub:vis fn $name:ident(&mut self $(<$id:tt>)?) -> &mut $typ:ty { $field:ident }
> +     $($rest:tt)*
> +    ) => {
> +        $pub fn $name<'a>(self: &'a mut $crate::list::ListArc<Self $(, $id)?>) -> &'a mut $typ {
> +            let field = &(&**self).$field;
> +            // SAFETY: We have a mutable reference to the `ListArc`.
> +            unsafe { $crate::list::ListArcField::<$typ $(, $id)?>::assert_mut(field) }
> +        }
> +
> +        $crate::list::define_list_arc_field_getter!($($rest)*);
> +    };
> +
> +    () => {};
> +}
> +pub use define_list_arc_field_getter;
> 
> --
> 2.44.0.478.gd926399ef9-goog
> 


      reply	other threads:[~2024-04-04 15:48 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-02 12:16 [PATCH 0/9] Add Rust linked list for reference counted values Alice Ryhl
2024-04-02 12:16 ` [PATCH 1/9] rust: list: add ListArc Alice Ryhl
2024-04-03 15:51   ` Benno Lossin
2024-04-04 14:00     ` Alice Ryhl
2024-05-03 14:36       ` Alice Ryhl
2024-05-04 15:50         ` Benno Lossin
2024-04-03 17:18   ` Kane York
2024-04-02 12:16 ` [PATCH 2/9] rust: list: add tracking for ListArc Alice Ryhl
2024-04-03 15:52   ` Benno Lossin
2024-04-04 14:14     ` Alice Ryhl
2024-04-04 14:41       ` Benno Lossin
2024-04-02 12:17 ` [PATCH 3/9] rust: list: add struct with prev/next pointers Alice Ryhl
2024-04-03 15:57   ` Benno Lossin
2024-04-04 14:03     ` Alice Ryhl
2024-04-04 14:05       ` Benno Lossin
2024-04-05  9:47   ` Benno Lossin
2024-04-08  7:57     ` Alice Ryhl
2024-04-02 12:17 ` [PATCH 4/9] rust: list: add macro for implementing ListItem Alice Ryhl
2024-04-03 10:42   ` Benno Lossin
2024-04-02 12:17 ` [PATCH 5/9] rust: list: add List Alice Ryhl
2024-04-04 14:03   ` Benno Lossin
2024-04-04 14:12     ` Alice Ryhl
2024-04-04 14:51       ` Benno Lossin
2024-04-08  8:04         ` Alice Ryhl
2024-04-08  8:51           ` Benno Lossin
2024-04-02 12:17 ` [PATCH 6/9] rust: list: add iterators Alice Ryhl
2024-04-04 14:36   ` Benno Lossin
2024-04-04 14:41     ` Alice Ryhl
2024-04-04 14:52       ` Benno Lossin
2024-04-08  8:00         ` Alice Ryhl
2024-04-02 12:17 ` [PATCH 7/9] rust: list: add cursor Alice Ryhl
2024-04-03 12:19   ` Benno Lossin
2024-04-03 12:49     ` Alice Ryhl
2024-04-04 13:28       ` Benno Lossin
2024-04-04 13:40         ` Alice Ryhl
2024-04-02 12:17 ` [PATCH 8/9] rust: list: support heterogeneous lists Alice Ryhl
2024-04-04 15:35   ` Benno Lossin
2024-04-08  7:59     ` Alice Ryhl
2024-04-02 12:17 ` [PATCH 9/9] rust: list: add ListArcField Alice Ryhl
2024-04-04 15:47   ` Benno Lossin [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86ac172a-4ad5-4cc5-844e-7b928d0765bd@proton.me \
    --to=benno.lossin@proton.me \
    --cc=a.hindborg@samsung.com \
    --cc=akpm@linux-foundation.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=colyli@suse.de \
    --cc=elver@google.com \
    --cc=gary@garyguo.net \
    --cc=keescook@chromium.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=pabeni@redhat.com \
    --cc=pierre.gondois@arm.com \
    --cc=richard.weiyang@gmail.com \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=wedsonaf@gmail.com \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).