Subject: softirq: Use sched_clock() based timeout From: Peter Zijlstra Date: Fri Sep 11 17:30:01 CEST 2020 From: Peter Zijlstra Jiffies based timeouts depend on the HZ value and the resulting granularity is between 1ms and 10ms. That does not allow to terminate the softirq processing loop precisely independent of the kernel configuration. Replace the jiffies based timeout with a sched_clock() based one. Note, that for systems which lack proper hardware sched_clock() is jiffies based and the change has no effect on them. [ tglx: Simplified the timeout condition by calculating the break time once and updated changelog. ] Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Thomas Gleixner --- kernel/softirq.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -25,6 +25,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -216,8 +217,8 @@ EXPORT_SYMBOL(__local_bh_enable_ip); * we want to handle softirqs as soon as possible, but they * should not be able to lock up the box. */ -#define MAX_SOFTIRQ_TIME msecs_to_jiffies(2) -#define MAX_SOFTIRQ_RESTART 10 +#define MAX_SOFTIRQ_TIME (2 * NSEC_PER_MSEC) +#define MAX_SOFTIRQ_RESTART 10 #ifdef CONFIG_TRACE_IRQFLAGS /* @@ -255,6 +256,7 @@ static inline void lockdep_softirq_end(b asmlinkage __visible void __softirq_entry __do_softirq(void) { unsigned int vec_nr, max_restart = MAX_SOFTIRQ_RESTART; + u64 tbreak = sched_clock() + MAX_SOFTIRQ_TIME; unsigned long old_flags = current->flags; struct softirq_action *h; unsigned long pending; @@ -304,8 +306,7 @@ asmlinkage __visible void __softirq_entr pending = local_softirq_pending(); if (pending) { - if (time_before(jiffies, end) && !need_resched() && - --max_restart) + if (sched_clock() < tbreak && !need_resched() && --max_restart) goto restart; wakeup_softirqd();