Skip to content

Commit a19f893

Browse files
Julia CartwrightWim Van Sebroeck
authored andcommitted
watchdog: prevent deferral of watchdogd wakeup on RT
When PREEMPT_RT is enabled, all hrtimer expiry functions are deferred for execution into the context of ksoftirqd unless otherwise annotated. Deferring the expiry of the hrtimer used by the watchdog core, however, is a waste, as the callback does nothing but queue a kthread work item and wakeup watchdogd. It's worst then that, too: the deferral through ksoftirqd also means that for correct behavior a user must adjust the scheduling parameters of both watchdogd _and_ ksoftirqd, which is unnecessary and has other side effects (like causing unrelated expiry functions to execute at potentially elevated priority). Instead, mark the hrtimer used by the watchdog core as being _HARD to allow it's execution directly from hardirq context. The work done in this expiry function is well-bounded and minimal. A user still must adjust the scheduling parameters of the watchdogd to be correct w.r.t. their application needs. Link: https://lkml.kernel.org/r/0e02d8327aeca344096c246713033887bc490dd7.1538089180.git.julia@ni.com Cc: Guenter Roeck <[email protected]> Reported-and-tested-by: Steffen Trumtrar <[email protected]> Reported-by: Tim Sander <[email protected]> Signed-off-by: Julia Cartwright <[email protected]> Acked-by: Guenter Roeck <[email protected]> [bigeasy: use only HRTIMER_MODE_REL_HARD] Signed-off-by: Sebastian Andrzej Siewior <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Guenter Roeck <[email protected]> Signed-off-by: Wim Van Sebroeck <[email protected]>
1 parent eccb7fe commit a19f893

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

drivers/watchdog/watchdog_dev.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ static inline void watchdog_update_worker(struct watchdog_device *wdd)
157157
ktime_t t = watchdog_next_keepalive(wdd);
158158

159159
if (t > 0)
160-
hrtimer_start(&wd_data->timer, t, HRTIMER_MODE_REL);
160+
hrtimer_start(&wd_data->timer, t,
161+
HRTIMER_MODE_REL_HARD);
161162
} else {
162163
hrtimer_cancel(&wd_data->timer);
163164
}
@@ -176,7 +177,7 @@ static int __watchdog_ping(struct watchdog_device *wdd)
176177
if (ktime_after(earliest_keepalive, now)) {
177178
hrtimer_start(&wd_data->timer,
178179
ktime_sub(earliest_keepalive, now),
179-
HRTIMER_MODE_REL);
180+
HRTIMER_MODE_REL_HARD);
180181
return 0;
181182
}
182183

@@ -974,7 +975,7 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
974975
return -ENODEV;
975976

976977
kthread_init_work(&wd_data->work, watchdog_ping_work);
977-
hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
978+
hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
978979
wd_data->timer.function = watchdog_timer_expired;
979980

980981
if (wdd->id == 0) {
@@ -1032,7 +1033,8 @@ static int watchdog_cdev_register(struct watchdog_device *wdd)
10321033
__module_get(wdd->ops->owner);
10331034
get_device(&wd_data->dev);
10341035
if (handle_boot_enabled)
1035-
hrtimer_start(&wd_data->timer, 0, HRTIMER_MODE_REL);
1036+
hrtimer_start(&wd_data->timer, 0,
1037+
HRTIMER_MODE_REL_HARD);
10361038
else
10371039
pr_info("watchdog%d running and kernel based pre-userspace handler disabled\n",
10381040
wdd->id);

0 commit comments

Comments
 (0)