On Thu, Nov 29, 2018 at 10:21:58AM -0500, Waiman Long wrote: > >> diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c > >> index 09b1800..50d9af6 100644 > >> --- a/kernel/locking/rwsem-xadd.c > >> +++ b/kernel/locking/rwsem-xadd.c > >> @@ -198,15 +198,22 @@ static void __rwsem_mark_wake(struct rw_semaphore > >> *sem, > >> woken++; > >> tsk = waiter->task; > >> > >> - wake_q_add(wake_q, tsk); > >> + get_task_struct(tsk); > >> list_del(&waiter->list); > >> /* > >> - * Ensure that the last operation is setting the reader > >> + * Ensure calling get_task_struct() before setting the reader > >> * waiter to nil such that rwsem_down_read_failed() cannot > >> * race with do_exit() by always holding a reference count > >> * to the task to wakeup. > >> */ > >> smp_store_release(&waiter->task, NULL); > >> + /* > >> + * Ensure issuing the wakeup (either by us or someone else) > >> + * after setting the reader waiter to nil. > >> + */ > >> + wake_q_add(wake_q, tsk); > >> + /* wake_q_add() already take the task ref */ > >> + put_task_struct(tsk); > >> } > >> > >> adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment; > > I doubt putting wake_q_add() after clearing waiter->task can really fix
Why; at that point we know the wakeup will happen after, which is all we require.