freezer: remove racy clear_freeze_flag() and set PF_NOFREEZE on dead tasks
authorTejun Heo <tj@kernel.org>
Mon, 21 Nov 2011 20:32:23 +0000 (12:32 -0800)
committerTejun Heo <tj@kernel.org>
Mon, 21 Nov 2011 20:32:23 +0000 (12:32 -0800)
clear_freeze_flag() in exit_mm() is racy.  Freezing can start
afterwards.  Remove it.  Skipping freezer for exiting task will be
properly implemented later.

Also, freezable() was testing exit_state directly to make system
freezer ignore dead tasks.  Let the exiting task set PF_NOFREEZE after
entering TASK_DEAD instead.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
kernel/exit.c
kernel/power/process.c

index d0b7d988f8735beb6e1e7b5f7b42ecbd04b91bf5..95a4141d07e7ba4c87e478a77e5555d69c8e0253 100644 (file)
@@ -679,8 +679,6 @@ static void exit_mm(struct task_struct * tsk)
        tsk->mm = NULL;
        up_read(&mm->mmap_sem);
        enter_lazy_tlb(mm, current);
-       /* We don't want this task to be frozen prematurely */
-       clear_freeze_flag(tsk);
        task_unlock(tsk);
        mm_update_next_owner(mm);
        mmput(mm);
@@ -1040,6 +1038,7 @@ NORET_TYPE void do_exit(long code)
        exit_rcu();
        /* causes final put_task_struct in finish_task_switch(). */
        tsk->state = TASK_DEAD;
+       tsk->flags |= PF_NOFREEZE;      /* tell freezer to ignore us */
        schedule();
        BUG();
        /* Avoid "noreturn function does return".  */
index fe2787207f00d665371ca72a57c3508d2cdbd000..23822dc14b6c14e61b718053cdee5d044e2bdc76 100644 (file)
@@ -25,8 +25,7 @@
 static inline int freezable(struct task_struct * p)
 {
        if ((p == current) ||
-           (p->flags & PF_NOFREEZE) ||
-           (p->exit_state != 0))
+           (p->flags & PF_NOFREEZE))
                return 0;
        return 1;
 }