mirror of https://github.com/torvalds/linux.git
rust: Add read_poll_timeout_atomic function
Add read_poll_timeout_atomic function which polls periodically until a condition is met, an error occurs, or the attempt limit is reached. The C's read_poll_timeout_atomic() is used for the similar purpose. In atomic context the timekeeping infrastructure is unavailable, so reliable time-based timeouts cannot be implemented. So instead, the helper accepts a maximum number of attempts and busy-waits (udelay + cpu_relax) between tries. Reviewed-by: Alice Ryhl <aliceryhl@google.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com> Link: https://patch.msgid.link/20251103112958.2961517-3-fujita.tomonori@gmail.com [ Adjust imports to use "kernel vertical" style. - Danilo ] Signed-off-by: Danilo Krummrich <dakr@kernel.org>
This commit is contained in:
parent
ad68b55a9e
commit
46f045db5a
|
|
@ -8,7 +8,15 @@
|
|||
error::{code::*, Result},
|
||||
processor::cpu_relax,
|
||||
task::might_sleep,
|
||||
time::{delay::fsleep, Delta, Instant, Monotonic},
|
||||
time::{
|
||||
delay::{
|
||||
fsleep,
|
||||
udelay, //
|
||||
},
|
||||
Delta,
|
||||
Instant,
|
||||
Monotonic, //
|
||||
},
|
||||
};
|
||||
|
||||
/// Polls periodically until a condition is met, an error occurs,
|
||||
|
|
@ -96,3 +104,70 @@ pub fn read_poll_timeout<Op, Cond, T>(
|
|||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
/// Polls periodically until a condition is met, an error occurs,
|
||||
/// or the attempt limit is reached.
|
||||
///
|
||||
/// The function repeatedly executes the given operation `op` closure and
|
||||
/// checks its result using the condition closure `cond`.
|
||||
///
|
||||
/// If `cond` returns `true`, the function returns successfully with the result of `op`.
|
||||
/// Otherwise, it performs a busy wait for a duration specified by `delay_delta`
|
||||
/// before executing `op` again.
|
||||
///
|
||||
/// This process continues until either `op` returns an error, `cond`
|
||||
/// returns `true`, or the attempt limit specified by `retry` is reached.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If `op` returns an error, then that error is returned directly.
|
||||
///
|
||||
/// If the attempt limit specified by `retry` is reached, then
|
||||
/// `Err(ETIMEDOUT)` is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use kernel::io::{poll::read_poll_timeout_atomic, Io};
|
||||
/// use kernel::time::Delta;
|
||||
///
|
||||
/// const HW_READY: u16 = 0x01;
|
||||
///
|
||||
/// fn wait_for_hardware<const SIZE: usize>(io: &Io<SIZE>) -> Result {
|
||||
/// read_poll_timeout_atomic(
|
||||
/// // The `op` closure reads the value of a specific status register.
|
||||
/// || io.try_read16(0x1000),
|
||||
/// // The `cond` closure takes a reference to the value returned by `op`
|
||||
/// // and checks whether the hardware is ready.
|
||||
/// |val: &u16| *val == HW_READY,
|
||||
/// Delta::from_micros(50),
|
||||
/// 1000,
|
||||
/// )?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
pub fn read_poll_timeout_atomic<Op, Cond, T>(
|
||||
mut op: Op,
|
||||
mut cond: Cond,
|
||||
delay_delta: Delta,
|
||||
retry: usize,
|
||||
) -> Result<T>
|
||||
where
|
||||
Op: FnMut() -> Result<T>,
|
||||
Cond: FnMut(&T) -> bool,
|
||||
{
|
||||
for _ in 0..retry {
|
||||
let val = op()?;
|
||||
if cond(&val) {
|
||||
return Ok(val);
|
||||
}
|
||||
|
||||
if !delay_delta.is_zero() {
|
||||
udelay(delay_delta);
|
||||
}
|
||||
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
Err(ETIMEDOUT)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue