Re: [RESEND PATCH] fs/pipe: Introduce a check to skip sleeping processes during pipe read/write

From: Oleg Nesterov
Date: Sat Dec 28 2024 - 11:34:01 EST


On 12/28, Oleg Nesterov wrote:
>
> If nothing else, consider
>
> int CONDITION;
> wait_queue_head_t WQ;
>
> void wake(void)
> {
> CONDITION = 1;
> wake_up(WQ);
> }
>
> void wait(void)
> {
> DEFINE_WAIT_FUNC(entry, woken_wake_function);
>
> add_wait_queue(WQ, entry);
> if (!CONDITION)
> wait_woken(entry, ...);
> remove_wait_queue(WQ, entry);
> }
>
> this code is correct even if LOAD(CONDITION) can leak into the critical
> section in add_wait_queue(), so CPU running wait() can actually do
>
> // add_wait_queue
> spin_lock(WQ->lock);
> LOAD(CONDITION); // false!
> list_add(entry, head);
> spin_unlock(WQ->lock);
>
> if (!false) // result of the LOAD above
> wait_woken(entry, ...);
>
> Now suppose that another CPU executes wake() between LOAD(CONDITION)
> and list_add(entry, head). With your patch wait() will miss the event.
> The same for __pollwait(), I think...
>
> No?

Even simpler,

void wait(void)
{
DEFINE_WAIT(entry);

__set_current_state(XXX);
add_wait_queue(WQ, entry);

if (!CONDITION)
schedule();

remove_wait_queue(WQ, entry);
__set_current_state(TASK_RUNNING);
}

This code is ugly but currently correct unless I am totally confused.

Oleg.