Re: [PATCH 1/3] sched/psi: Avoid losing wakeups during rtpoll worker replacement

Guopeng Zhang <[email protected]>
Newsgroups gmane.linux.kernel
Message-ID <[email protected]>

在 2026/7/27 12:03, Suren Baghdasaryan 写道:
> On Fri, Jul 17, 2026 at 2:14 AM Guopeng Zhang <[email protected]> wrote:
>>
>> From: Guopeng Zhang <[email protected]>
>>
>> psi_trigger_destroy() clears rtpoll_task while holding the trigger
>> lock, but has to drop the lock before stopping the worker because
>> psi_rtpoll_work() takes the same lock. A new trigger can therefore
>> install a replacement worker before the old one exits.
>>
>> rtpoll_wakeup is shared by both workers. The wait condition currently
> 
> To be clear, "both workers" refer to the old worked being stopped and
> the new worked created by psi_trigger_create(). Please spell that out
> to avoid confusion.
> 
Hi Suren,

Sorry for the late reply, I got tied up with some other work :)

Thanks for the review. Yes, I'll make that explicit in v2.

>> consumes it before checking whether the worker should stop. If the
>> replacement timer sets the wakeup while the old worker is being stopped,
>> the old worker can consume it and then exit. Since the one-shot timer has
>> already fired and rtpoll_scheduled remains set, the replacement can stay
>> asleep and rtpolling can stall.
>>
>> Make the wait condition only observe the wakeup. Check for stop before
>> consuming it and, once consumed, always process the work.
>>
>> Fixes: 461daba06bdc ("psi: eliminate kthread_worker from psi trigger scheduling mechanism")
>> Signed-off-by: Guopeng Zhang <[email protected]>
>> ---
>>  kernel/sched/psi.c | 8 +++++++-
>>  1 file changed, 7 insertions(+), 1 deletion(-)
>>
>> diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c
>> index 4e152410653d..b9e2a93a757b 100644
>> --- a/kernel/sched/psi.c
>> +++ b/kernel/sched/psi.c
>> @@ -743,10 +743,16 @@ static int psi_rtpoll_worker(void *data)
>>
>>         while (true) {
>>                 wait_event_interruptible(group->rtpoll_wait,
>> -                               atomic_cmpxchg(&group->rtpoll_wakeup, 1, 0) ||
>> +                               atomic_read(&group->rtpoll_wakeup) ||
>>                                 kthread_should_stop());
>>                 if (kthread_should_stop())
>>                         break;
>> +               /*
>> +                * Consume the wakeup only after checking for stop. Once consumed,
>> +                * always run the work so a replacement worker cannot lose it.
>> +                */
>> +               if (atomic_cmpxchg(&group->rtpoll_wakeup, 1, 0) != 1)
>> +                       continue;
> 
> This works but a simpler fix is to reorder conditions in
> wait_event_interruptible() call like this:
> 
>          while (true) {
>                  wait_event_interruptible(group->rtpoll_wait,
>                                 kthread_should_stop() ||
>                                 atomic_cmpxchg(&group->rtpoll_wakeup, 1, 0));
>                  if (kthread_should_stop())
>                          break;
> 
>                  psi_rtpoll_work(group);
>          }
> 
> The old worker would check kthread_should_stop() and stop before it
> can consume rtpoll_wakeup. Do you agree?
> 

Could the following race still happen?

old worker                         teardown
-------------------------------------------------------
kthread_should_stop() == false
cmpxchg(wakeup, 1, 0) succeeds
                                   kthread_stop() sets SHOULD_STOP
kthread_should_stop() == true
exits without running the work

In this case, it seems the old worker could still consume the wakeup and
then observe the stop request before calling psi_rtpoll_work().

Therefore, reordering the conditions appears to narrow the race window,
but does not close it completely.

Thanks,
Guopeng

>>
>>                 psi_rtpoll_work(group);
>>         }
>> --
>> 2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.