>So I think you're wrong here; imagine this:
>
>
> rwsem_down_read_failed() rwsem_wake()
> get_task_struct();
> raw_spin_lock_irq(&wait_lock);
> list_add_tail(&waiter.list, &wait_list);
> raw_spin_unlock_irq(&wait_lock);
> raw_spin_lock_irqsave(&wait_lock)
> __rwsem_do_wake()
> while (true) {
> set_task_state(tsk, TASK_UNINTERRUPTIBLE);
> waiter->task = NULL
> if (!waiter.task) // true
> break;
>
> __set_task_state(tsk, TASK_RUNNING);
>
> do_exit();
> wake_up_process(tsk); /* BOOM */
I may be missing something, but rwsem_down_read_failed() will not return until
after the wakeup is done by the rwsem_wake() thread.
The above never gets to schedule(), and even if it did, a spurious
wakeup could've happened, no?