summaryrefslogtreecommitdiff
path: root/kernel/watchdog_buddy.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/watchdog_buddy.c')
-rw-r--r--kernel/watchdog_buddy.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/kernel/watchdog_buddy.c b/kernel/watchdog_buddy.c
index 2ef88722c5e7..34dbfe091f4b 100644
--- a/kernel/watchdog_buddy.c
+++ b/kernel/watchdog_buddy.c
@@ -51,6 +51,13 @@ void watchdog_hardlockup_enable(unsigned int cpu)
if (next_cpu < nr_cpu_ids)
watchdog_hardlockup_touch_cpu(next_cpu);
+ /*
+ * Makes sure that watchdog is touched on this CPU before
+ * other CPUs could see it in watchdog_cpus. The counter
+ * part is in watchdog_buddy_check_hardlockup().
+ */
+ smp_wmb();
+
cpumask_set_cpu(cpu, &watchdog_cpus);
}
@@ -68,6 +75,13 @@ void watchdog_hardlockup_disable(unsigned int cpu)
if (next_cpu < nr_cpu_ids)
watchdog_hardlockup_touch_cpu(next_cpu);
+ /*
+ * Makes sure that watchdog is touched on the next CPU before
+ * this CPU disappear in watchdog_cpus. The counter part is in
+ * watchdog_buddy_check_hardlockup().
+ */
+ smp_wmb();
+
cpumask_clear_cpu(cpu, &watchdog_cpus);
}
@@ -88,5 +102,12 @@ void watchdog_buddy_check_hardlockup(int hrtimer_interrupts)
if (next_cpu >= nr_cpu_ids)
return;
+ /*
+ * Make sure that the watchdog was touched on next CPU when
+ * watchdog_next_cpu() returned another one because of
+ * a change in watchdog_hardlockup_enable()/disable().
+ */
+ smp_rmb();
+
watchdog_hardlockup_check(next_cpu, NULL);
}