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.


Reply via email to