From: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
To: Wedson Almeida Filho <wedsonaf@gmail.com>,
rust-for-linux@vger.kernel.org
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
linux-kernel@vger.kernel.org,
"Wedson Almeida Filho" <walmeida@microsoft.com>
Subject: Re: [PATCH v3 08/13] rust: introduce `ARef`
Date: Sun, 9 Apr 2023 13:48:36 -0300 [thread overview]
Message-ID: <35f8586b-a462-a482-d892-e31d194b90f4@gmail.com> (raw)
In-Reply-To: <20230408075340.25237-8-wedsonaf@gmail.com>
On 4/8/23 04:53, Wedson Almeida Filho wrote:
> From: Wedson Almeida Filho <walmeida@microsoft.com>
>
> This is an owned reference to an object that is always ref-counted. This
> is meant to be used in wrappers for C types that have their own ref
> counting functions, for example, tasks, files, inodes, dentries, etc.
>
> Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com>
> ---
> v1 -> v2: No changes
> v2 -> v3: No changes
>
> rust/kernel/types.rs | 107 +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 107 insertions(+)
>
> diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
> index 3a46ec1a00cd..73709ce1f0a1 100644
> --- a/rust/kernel/types.rs
> +++ b/rust/kernel/types.rs
> @@ -6,8 +6,10 @@ use crate::init::{self, PinInit};
> use alloc::boxed::Box;
> use core::{
> cell::UnsafeCell,
> + marker::PhantomData,
> mem::MaybeUninit,
> ops::{Deref, DerefMut},
> + ptr::NonNull,
> };
>
> /// Used to transfer ownership to and from foreign (non-Rust) languages.
> @@ -268,6 +270,111 @@ impl<T> Opaque<T> {
> }
> }
>
> +/// Types that are _always_ reference counted.
> +///
> +/// It allows such types to define their own custom ref increment and decrement functions.
> +/// Additionally, it allows users to convert from a shared reference `&T` to an owned reference
> +/// [`ARef<T>`].
> +///
> +/// This is usually implemented by wrappers to existing structures on the C side of the code. For
> +/// Rust code, the recommendation is to use [`Arc`](crate::sync::Arc) to create reference-counted
> +/// instances of a type.
> +///
> +/// # Safety
> +///
> +/// Implementers must ensure that increments to the reference count keep the object alive in memory
> +/// at least until matching decrements are performed.
> +///
> +/// Implementers must also ensure that all instances are reference-counted. (Otherwise they
> +/// won't be able to honour the requirement that [`AlwaysRefCounted::inc_ref`] keep the object
> +/// alive.)
> +pub unsafe trait AlwaysRefCounted {
> + /// Increments the reference count on the object.
> + fn inc_ref(&self);
> +
> + /// Decrements the reference count on the object.
> + ///
> + /// Frees the object when the count reaches zero.
> + ///
> + /// # Safety
> + ///
> + /// Callers must ensure that there was a previous matching increment to the reference count,
> + /// and that the object is no longer used after its reference count is decremented (as it may
> + /// result in the object being freed), unless the caller owns another increment on the refcount
> + /// (e.g., it calls [`AlwaysRefCounted::inc_ref`] twice, then calls
> + /// [`AlwaysRefCounted::dec_ref`] once).
> + unsafe fn dec_ref(obj: NonNull<Self>);
> +}
> +
> +/// An owned reference to an always-reference-counted object.
> +///
> +/// The object's reference count is automatically decremented when an instance of [`ARef`] is
> +/// dropped. It is also automatically incremented when a new instance is created via
> +/// [`ARef::clone`].
> +///
> +/// # Invariants
> +///
> +/// The pointer stored in `ptr` is non-null and valid for the lifetime of the [`ARef`] instance. In
> +/// particular, the [`ARef`] instance owns an increment on the underlying object's reference count.
> +pub struct ARef<T: AlwaysRefCounted> {
> + ptr: NonNull<T>,
> + _p: PhantomData<T>,
> +}
> +
> +impl<T: AlwaysRefCounted> ARef<T> {
> + /// Creates a new instance of [`ARef`].
> + ///
> + /// It takes over an increment of the reference count on the underlying object.
> + ///
> + /// # Safety
> + ///
> + /// Callers must ensure that the reference count was incremented at least once, and that they
> + /// are properly relinquishing one increment. That is, if there is only one increment, callers
> + /// must not use the underlying object anymore -- it is only safe to do so via the newly
> + /// created [`ARef`].
> + pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
> + // INVARIANT: The safety requirements guarantee that the new instance now owns the
> + // increment on the refcount.
> + Self {
> + ptr,
> + _p: PhantomData,
> + }
> + }
> +}
> +
> +impl<T: AlwaysRefCounted> Clone for ARef<T> {
> + fn clone(&self) -> Self {
> + self.inc_ref();
> + // SAFETY: We just incremented the refcount above.
> + unsafe { Self::from_raw(self.ptr) }
> + }
> +}
> +
> +impl<T: AlwaysRefCounted> Deref for ARef<T> {
> + type Target = T;
> +
> + fn deref(&self) -> &Self::Target {
> + // SAFETY: The type invariants guarantee that the object is valid.
> + unsafe { self.ptr.as_ref() }
> + }
> +}
> +
> +impl<T: AlwaysRefCounted> From<&T> for ARef<T> {
> + fn from(b: &T) -> Self {
> + b.inc_ref();
> + // SAFETY: We just incremented the refcount above.
> + unsafe { Self::from_raw(NonNull::from(b)) }
> + }
> +}
> +
> +impl<T: AlwaysRefCounted> Drop for ARef<T> {
> + fn drop(&mut self) {
> + // SAFETY: The type invariants guarantee that the `ARef` owns the reference we're about to
> + // decrement.
> + unsafe { T::dec_ref(self.ptr) };
> + }
> +}
> +
> /// A sum type that always holds either a value of type `L` or `R`.
> pub enum Either<L, R> {
> /// Constructs an instance of [`Either`] containing a value of type `L`.
Reviewed-by: Martin Rodriguez Reboredo <yakoyoku@gmail.com>
next prev parent reply other threads:[~2023-04-09 16:49 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-08 7:53 [PATCH v3 01/13] rust: sync: introduce `LockClassKey` Wedson Almeida Filho
2023-04-08 7:53 ` [PATCH v3 02/13] rust: sync: introduce `Lock` and `Guard` Wedson Almeida Filho
2023-04-09 16:47 ` Martin Rodriguez Reboredo
2023-04-11 3:01 ` Wedson Almeida Filho
2023-04-08 7:53 ` [PATCH v3 03/13] rust: lock: introduce `Mutex` Wedson Almeida Filho
2023-04-09 16:47 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 04/13] locking/spinlock: introduce spin_lock_init_with_key Wedson Almeida Filho
2023-04-09 16:47 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 05/13] rust: lock: introduce `SpinLock` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 06/13] rust: lock: add support for `Lock::lock_irqsave` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 07/13] rust: lock: implement `IrqSaveBackend` for `SpinLock` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 08/13] rust: introduce `ARef` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo [this message]
2023-04-08 7:53 ` [PATCH v3 09/13] rust: add basic `Task` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 10/13] rust: introduce `current` Wedson Almeida Filho
2023-04-09 16:48 ` Martin Rodriguez Reboredo
2023-04-10 18:04 ` Benno Lossin
2023-04-11 3:08 ` Wedson Almeida Filho
2023-04-08 7:53 ` [PATCH v3 11/13] rust: lock: add `Guard::do_unlocked` Wedson Almeida Filho
2023-04-09 16:49 ` Martin Rodriguez Reboredo
2023-04-08 7:53 ` [PATCH v3 12/13] rust: sync: introduce `CondVar` Wedson Almeida Filho
2023-04-09 16:49 ` Martin Rodriguez Reboredo
2023-04-11 2:59 ` Wedson Almeida Filho
2023-04-08 7:53 ` [PATCH v3 13/13] rust: sync: introduce `LockedBy` Wedson Almeida Filho
2023-04-09 16:49 ` Martin Rodriguez Reboredo
2023-04-10 17:46 ` Boqun Feng
2023-04-10 18:13 ` Boqun Feng
2023-04-10 19:52 ` Benno Lossin
2023-04-11 2:57 ` Wedson Almeida Filho
2023-04-09 16:46 ` [PATCH v3 01/13] rust: sync: introduce `LockClassKey` Martin Rodriguez Reboredo
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=35f8586b-a462-a482-d892-e31d194b90f4@gmail.com \
--to=yakoyoku@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=walmeida@microsoft.com \
--cc=wedsonaf@gmail.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.