History

watchdog/softlockup: report the overall time of softlockups

The softlockup detector currently shows the time spent since the last report. As a result it is not clear whether a CPU is infinitely hogged by a single task or if it is a repeated event. The situation can be simulated with a simply busy loop: while (true) cpu_relax(); The softlockup detector produces: [ 168.277520] watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [cat:4865] [ 196.277604] watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [cat:4865] [ 236.277522] watchdog: BUG: soft lockup - CPU#1 stuck for 23s! [cat:4865] But it should be, something like: [ 480.372418] watchdog: BUG: soft lockup - CPU#2 stuck for 26s! [cat:4943] [ 508.372359] watchdog: BUG: soft lockup - CPU#2 stuck for 52s! [cat:4943] [ 548.372359] watchdog: BUG: soft lockup - CPU#2 stuck for 89s! [cat:4943] [ 576.372351] watchdog: BUG: soft lockup - CPU#2 stuck for 115s! [cat:4943] For the better output, add an additional timestamp of the last report. Only this timestamp is reset when the watchdog is intentionally touched from slow code paths or when printing the report.

Petr Mladek committed 5 years ago

Commit fef06ef1 parent c9ad17c1 file · +28 −12Browse files

Unified · Split

kernel/watchdog.c+28−12
@@ -154,7 +154,11 @@ static void lockup_detector_update_enable(void) · 153 unmodified lines
154154
155155 #ifdef CONFIG_SOFTLOCKUP_DETECTOR
156156
157−#define SOFTLOCKUP_RESET ULONG_MAX
157+/*
158+ * Delay the soflockup report when running a known slow code.
159+ * It does _not_ affect the timestamp of the last successdul reschedule.
160+ */
161+#define SOFTLOCKUP_DELAY_REPORT ULONG_MAX
158162
159163 #ifdef CONFIG_SMP
160164 int __read_mostly sysctl_softlockup_all_cpu_backtrace;
@@ -169,7 +173,10 @@ unsigned int __read_mostly softlockup_panic = · 8 unmodified lines
169173 static bool softlockup_initialized __read_mostly;
170174 static u64 __read_mostly sample_period;
171175
176+/* Timestamp taken after the last successful reschedule. */
172177 static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts);
178+/* Timestamp of the last softlockup report. */
179+static DEFINE_PER_CPU(unsigned long, watchdog_report_ts);
173180 static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer);
174181 static DEFINE_PER_CPU(bool, softlockup_touch_sync);
175182 static DEFINE_PER_CPU(bool, soft_watchdog_warn);
@@ -235,10 +242,16 @@ static void set_sample_period(void) · 59 unmodified lines
235242 watchdog_update_hrtimer_threshold(sample_period);
236243 }
237244
245+static void update_report_ts(void)
246+{
247+ __this_cpu_write(watchdog_report_ts, get_timestamp());
248+}
249+
238250 /* Commands for resetting the watchdog */
239251 static void update_touch_ts(void)
240252 {
241253 __this_cpu_write(watchdog_touch_ts, get_timestamp());
254+ update_report_ts();
242255 }
243256
244257 /**
@@ -252,10 +265,10 @@ static void update_touch_ts(void) · 7 unmodified lines
252265 notrace void touch_softlockup_watchdog_sched(void)
253266 {
254267 /*
255− * Preemption can be enabled. It doesn't matter which CPU's timestamp
256− * gets zeroed here, so use the raw_ operation.
268+ * Preemption can be enabled. It doesn't matter which CPU's watchdog
269+ * report period gets restarted here, so use the raw_ operation.
257270 */
258− raw_cpu_write(watchdog_touch_ts, SOFTLOCKUP_RESET);
271+ raw_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT);
259272 }
260273
261274 notrace void touch_softlockup_watchdog(void)
@@ -279,7 +292,7 @@ void touch_all_softlockup_watchdogs(void) · 17 unmodified lines
279292 * the softlockup check.
280293 */
281294 for_each_cpu(cpu, &watchdog_allowed_mask) {
282− per_cpu(watchdog_touch_ts, cpu) = SOFTLOCKUP_RESET;
295+ per_cpu(watchdog_report_ts, cpu) = SOFTLOCKUP_DELAY_REPORT;
283296 wq_watchdog_touch(cpu);
284297 }
285298 }
@@ -287,16 +300,16 @@ void touch_all_softlockup_watchdogs(void) · 1 unmodified line
287300 void touch_softlockup_watchdog_sync(void)
288301 {
289302 __this_cpu_write(softlockup_touch_sync, true);
290− __this_cpu_write(watchdog_touch_ts, SOFTLOCKUP_RESET);
303+ __this_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT);
291304 }
292305
293−static int is_softlockup(unsigned long touch_ts)
306+static int is_softlockup(unsigned long touch_ts, unsigned long period_ts)
294307 {
295308 unsigned long now = get_timestamp();
296309
297310 if ((watchdog_enabled & SOFT_WATCHDOG_ENABLED) && watchdog_thresh){
298311 /* Warn about unreasonable delays. */
299− if (time_after(now, touch_ts + get_softlockup_thresh()))
312+ if (time_after(now, period_ts + get_softlockup_thresh()))
300313 return now - touch_ts;
301314 }
302315 return 0;
@@ -342,6 +355,7 @@ static int softlockup_fn(void *data) · 39 unmodified lines
342355 static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
343356 {
344357 unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts);
358+ unsigned long period_ts = __this_cpu_read(watchdog_report_ts);
345359 struct pt_regs *regs = get_irq_regs();
346360 int duration;
347361 int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace;
@@ -363,7 +377,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) · 15 unmodified lines
363377 /* .. and repeat */
364378 hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period));
365379
366− if (touch_ts == SOFTLOCKUP_RESET) {
380+ /* Reset the interval when touched externally by a known slow code. */
381+ if (period_ts == SOFTLOCKUP_DELAY_REPORT) {
367382 if (unlikely(__this_cpu_read(softlockup_touch_sync))) {
368383 /*
369384 * If the time stamp was touched atomically
@@ -375,7 +390,8 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) · 5 unmodified lines
375390
376391 /* Clear the guest paused flag on watchdog reset */
377392 kvm_check_and_clear_guest_paused();
378− update_touch_ts();
393+ update_report_ts();
394+
379395 return HRTIMER_RESTART;
380396 }
381397
@@ -385,7 +401,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) · 3 unmodified lines
385401 * indicate it is getting cpu time. If it hasn't then
386402 * this is a good indication some task is hogging the cpu
387403 */
388− duration = is_softlockup(touch_ts);
404+ duration = is_softlockup(touch_ts, period_ts);
389405 if (unlikely(duration)) {
390406 /*
391407 * If a virtual machine is stopped by the host it can look to
@@ -411,7 +427,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) · 19 unmodified lines
411427 }
412428
413429 /* Start period for the next softlockup warning. */
414− update_touch_ts();
430+ update_report_ts();
415431
416432 pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
417433 smp_processor_id(), duration,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t