lkml.org 
[lkml]   [2011]   [May]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    SubjectRe: [BUG] "sched: Remove rq->lock from the first half of ttwu()" locks up on ARM
    From
    Date
    On Thu, 2011-05-26 at 13:32 +0200, Peter Zijlstra wrote:
    >
    > The bad news is of course that I've got a little more head-scratching to
    > do, will keep you informed.

    OK, that wasn't too hard.. (/me crosses fingers and prays Marc doesn't
    find more funnies ;-).

    Does the below cure all woes?

    ---
    Subject: sched: Fix ttwu() for __ARCH_WANT_INTERRUPTS_ON_CTXSW
    From: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Date: Thu May 26 14:21:33 CEST 2011

    Marc reported that e4a52bcb9 (sched: Remove rq->lock from the first
    half of ttwu()) broke his ARM-SMP machine. Now ARM is one of the few
    __ARCH_WANT_INTERRUPTS_ON_CTXSW users, so that exception in the ttwu()
    code was suspect.

    Yong found that the interrupt could hit hits after context_switch() changes
    current but before it clears p->on_cpu, if that interrupt were to
    attempt a wake-up of p we would indeed find ourselves spinning in IRQ
    context.

    Sort this by reverting to the old behaviour for this situation and
    perform a full remote wake-up.

    Cc: Frank Rowand <frank.rowand@am.sony.com>
    Cc: Yong Zhang <yong.zhang0@gmail.com>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Reported-by: Marc Zyngier <Marc.Zyngier@arm.com>
    Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
    ---
    kernel/sched.c | 37 ++++++++++++++++++++++++++++---------
    1 file changed, 28 insertions(+), 9 deletions(-)

    Index: linux-2.6/kernel/sched.c
    ===================================================================
    --- linux-2.6.orig/kernel/sched.c
    +++ linux-2.6/kernel/sched.c
    @@ -2573,7 +2573,26 @@ static void ttwu_queue_remote(struct tas
    if (!next)
    smp_send_reschedule(cpu);
    }
    -#endif
    +
    +#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
    +static int ttwu_activate_remote(struct task_struct *p, int wake_flags)
    +{
    + struct rq *rq;
    + int ret = 0;
    +
    + rq = __task_rq_lock(p);
    + if (p->on_cpu) {
    + ttwu_activate(rq, p, ENQUEUE_WAKEUP);
    + ttwu_do_wakeup(rq, p, wake_flags);
    + ret = 1;
    + }
    + __task_rq_unlock(rq);
    +
    + return ret;
    +
    +}
    +#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
    +#endif /* CONFIG_SMP */

    static void ttwu_queue(struct task_struct *p, int cpu)
    {
    @@ -2631,17 +2650,17 @@ try_to_wake_up(struct task_struct *p, un
    while (p->on_cpu) {
    #ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
    /*
    - * If called from interrupt context we could have landed in the
    - * middle of schedule(), in this case we should take care not
    - * to spin on ->on_cpu if p is current, since that would
    - * deadlock.
    + * In case the architecture enables interrupts in
    + * context_switch(), we cannot busy wait, since that
    + * would lead to live-locks when an interrupt hits and
    + * tries to wake up @prev. So bail and do a complete
    + * remote wakeup.
    */
    - if (p == current) {
    - ttwu_queue(p, cpu);
    + if (ttwu_activate_remote(p, wake_flags))
    goto stat;
    - }
    -#endif
    +#else
    cpu_relax();
    +#endif
    }
    /*
    * Pairs with the smp_wmb() in finish_lock_switch().


    \
     
     \ /
      Last update: 2011-05-26 14:25    [W:0.028 / U:2.184 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site