[PATCH v10] rust: sync: condvar: use Delta<Jiffy> for timeout and result
From: FUJITA Tomonori
Date: Wed Nov 04 2026 - 22:26:08 EST
From: FUJITA Tomonori <fujita.tomonori@xxxxxxxxx>
wait_interruptible_timeout() takes the timeout as a raw Jiffies, and
CondVarTimeoutResult reports the remaining time as a raw Jiffies. The
type does not show the unit.
Switch the parameter and the result fields to Delta<Jiffy>.
Delta<Jiffy> is signed, but schedule_timeout() prints an error and a
stack dump for a negative timeout. Clamp a negative timeout to zero, so
it means an immediate timeout.
Update the only user, binder. It now converts the freeze timeout with
Delta::to_jiffies_timeout() instead of msecs_to_jiffies(). Both round
up, so a short timeout does not become zero. They differ only for a
very long timeout. msecs_to_jiffies() returns MAX_JIFFY_OFFSET for
2^31 ms (about 24.9 days) or more, which means an infinite
timeout. to_jiffies_timeout() has no such special case. It converts
such a value to the matching number of jiffies, so the wait is long
but finite.
Reviewed-by: Gary Guo <gary@xxxxxxxxxxx>
Reviewed-by: Alice Ryhl <aliceryhl@xxxxxxxxxx>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxx>
---
v10:
- Rename variables and fields to describe their role, since the type now
shows the unit (suggested by Boqun):
- binder: the local variable `jiffies` to `timeout`
- wait_interruptible_timeout(): the parameter `delta` to `timeout`
- the `jiffies` match bindings and the `jiffies` field of
CondVarTimeoutResult::{Woken, Signal} to `remainder`
- Add Alice's Reviewed-by
v9: https://lore.kernel.org/rust-for-linux/20261102035934.711973-1-tomo@xxxxxxxxxxxx/
- Send as a single patch. Patches 1/4 and 2/4 of v8 are in v7.4-rc1,
and the workqueue patch will be sent separately
- Rebase on v7.4-rc1
- Drop the comparison with enqueue_delayed() from the commit message
v8: https://lore.kernel.org/rust-for-linux/20261002050428.2746277-1-tomo@xxxxxxxxxxxx/
Boqun, would you take this through the rust-sync tree?
---
drivers/android/binder/process.rs | 13 +++++++------
rust/kernel/sync/condvar.rs | 31 ++++++++++++++++++++++---------
2 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index 1f4cb43f1de6..0ed6a4b1c74b 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -35,6 +35,7 @@
Arc, ArcBorrow, CondVar, CondVarTimeoutResult, SetOnce, SpinLock, UniqueArc,
},
task::{Pid, Task},
+ time::Delta,
uaccess::{UserSlice, UserSliceReader},
uapi,
workqueue::{self, Work},
@@ -1552,25 +1553,25 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
inner.is_frozen = IsFrozen::InProgress;
if info.timeout_ms > 0 {
- let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms);
- while jiffies > 0 {
+ let mut timeout = Delta::from_millis(info.timeout_ms.into()).to_jiffies_timeout();
+ while timeout.as_jiffies() > 0 {
if inner.outstanding_txns == 0 {
break;
}
match self
.freeze_wait
- .wait_interruptible_timeout(&mut inner, jiffies)
+ .wait_interruptible_timeout(&mut inner, timeout)
{
CondVarTimeoutResult::Signal { .. } => {
inner.is_frozen = IsFrozen::No;
return Err(ERESTARTSYS);
}
- CondVarTimeoutResult::Woken { jiffies: remaining } => {
- jiffies = remaining;
+ CondVarTimeoutResult::Woken { remainder } => {
+ timeout = remainder;
}
CondVarTimeoutResult::Timeout => {
- jiffies = 0;
+ timeout = Delta::ZERO;
}
}
}
diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 69d58dfbad7b..4be2c3bf8802 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -12,7 +12,10 @@
task::{
MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE,
},
- time::Jiffies,
+ time::{
+ Delta,
+ Jiffy, //
+ },
types::Opaque,
};
use core::{marker::PhantomPinned, pin::Pin, ptr};
@@ -182,19 +185,29 @@ pub fn wait_interruptible_freezable<T: ?Sized, B: Backend>(
/// Atomically releases the given lock (whose ownership is proven by the guard) and puts the
/// thread to sleep. It wakes up when notified by [`CondVar::notify_one`] or
/// [`CondVar::notify_all`], or when a timeout occurs, or when the thread receives a signal.
+ ///
+ /// A negative timeout is treated as zero.
#[must_use = "wait_interruptible_timeout returns if a signal is pending, so the caller must check the return value"]
pub fn wait_interruptible_timeout<T: ?Sized, B: Backend>(
&self,
guard: &mut Guard<'_, T, B>,
- jiffies: Jiffies,
+ timeout: Delta<Jiffy>,
) -> CondVarTimeoutResult {
- let jiffies = jiffies.try_into().unwrap_or(MAX_SCHEDULE_TIMEOUT);
- let res = self.wait_internal(TASK_INTERRUPTIBLE, guard, jiffies);
+ let jiffies = timeout.as_jiffies();
+ let res = self.wait_internal(
+ TASK_INTERRUPTIBLE,
+ guard,
+ jiffies.clamp(0, MAX_SCHEDULE_TIMEOUT),
+ );
- match (res as Jiffies, crate::current!().signal_pending()) {
- (jiffies, true) => CondVarTimeoutResult::Signal { jiffies },
+ match (res, crate::current!().signal_pending()) {
+ (remainder, true) => CondVarTimeoutResult::Signal {
+ remainder: Delta::from_jiffies(remainder),
+ },
(0, false) => CondVarTimeoutResult::Timeout,
- (jiffies, false) => CondVarTimeoutResult::Woken { jiffies },
+ (remainder, false) => CondVarTimeoutResult::Woken {
+ remainder: Delta::from_jiffies(remainder),
+ },
}
}
@@ -248,11 +261,11 @@ pub enum CondVarTimeoutResult {
/// Somebody woke us up.
Woken {
/// Remaining sleep duration.
- jiffies: Jiffies,
+ remainder: Delta<Jiffy>,
},
/// A signal occurred.
Signal {
/// Remaining sleep duration.
- jiffies: Jiffies,
+ remainder: Delta<Jiffy>,
},
}
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
--
2.43.0