From: Danilo Krummrich <dakr@kernel.org>
To: Alexandre Courbot <acourbot@nvidia.com>
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>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] rust/revocable: add try_with() convenience method
Date: Thu, 13 Mar 2025 15:37:23 +0100 [thread overview]
Message-ID: <Z9Lto6tbWS0kR6gK@pollux> (raw)
In-Reply-To: <20250313-try_with-v1-1-adcae7ed98a9@nvidia.com>
Hi Alex,
Thanks for looking into this!
On Thu, Mar 13, 2025 at 09:40:59PM +0900, Alexandre Courbot wrote:
> Revocable::try_access() returns a guard through which the wrapped object
> can be accessed. Code that can sleep is not allowed while the guard is
> held ; thus, it is common that the caller will explicitly need to drop
> it before running sleepable code, e.g:
>
> let b = bar.try_access()?;
> let reg = b.readl(...);
>
> // Don't forget this or things could go wrong!
> drop(b);
>
> something_that_might_sleep();
>
> let b = bar.try_access()?;
> let reg2 = b.readl(...);
Ideally, we get klint to protect us against those kind of mistakes too.
> This is arguably error-prone. try_with() and try_with_ok() provides an
> arguably safer alternative, by taking a closure that is run while the
> guard is held, and by dropping the guard automatically after the closure
> completes. This way, code can be organized more clearly around the
> critical sections and the risk is forgetting to release the guard when
> needed is considerably reduced:
>
> let reg = bar.try_with_ok(|b| b.readl(...))?;
>
> something_that_might_sleep();
>
> let reg2 = bar.try_with_ok(|b| b.readl(...))?;
However, that's much more convenient and a great improvement.
Feel free to add
Acked-by: Danilo Krummrich <dakr@kernel.org>
>
> Unlike try_access() which returns an Option, try_with() and
> try_with_ok() return Err(ENXIO) if the object cannot be acquired. The
> Option returned by try_access() is typically converted to an error in
> practice, so this saves one step for the caller.
>
> try_with() requires the callback itself to return a Result that is
> passed to the caller. try_with_ok() accepts a callback that never fails.
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Since I proposed something like that in one of the nova threads (and in Zulip),
feel free to also add
Suggested-by: Danilo Krummrich <dakr@kernel.org>
> ---
> This is a feature I found useful to have while writing Nova driver code
> that accessed registers alongside other operations. I would find myself
> quite confused about whether the guard was held or dropped at a given
> point of the code, and it felt like walking through a minefield ; this
> pattern makes things safer and easier to read IMHO.
> ---
> rust/kernel/revocable.rs | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
>
> diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs
> index 1e5a9d25c21b279b01f90b02997492aa4880d84f..0157b20373b5b2892cb618b46958bfe095e428b6 100644
> --- a/rust/kernel/revocable.rs
> +++ b/rust/kernel/revocable.rs
> @@ -105,6 +105,28 @@ pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> {
> }
> }
>
> + /// Tries to access the wrapped object and run the closure `f` on it with the guard held.
> + ///
> + /// This is a convenience method to run short non-sleepable code blocks while ensuring the
> + /// guard is dropped afterwards. [`Self::try_access`] carries the risk that the caller
> + /// will forget to explicitly drop that returned guard before calling sleepable code ; this
> + /// method adds an extra safety to make sure it doesn't happen.
> + ///
> + /// Returns `Err(ENXIO)` if the wrapped object has been revoked, or the result of `f` after it
> + /// has been run.
> + pub fn try_with<R, F: Fn(&T) -> Result<R>>(&self, f: F) -> Result<R> {
> + self.try_access().ok_or(ENXIO).and_then(|t| f(&*t))
> + }
> +
> + /// Tries to access the wrapped object and run the closure `f` on it with the guard held.
> + ///
> + /// This is the same as [`Self::try_with`], with the exception that `f` is expected to
> + /// always succeed and thus does not need to return a `Result`. Thus the only error case is if
> + /// the wrapped object has been revoked.
> + pub fn try_with_ok<R, F: Fn(&T) -> R>(&self, f: F) -> Result<R> {
> + self.try_with(|t| Ok(f(t)))
> + }
> +
> /// Tries to access the revocable wrapped object.
> ///
> /// Returns `None` if the object has been revoked and is therefore no longer accessible.
>
> ---
> base-commit: 4d872d51bc9d7b899c1f61534e3dbde72613f627
> change-id: 20250313-try_with-cc9f91dd3b60
>
> Best regards,
> --
> Alexandre Courbot <acourbot@nvidia.com>
>
next prev parent reply other threads:[~2025-03-13 14:37 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-13 12:40 [PATCH] rust/revocable: add try_with() convenience method Alexandre Courbot
2025-03-13 14:19 ` Benno Lossin
2025-03-13 15:08 ` Alexandre Courbot
2025-03-13 15:38 ` Benno Lossin
2025-03-13 15:48 ` Danilo Krummrich
2025-03-13 17:50 ` Benno Lossin
2025-03-15 14:07 ` Alexandre Courbot
2025-03-15 14:17 ` Danilo Krummrich
2025-03-15 14:26 ` Alexandre Courbot
2025-03-15 17:48 ` Benno Lossin
2025-03-16 12:20 ` Alexandre Courbot
2025-03-16 12:42 ` Danilo Krummrich
2025-03-13 14:37 ` Danilo Krummrich [this message]
2025-03-13 15:11 ` Alexandre Courbot
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=Z9Lto6tbWS0kR6gK@pollux \
--to=dakr@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--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=tmgross@umich.edu \
/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.