OSDN Git Service

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 d0b7d98..95a4141 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 fe27872..23822dc 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;
 }