From: "Gary Guo" <gary@garyguo.net>
To: "FUJITA Tomonori" <tomo@flapping.org>, <gary@garyguo.net>,
<anna-maria@linutronix.de>, <frederic@kernel.org>,
<tglx@kernel.org>
Cc: <a.hindborg@kernel.org>, <ojeda@kernel.org>,
<acourbot@nvidia.com>, <aliceryhl@google.com>,
<bjorn3_gh@protonmail.com>, <boqun@kernel.org>, <dakr@kernel.org>,
<daniel.almeida@collabora.com>, <jstultz@google.com>,
<lossin@kernel.org>, <lyude@redhat.com>, <sboyd@kernel.org>,
<tamird@kernel.org>, <tmgross@umich.edu>, <work@onurozkan.dev>,
<rust-for-linux@vger.kernel.org>, <fujita.tomonori@gmail.com>
Subject: Re: [PATCH 0/4] Fix forward()/expires() racing with concurrent arming
Date: Fri, 14 Aug 2026 01:54:25 +0100 [thread overview]
Message-ID: <DKO995UPAESG.UQNZ5G92HCPQ@garyguo.net> (raw)
In-Reply-To: <20260814.084700.1697518597717457311.tomo@flapping.org>
On Fri Aug 14, 2026 at 12:47 AM BST, FUJITA Tomonori wrote:
> On Thu, 13 Aug 2026 15:16:38 +0100
> "Gary Guo" <gary@garyguo.net> wrote:
>
>> I am thinking about this and I wonder about a different approach: the only
>> reason that we're having this issue, is that `expires()` call and
>> `forward`/`forward_now` is executed outside the protection of the base lock.
>>
>> The fix is easy -- to ensure that they are executed with the base lock held.
>> The callback wants either:
>> * Do not restart the timer
>> * Call hrtimer_forward[_now] and restart the timer
>>
>> So, if we change the order from
>>
>> unlock base
>> restart = fn(timer)
>> lock base
>> if restart {
>> queue
>> }
>>
>> to
>>
>> get expires
>> unlock base
>> restart = fn(timer, expires)
>> lock base
>> match restart {
>> Restart(now, interval) => {
>> hrtimer_forward(timer, now, interval);
>> queue
>> }
>> NoRestart => (),
>> }
>>
>> then we completely eradicate this issue.
>
> If I understood the proposal correctly: hrtimer_forward[_now]() would no
> longer be called by drivers at all. It becomes internal to the core and
> runs with the base lock held, and every hrtimer callback in the tree is
> updated to take the expiry as an argument and return the interval, with
> the ones that use the overrun computing it from what they were passed.
Right, that the idea. I think patching all hrtimer callback is probably a bit
excessive, but one way would be add a mode where cpu_base->lock is not unlocked,
and the Rust hrtimer abstraction would read the expiry, unlock it, run the
callback and re-lock the base lock.
>
> That could remove the need for the rule on the Rust side.
>
> Anna-Maria, Frederic, Thomas: does this direction look reasonable to you?
>
>
>> Alternatively, we can add another spinlock to protect `expires` from race
>> condition from within callback and concurrent restart -- that is what perf core
>> does: perf_mux_hrtimer_handler and perf_mux_hrtimer_restart uses the same
>> hrtimer_lock to prevent race.
>
> Right, with the lock and cpc->hrtimer_active flag together, perf
> implements the same "do not arm while armed" rule that these patches
> implement in the type system.
>
>
>> But further complicating the type system to prevent concurrent restart sounds
>> like a bad approach to me.
>
> My intent is the opposite: I think this makes the design simpler.
>
> All four implementations of start() already take self by value. For
> Pin<Box<T, A>> and Pin<&mut T> that means what it says -- the box is moved
> into the handle, the exclusive borrow is consumed -- so "no arming while
> armed" is already the design there. For Arc<T> and Pin<&T> the same
> signature meant nothing, because Clone and Copy let you build another
> pointer and call start() again.
>
> So the contract depended on which pointer type you picked, and the module
> documentation had to spell that out: "When a type implements both
> HrTimerPointer and Clone, it is possible to issue the start operation
> while the timer is in the started state." After the series there is one
> rule for all four types, and that paragraph is gone together with the
> restart operation it described.
Let's ignore the implementation detail of all various Rust pointers. It is
something that I plan to overhaul and doesn't matter to the core issue here.
The change you're making is to remove the ability to concurrently start a timer
in Rust. So if you have a timer might be running, you'd need to first cancel it
before you can arm it again.
I do think it is conceptually cleaner -- however given this is explicitly added
in
https://lore.kernel.org/all/tip-5de2755c8c8b3a6b8414870e2c284914a2b42e4d@git.kernel.org/
and the pattern is what perf core uses; so I wouldn't just dismiss the existence
of this pattern. Perhaps cancelling before restarting is considered too
expensive and has to be avoided?
Best,
Gary
next prev parent reply other threads:[~2026-08-14 0:54 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-13 13:48 [PATCH 0/4] Fix forward()/expires() racing with concurrent arming FUJITA Tomonori
2026-08-13 13:48 ` [PATCH v1 1/4] rust: hrtimer: Introduce HrTimerArc to make arming exclusive FUJITA Tomonori
2026-08-13 13:48 ` [PATCH v1 2/4] rust: hrtimer: Introduce HrTimerPin " FUJITA Tomonori
2026-08-13 13:48 ` [PATCH v1 3/4] rust: hrtimer: Restrict expires() to safe contexts FUJITA Tomonori
2026-08-13 13:48 ` [PATCH v1 4/4] rust: hrtimer: Make HrTimer repr(transparent) FUJITA Tomonori
2026-08-13 14:16 ` [PATCH 0/4] Fix forward()/expires() racing with concurrent arming Gary Guo
2026-08-13 23:47 ` FUJITA Tomonori
2026-08-14 0:54 ` Gary Guo [this message]
2026-08-14 13:48 ` FUJITA Tomonori
2026-08-14 14:24 ` Gary Guo
2026-08-18 0:56 ` FUJITA Tomonori
2026-08-17 15:40 ` Gary Guo
2026-08-18 1:35 ` FUJITA Tomonori
2026-08-17 15:26 ` Andreas Hindborg
2026-08-18 2:26 ` FUJITA Tomonori
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DKO995UPAESG.UQNZ5G92HCPQ@garyguo.net \
--to=gary@garyguo.net \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=aliceryhl@google.com \
--cc=anna-maria@linutronix.de \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=frederic@kernel.org \
--cc=fujita.tomonori@gmail.com \
--cc=jstultz@google.com \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=sboyd@kernel.org \
--cc=tamird@kernel.org \
--cc=tglx@kernel.org \
--cc=tmgross@umich.edu \
--cc=tomo@flapping.org \
--cc=work@onurozkan.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox