freezer: don't distinguish nosig tasks on thaw
[deliverable/linux.git] / kernel / freezer.c
index 66a594e8ad2fe8b37bc238e940f162392663d1bf..c851d588e29f115a2cf338793440e79282120381 100644 (file)
@@ -6,9 +6,10 @@
 
 #include <linux/interrupt.h>
 #include <linux/suspend.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/syscalls.h>
 #include <linux/freezer.h>
+#include <linux/kthread.h>
 
 /*
  * freezing is complete, mark current process as frozen
@@ -23,10 +24,11 @@ static inline void frozen_process(void)
 }
 
 /* Refrigerator is place where frozen processes are stored :-). */
-void refrigerator(void)
+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;
 
        task_lock(current);
@@ -35,7 +37,7 @@ void refrigerator(void)
                task_unlock(current);
        } else {
                task_unlock(current);
-               return;
+               return was_frozen;
        }
        save = current->state;
        pr_debug("%s entered refrigerator\n", current->comm);
@@ -49,8 +51,10 @@ void refrigerator(void)
 
        for (;;) {
                set_current_state(TASK_UNINTERRUPTIBLE);
-               if (!frozen(current))
+               if (!frozen(current) ||
+                   (check_kthr_stop && kthread_should_stop()))
                        break;
+               was_frozen = true;
                schedule();
        }
 
@@ -58,16 +62,24 @@ void refrigerator(void)
        current->flags &= ~PF_FREEZING;
 
        pr_debug("%s left refrigerator\n", current->comm);
-       __set_current_state(save);
+
+       /*
+        * Restore saved task state before returning.  The mb'd version
+        * needs to be used; otherwise, it might silently break
+        * synchronization which depends on ordered task state change.
+        */
+       set_current_state(save);
+
+       return was_frozen;
 }
-EXPORT_SYMBOL(refrigerator);
+EXPORT_SYMBOL(__refrigerator);
 
 static void fake_signal_wake_up(struct task_struct *p)
 {
        unsigned long flags;
 
        spin_lock_irqsave(&p->sighand->siglock, flags);
-       signal_wake_up(p, 1);
+       signal_wake_up(p, 0);
        spin_unlock_irqrestore(&p->sighand->siglock, flags);
 }
 
@@ -133,18 +145,8 @@ void cancel_freezing(struct task_struct *p)
        }
 }
 
-static int __thaw_process(struct task_struct *p)
-{
-       if (frozen(p)) {
-               p->flags &= ~PF_FROZEN;
-               return 1;
-       }
-       clear_freeze_flag(p);
-       return 0;
-}
-
 /*
- * Wake up a frozen process
+ * Wake up a frozen task
  *
  * task_lock() is needed to prevent the race with refrigerator() which may
  * occur if the freezing of tasks fails.  Namely, without the lock, if the
@@ -152,15 +154,18 @@ static int __thaw_process(struct task_struct *p)
  * refrigerator() could call frozen_process(), in which case the task would be
  * frozen and no one would thaw it.
  */
-int thaw_process(struct task_struct *p)
+void __thaw_task(struct task_struct *p)
 {
+       bool was_frozen;
+
        task_lock(p);
-       if (__thaw_process(p) == 1) {
-               task_unlock(p);
-               wake_up_process(p);
-               return 1;
-       }
+       was_frozen = frozen(p);
+       if (was_frozen)
+               p->flags &= ~PF_FROZEN;
+       else
+               clear_freeze_flag(p);
        task_unlock(p);
-       return 0;
+
+       if (was_frozen)
+               wake_up_process(p);
 }
-EXPORT_SYMBOL(thaw_process);
This page took 0.031307 seconds and 5 git commands to generate.