lkml.org 
[lkml]   [2011]   [Sep]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3/6] freezer: restructure __refrigerator()
    Date
    If another freeze happens before all tasks leave FROZEN state after
    being thawed, the freezer can see the existing FROZEN and consider the
    tasks to be frozen but they can clear FROZEN without checking the new
    freezing().

    Oleg suggested restructuring __refrigerator() such that there's single
    condition check section inside freezer_lock and sigpending is cleared
    afterwards, which fixes the problem and simplifies the code.
    Restructure accordingly.

    -v2: Frozen loop exited without releasing freezer_lock. Fixed.

    Signed-off-by: Tejun Heo <tj@kernel.org>
    Reported-by: Oleg Nesterov <oleg@redhat.com>
    Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
    ---
    kernel/freezer.c | 29 +++++++++++------------------
    1 files changed, 11 insertions(+), 18 deletions(-)

    diff --git a/kernel/freezer.c b/kernel/freezer.c
    index 466ea6b..ebee1ab 100644
    --- a/kernel/freezer.c
    +++ b/kernel/freezer.c
    @@ -52,36 +52,29 @@ bool __refrigerator(bool check_kthr_stop)
    /* Hmm, should we be allowed to suspend when there are realtime
    processes around? */
    bool was_frozen = false;
    - long save;
    + long save = current->state;

    - /*
    - * No point in checking freezing() again - the caller already did.
    - * Proceed to enter FROZEN.
    - */
    - spin_lock_irq(&freezer_lock);
    - current->flags |= PF_FROZEN;
    - spin_unlock_irq(&freezer_lock);
    -
    - save = current->state;
    pr_debug("%s entered refrigerator\n", current->comm);

    - spin_lock_irq(&current->sighand->siglock);
    - recalc_sigpending(); /* We sent fake signal, clean it up */
    - spin_unlock_irq(&current->sighand->siglock);
    -
    for (;;) {
    set_current_state(TASK_UNINTERRUPTIBLE);
    +
    + spin_lock_irq(&freezer_lock);
    + current->flags |= PF_FROZEN;
    if (!freezing(current) ||
    (check_kthr_stop && kthread_should_stop()))
    + current->flags &= ~PF_FROZEN;
    + spin_unlock_irq(&freezer_lock);
    +
    + if (!(current->flags & PF_FROZEN))
    break;
    was_frozen = true;
    schedule();
    }

    - /* leave FROZEN */
    - spin_lock_irq(&freezer_lock);
    - current->flags &= ~PF_FROZEN;
    - spin_unlock_irq(&freezer_lock);
    + spin_lock_irq(&current->sighand->siglock);
    + recalc_sigpending(); /* We sent fake signal, clean it up */
    + spin_unlock_irq(&current->sighand->siglock);

    pr_debug("%s left refrigerator\n", current->comm);

    --
    1.7.6


    \
     
     \ /
      Last update: 2011-09-02 20:31    [W:0.022 / U:0.472 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site