summaryrefslogtreecommitdiff
path: root/rust/kernel
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2025-04-11 21:09:38 +0900
committerDanilo Krummrich <dakr@kernel.org>2025-04-22 17:20:28 +0200
commit80e62fcea4f3ce8c7cc3205d7543e532b255d322 (patch)
tree1d40ff8f60cc062246bdf941cac153ffb9b83b33 /rust/kernel
parent96609a1969f4ade45351ec368c65580c77592e8b (diff)
rust/revocable: add try_access_with() convenience method
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 for the caller to explicitly 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(...); This is arguably error-prone. try_access_with() 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 of forgetting to release the guard when needed is considerably reduced: let reg = bar.try_access_with(|b| b.readl(...))?; something_that_might_sleep(); let reg2 = bar.try_access_with(|b| b.readl(...))?; The closure can return nothing, or any value including a Result which is then wrapped inside the Option returned by try_access_with. Error management is driver-specific, so users are encouraged to create their own macros that map and flatten the returned values to something appropriate for the code they are working on. Suggested-by: Danilo Krummrich <dakr@kernel.org> Reviewed-by: Benno Lossin <benno.lossin@proton.me> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Reviewed-by: Joel Fernandes <joelagnelf@nvidia.com> Acked-by: Miguel Ojeda <ojeda@kernel.org> Link: https://lore.kernel.org/r/20250411-try_with-v4-1-f470ac79e2e2@nvidia.com [ Link `None`, `Some`, `Option` in doc-comment. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Diffstat (limited to 'rust/kernel')
-rw-r--r--rust/kernel/revocable.rs16
1 files changed, 16 insertions, 0 deletions
diff --git a/rust/kernel/revocable.rs b/rust/kernel/revocable.rs
index 1e5a9d25c21b..971d0dc38d83 100644
--- a/rust/kernel/revocable.rs
+++ b/rust/kernel/revocable.rs
@@ -123,6 +123,22 @@ impl<T> Revocable<T> {
}
}
+ /// Tries to access the wrapped object and run a closure on it while the guard is 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 [`None`] if the object has been revoked and is therefore no longer accessible, or
+ /// the result of the closure wrapped in [`Some`]. If the closure returns a [`Result`] then the
+ /// return type becomes `Option<Result<>>`, which can be inconvenient. Users are encouraged to
+ /// define their own macro that turns the [`Option`] into a proper error code and flattens the
+ /// inner result into it if it makes sense within their subsystem.
+ pub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R> {
+ self.try_access().map(|t| f(&*t))
+ }
+
/// # Safety
///
/// Callers must ensure that there are no more concurrent users of the revocable object.