[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <64335523-D12A-4E65-9518-64FC08C26D39@kloenk.dev>
Date: Tue, 28 Jan 2025 11:49:48 +0100
From: Fiona Behrens <me@...enk.dev>
To: FUJITA Tomonori <fujita.tomonori@...il.com>
Cc: gary@...yguo.net, linux-kernel@...r.kernel.org,
rust-for-linux@...r.kernel.org, netdev@...r.kernel.org, andrew@...n.ch,
hkallweit1@...il.com, tmgross@...ch.edu, ojeda@...nel.org,
alex.gaynor@...il.com, bjorn3_gh@...tonmail.com, benno.lossin@...ton.me,
a.hindborg@...sung.com, aliceryhl@...gle.com, anna-maria@...utronix.de,
frederic@...nel.org, tglx@...utronix.de, arnd@...db.de, jstultz@...gle.com,
sboyd@...nel.org, mingo@...hat.com, peterz@...radead.org,
juri.lelli@...hat.com, vincent.guittot@...aro.org, dietmar.eggemann@....com,
rostedt@...dmis.org, bsegall@...gle.com, mgorman@...e.de,
vschneid@...hat.com, tgunders@...hat.com
Subject: Re: [PATCH v9 7/8] rust: Add read_poll_timeout functions
On 28 Jan 2025, at 7:29, FUJITA Tomonori wrote:
> On Tue, 28 Jan 2025 08:49:37 +0800
> Gary Guo <gary@...yguo.net> wrote:
>
>> On Mon, 27 Jan 2025 15:31:47 +0900 (JST)
>> FUJITA Tomonori <fujita.tomonori@...il.com> wrote:
>>
>>> On Mon, 27 Jan 2025 11:46:46 +0800
>>> Gary Guo <gary@...yguo.net> wrote:
>>>
>>>>> +#[track_caller]
>>>>> +pub fn read_poll_timeout<Op, Cond, T: Copy>(
>>>>> + mut op: Op,
>>>>> + mut cond: Cond,
>>>>> + sleep_delta: Delta,
>>>>> + timeout_delta: Delta,
>>>>> +) -> Result<T>
>>>>> +where
>>>>> + Op: FnMut() -> Result<T>,
>>>>> + Cond: FnMut(&T) -> bool,
>>>>> +{
>>>>> + let start = Instant::now();
>>>>> + let sleep = !sleep_delta.is_zero();
>>>>> + let timeout = !timeout_delta.is_zero();
>>>>> +
>>>>> + if sleep {
>>>>> + might_sleep(Location::caller());
>>>>> + }
>>>>> +
>>>>> + loop {
>>>>> + let val = op()?;
>>>>> + if cond(&val) {
>>>>> + // Unlike the C version, we immediately return.
>>>>> + // We know the condition is met so we don't need to check again.
>>>>> + return Ok(val);
>>>>> + }
>>>>> + if timeout && start.elapsed() > timeout_delta {
>>>>
>>>> Re-reading this again I wonder if this is the desired behaviour? Maybe
>>>> a timeout of 0 should mean check-once instead of no timeout. The
>>>> special-casing of 0 makes sense in C but in Rust we should use `None`
>>>> to mean it instead?
>>>
>>> It's the behavior of the C version; the comment of this function says:
>>>
>>> * @timeout_us: Timeout in us, 0 means never timeout
>>>
>>> You meant that waiting for a condition without a timeout is generally
>>> a bad idea? If so, can we simply return EINVAL for zero Delta?
>>>
>>
>> No, I think we should still keep the ability to represent indefinite
>> wait (no timeout) but we should use `None` to represent this rather
>> than `Delta::ZERO`.
>>
>> I know that we use 0 to mean indefinite wait in C, I am saying that
>> it's not the most intuitive way to represent in Rust.
>>
>> Intuitively, a timeout of 0 should be closer to a timeout of 1 and thus
>> should mean "return with ETIMEDOUT immedidately" rather than "wait
>> forever".
>>
>> In C since we don't have a very good sum type support, so we
>> special case 0 to be the special value to represent indefinite wait,
>> but I don't think we need to repeat this in Rust.
>
> Understood, thanks. How about the following code?
>
> +#[track_caller]
> +pub fn read_poll_timeout<Op, Cond, T: Copy>(
> + mut op: Op,
> + mut cond: Cond,
> + sleep_delta: Delta,
> + timeout_delta: Option<Delta>,
> +) -> Result<T>
> +where
> + Op: FnMut() -> Result<T>,
> + Cond: FnMut(&T) -> bool,
> +{
> + let start = Instant::now();
> + let sleep = !sleep_delta.is_zero();
> +
> + if sleep {
> + might_sleep(Location::caller());
> + }
> +
> + loop {
> + let val = op()?;
> + if cond(&val) {
> + // Unlike the C version, we immediately return.
> + // We know the condition is met so we don't need to check again.
> + return Ok(val);
> + }
> + if let Some(timeout_delta) = timeout_delta {
> + if start.elapsed() > timeout_delta {
> + // Unlike the C version, we immediately return.
> + // We have just called `op()` so we don't need to call it again.
> + return Err(ETIMEDOUT);
> + }
> + }
> + if sleep {
> + fsleep(sleep_delta);
> + }
> + // fsleep() could be busy-wait loop so we always call cpu_relax().
> + cpu_relax();
> + }
> +}
I wonder if it makes sense to then switch `Delta` to wrap a `NonZeroI64` and forbid deltas with 0 nanoseconds with that and use the niche optimization. Not sure if we make other apis horrible by that, but this would prevent deltas that encode no time passing.
Thanks,
Fiona
Powered by blists - more mailing lists