[PATCH 01/17] rust: sync: completion: add wait_for_completion_timeout()
From: John Hubbard
Date: Fri Aug 07 2026 - 23:11:40 EST
From: Joel Fernandes <joelagnelf@xxxxxxxxxx>
A driver that runs an interrupt self-test during probe waits for the
handler to fire. wait_for_completion() has no timeout, so a broken
interrupt path stalls probe indefinitely. Add a timeout variant of
wait_for_completion().
Document the type invariant that Completion always holds an initialized
struct completion, and cite it in the SAFETY comments.
Signed-off-by: Joel Fernandes <joelagnelf@xxxxxxxxxx>
[jhubbard: return the remaining jiffies, document the type invariant,
cite it in the SAFETY comments]
Signed-off-by: John Hubbard <jhubbard@xxxxxxxxxx>
---
rust/kernel/sync/completion.rs | 34 +++++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/sync/completion.rs b/rust/kernel/sync/completion.rs
index 35ff049ff078..b443c4999493 100644
--- a/rust/kernel/sync/completion.rs
+++ b/rust/kernel/sync/completion.rs
@@ -6,13 +6,22 @@
//!
//! C header: [`include/linux/completion.h`](srctree/include/linux/completion.h)
-use crate::{bindings, prelude::*, types::Opaque};
+use crate::{
+ bindings,
+ prelude::*,
+ time::Jiffies,
+ types::Opaque, //
+};
/// Synchronization primitive to signal when a certain task has been completed.
///
/// The [`Completion`] synchronization primitive signals when a certain task has been completed by
/// waking up other tasks that have been queued up to wait for the [`Completion`] to be completed.
///
+/// # Invariants
+///
+/// `inner` always holds an initialized `struct completion`.
+///
/// # Examples
///
/// ```
@@ -96,7 +105,8 @@ fn as_raw(&self) -> *mut bindings::completion {
/// completion is permanently done, i.e. signals all current and future waiters.
#[inline]
pub fn complete_all(&self) {
- // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
+ // SAFETY: By the type invariant, `self.as_raw()` is a pointer to an initialized
+ // `struct completion`.
unsafe { bindings::complete_all(self.as_raw()) };
}
@@ -108,7 +118,25 @@ pub fn complete_all(&self) {
/// See also [`Completion::complete_all`].
#[inline]
pub fn wait_for_completion(&self) {
- // SAFETY: `self.as_raw()` is a pointer to a valid `struct completion`.
+ // SAFETY: By the type invariant, `self.as_raw()` is a pointer to an initialized
+ // `struct completion`.
unsafe { bindings::wait_for_completion(self.as_raw()) };
}
+
+ /// Wait for completion of a task, with a timeout.
+ ///
+ /// This method waits for the completion of a task, or until `timeout` elapses. It is not
+ /// interruptible. Returns the number of jiffies left when the task completed, or [`None`] if
+ /// `timeout` elapsed first.
+ ///
+ /// See also [`Completion::complete_all`].
+ #[inline]
+ pub fn wait_for_completion_timeout(&self, timeout: Jiffies) -> Option<Jiffies> {
+ // SAFETY: By the type invariant, `self.as_raw()` is a pointer to an initialized
+ // `struct completion`.
+ match unsafe { bindings::wait_for_completion_timeout(self.as_raw(), timeout) } {
+ 0 => None,
+ remaining => Some(remaining),
+ }
+ }
}
--
2.55.0