In the while loop of __run_timers(), because there are too many timers or improper timer handler functions, if the processing time of the expired timers is always greater than the time wheel's next_expiry, the function will loop infinitely. To prevent this, use the timeout/break logic provided by SoftIRQs. If the running time exceeds the limit, break the loop and an additional TIMER_SOFTIRQ is triggered. Signed-off-by: Liu Jian <liujian56@xxxxxxxxxx> --- kernel/time/timer.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 63a8ce7177dd..70744a469a39 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1992,7 +1992,7 @@ void timer_clear_idle(void) * __run_timers - run all expired timers (if any) on this CPU. * @base: the timer vector to be processed. */ -static inline void __run_timers(struct timer_base *base) +static inline void __run_timers(struct timer_base *base, struct softirq_action *h) { struct hlist_head heads[LVL_DEPTH]; int levels; @@ -2020,6 +2020,12 @@ static inline void __run_timers(struct timer_base *base) while (levels--) expire_timers(base, heads + levels); + + if (softirq_needs_break(h)) { + if (time_after_eq(jiffies, base->next_expiry)) + __raise_softirq_irqoff(TIMER_SOFTIRQ); + break; + } } raw_spin_unlock_irq(&base->lock); timer_base_unlock_expiry(base); @@ -2032,9 +2038,9 @@ static __latent_entropy void run_timer_softirq(struct softirq_action *h) { struct timer_base *base = this_cpu_ptr(&timer_bases[BASE_STD]); - __run_timers(base); + __run_timers(base, h); if (IS_ENABLED(CONFIG_NO_HZ_COMMON)) - __run_timers(this_cpu_ptr(&timer_bases[BASE_DEF])); + __run_timers(this_cpu_ptr(&timer_bases[BASE_DEF]), h); } /* -- 2.34.1