lkml.org 
[lkml]   [2010]   [Sep]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[072/123] sched: Make wakeup side and atomic variants of completion API irq safe
    From: Rafael J.Wysocki <rjw@sisk.pl>

    commit 7539a3b3d1f892dd97eaf094134d7de55c13befe upstream

    Alan Stern noticed that all the wakeup side (and atomic) variants of the
    completion APIs should be irq safe, but the newly introduced
    completion_done() and try_wait_for_completion() aren't. The use of the
    irq unsafe variants in IRQ contexts can cause crashes/hangs.

    Fix the problem by making them use spin_lock_irqsave() and
    spin_lock_irqrestore().

    Reported-by: Alan Stern <stern@rowland.harvard.edu>
    Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Zhang Rui <rui.zhang@intel.com>
    Cc: pm list <linux-pm@lists.linux-foundation.org>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: David Chinner <david@fromorbit.com>
    Cc: Lachlan McIlroy <lachlan@sgi.com>
    LKML-Reference: <200912130007.30541.rjw@sisk.pl>
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    Signed-off-by: Mike Galbraith <efault@gmx.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
    ---
    kernel/sched.c | 10 ++++++----
    1 file changed, 6 insertions(+), 4 deletions(-)

    --- a/kernel/sched.c
    +++ b/kernel/sched.c
    @@ -5947,14 +5947,15 @@ EXPORT_SYMBOL(wait_for_completion_killab
    */
    bool try_wait_for_completion(struct completion *x)
    {
    + unsigned long flags;
    int ret = 1;

    - spin_lock_irq(&x->wait.lock);
    + spin_lock_irqsave(&x->wait.lock, flags);
    if (!x->done)
    ret = 0;
    else
    x->done--;
    - spin_unlock_irq(&x->wait.lock);
    + spin_unlock_irqrestore(&x->wait.lock, flags);
    return ret;
    }
    EXPORT_SYMBOL(try_wait_for_completion);
    @@ -5969,12 +5970,13 @@ EXPORT_SYMBOL(try_wait_for_completion);
    */
    bool completion_done(struct completion *x)
    {
    + unsigned long flags;
    int ret = 1;

    - spin_lock_irq(&x->wait.lock);
    + spin_lock_irqsave(&x->wait.lock, flags);
    if (!x->done)
    ret = 0;
    - spin_unlock_irq(&x->wait.lock);
    + spin_unlock_irqrestore(&x->wait.lock, flags);
    return ret;
    }
    EXPORT_SYMBOL(completion_done);



    \
     
     \ /
      Last update: 2010-09-18 21:49    [W:3.582 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site