On Mon, Feb 15, 2021 at 12:23:52PM -0300, André Almeida wrote: > +static int __futex_wait(struct futexv_head *futexv, unsigned int nr_futexes, > + struct hrtimer_sleeper *timeout) > +{ > + int ret; > + > + while (1) { > + int awakened = -1; > + Might be easier to understand if the set_current_state() is here, instead of squirreled away in futex_enqueue(). > + ret = futex_enqueue(futexv, nr_futexes, &awakened); > + > + if (ret) { > + if (awakened >= 0) > + return awakened; > + return ret; > + } > + > + /* Before sleeping, check if someone was woken */ > + if (!futexv->hint && (!timeout || timeout->task)) > + freezable_schedule(); > + > + __set_current_state(TASK_RUNNING); This is typically after the loop. > + > + /* > + * One of those things triggered this wake: > + * > + * * We have been removed from the bucket. futex_wake() woke > + * us. We just need to dequeue and return 0 to userspace. > + * > + * However, if no futex was dequeued by a futex_wake(): > + * > + * * If the there's a timeout and it has expired, > + * return -ETIMEDOUT. > + * > + * * If there is a signal pending, something wants to kill our > + * thread, return -ERESTARTSYS. > + * > + * * If there's no signal pending, it was a spurious wake > + * (scheduler gave us a change to do some work, even if we chance? > + * don't want to). We need to remove ourselves from the > + * bucket and add again, to prevent losing wakeups in the > + * meantime. > + */ Anyway, doing a dequeue and enqueue for spurious wakes is a bit of an anti-pattern that can lead to starvation. I've not actually looked at much detail yet as this is my first read-through, but did figure I'd mention it. > + > + ret = futex_dequeue_multiple(futexv, nr_futexes); > + > + /* Normal wake */ > + if (ret >= 0) > + return ret; > + > + if (timeout && !timeout->task) > + return -ETIMEDOUT; > + > + if (signal_pending(current)) > + return -ERESTARTSYS; > + > + /* Spurious wake, do everything again */ > + } > +}