|
@@ -47,6 +47,7 @@ static DEFINE_PER_CPU(bool, softlockup_touch_sync);
|
|
|
static DEFINE_PER_CPU(bool, soft_watchdog_warn);
|
|
|
static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts);
|
|
|
static DEFINE_PER_CPU(unsigned long, soft_lockup_hrtimer_cnt);
|
|
|
+static DEFINE_PER_CPU(struct task_struct *, softlockup_task_ptr_saved);
|
|
|
#ifdef CONFIG_HARDLOCKUP_DETECTOR
|
|
|
static DEFINE_PER_CPU(bool, hard_watchdog_warn);
|
|
|
static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
|
|
@@ -333,8 +334,22 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
|
|
return HRTIMER_RESTART;
|
|
|
|
|
|
/* only warn once */
|
|
|
- if (__this_cpu_read(soft_watchdog_warn) == true)
|
|
|
+ if (__this_cpu_read(soft_watchdog_warn) == true) {
|
|
|
+ /*
|
|
|
+ * When multiple processes are causing softlockups the
|
|
|
+ * softlockup detector only warns on the first one
|
|
|
+ * because the code relies on a full quiet cycle to
|
|
|
+ * re-arm. The second process prevents the quiet cycle
|
|
|
+ * and never gets reported. Use task pointers to detect
|
|
|
+ * this.
|
|
|
+ */
|
|
|
+ if (__this_cpu_read(softlockup_task_ptr_saved) !=
|
|
|
+ current) {
|
|
|
+ __this_cpu_write(soft_watchdog_warn, false);
|
|
|
+ __touch_watchdog();
|
|
|
+ }
|
|
|
return HRTIMER_RESTART;
|
|
|
+ }
|
|
|
|
|
|
if (softlockup_all_cpu_backtrace) {
|
|
|
/* Prevent multiple soft-lockup reports if one cpu is already
|
|
@@ -350,6 +365,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
|
|
pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
|
|
|
smp_processor_id(), duration,
|
|
|
current->comm, task_pid_nr(current));
|
|
|
+ __this_cpu_write(softlockup_task_ptr_saved, current);
|
|
|
print_modules();
|
|
|
print_irqtrace_events(current);
|
|
|
if (regs)
|