On Thu, 22 Aug 2024 at 06:28, Dave Chinner <david@xxxxxxxxxxxxx> wrote: > > wakeup_var() takes the wait queue head spinlock That's the part you missed. wake_up_var() does no such thing. It calles __wake_up_bit(), which does this: if (waitqueue_active(wq_head)) __wake_up(wq_head, TASK_NORMAL, 1, &key); and that waitqueue_active() is lockless. That's the thing that wants the barrier (or something else that guarantees that the waiters actually *see* the new state after they've added themselves to the wait-list, and before we then look at the wait-list being empty). See the comment in <linux/wait.h> above the waitqueue_active(). And yes, this is annoying and subtle and has caused bugs. But taking waitqueue locks just to notice nobody is waiting is very expensive indeed, and much more expensive than a memory barrier when the common case is typically often "nobody is waiting". Linus