irq: enable suspended EARLY_RESUME irqs forcefully if not resumed
[linux-3.10.git] / kernel / hung_task.c
index ea64012..6df6149 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/freezer.h>
 #include <linux/kthread.h>
 #include <linux/lockdep.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sysctl.h>
 
 /*
@@ -74,11 +74,17 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
 
        /*
         * Ensure the task is not frozen.
-        * Also, when a freshly created task is scheduled once, changes
-        * its state to TASK_UNINTERRUPTIBLE without having ever been
-        * switched out once, it musn't be checked.
+        * Also, skip vfork and any other user process that freezer should skip.
         */
-       if (unlikely(t->flags & PF_FROZEN || !switch_count))
+       if (unlikely(t->flags & (PF_FROZEN | PF_FREEZER_SKIP)))
+           return;
+
+       /*
+        * When a freshly created task is scheduled once, changes its state to
+        * TASK_UNINTERRUPTIBLE without having ever been switched out once, it
+        * musn't be checked.
+        */
+       if (unlikely(!switch_count))
                return;
 
        if (switch_count != t->last_switch_count) {
@@ -102,8 +108,10 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
 
        touch_nmi_watchdog();
 
-       if (sysctl_hung_task_panic)
+       if (sysctl_hung_task_panic) {
+               trigger_all_cpu_backtrace();
                panic("hung_task: blocked tasks");
+       }
 }
 
 /*
@@ -113,15 +121,20 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
  * For preemptible RCU it is sufficient to call rcu_read_unlock in order
  * to exit the grace period. For classic RCU, a reschedule is required.
  */
-static void rcu_lock_break(struct task_struct *g, struct task_struct *t)
+static bool rcu_lock_break(struct task_struct *g, struct task_struct *t)
 {
+       bool can_cont;
+
        get_task_struct(g);
        get_task_struct(t);
        rcu_read_unlock();
        cond_resched();
        rcu_read_lock();
+       can_cont = pid_alive(g) && pid_alive(t);
        put_task_struct(t);
        put_task_struct(g);
+
+       return can_cont;
 }
 
 /*
@@ -148,9 +161,7 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
                        goto unlock;
                if (!--batch_count) {
                        batch_count = HUNG_TASK_BATCHING;
-                       rcu_lock_break(g, t);
-                       /* Exit if t or g was unhashed during refresh. */
-                       if (t->state == TASK_DEAD || g->state == TASK_DEAD)
+                       if (!rcu_lock_break(g, t))
                                goto unlock;
                }
                /* use "==" to skip the TASK_KILLABLE tasks waiting on NFS */