diff --git a/include/linux/timer.h b/include/linux/timer.h index 7b066fd38248..532e4ba2cfe3 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h @@ -172,6 +172,8 @@ extern void add_timer(struct timer_list *timer); extern int try_to_del_timer_sync(struct timer_list *timer); +extern struct timer_base timer_base_deferrable; + #ifdef CONFIG_SMP extern int del_timer_sync(struct timer_list *timer); #else diff --git a/kernel/time/timer.c b/kernel/time/timer.c index 343c7ba33b1c..65af3b1d8120 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -206,6 +206,7 @@ struct timer_base { } ____cacheline_aligned; static DEFINE_PER_CPU(struct timer_base, timer_bases[NR_BASES]); +struct timer_base timer_base_deferrable; #ifdef CONFIG_NO_HZ_COMMON @@ -837,8 +838,11 @@ static inline struct timer_base *get_timer_cpu_base(u32 tflags, u32 cpu) * If the timer is deferrable and NO_HZ_COMMON is set then we need * to use the deferrable base. */ - if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && (tflags & TIMER_DEFERRABLE)) - base = per_cpu_ptr(&timer_bases[BASE_DEF], cpu); + if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && (tflags & TIMER_DEFERRABLE)) { + base = &timer_base_deferrable; + if (tflags & TIMER_PINNED) + base = per_cpu_ptr(&timer_bases[BASE_DEF], cpu); + } return base; } @@ -850,8 +854,11 @@ static inline struct timer_base *get_timer_this_cpu_base(u32 tflags) * If the timer is deferrable and NO_HZ_COMMON is set then we need * to use the deferrable base. */ - if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && (tflags & TIMER_DEFERRABLE)) - base = this_cpu_ptr(&timer_bases[BASE_DEF]); + if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && (tflags & TIMER_DEFERRABLE)) { + base = &timer_base_deferrable; + if (tflags & TIMER_PINNED) + base = this_cpu_ptr(&timer_bases[BASE_DEF]); + } return base; } @@ -1696,8 +1703,10 @@ 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); - if (IS_ENABLED(CONFIG_NO_HZ_COMMON)) + if (IS_ENABLED(CONFIG_NO_HZ_COMMON)) { + __run_timers(&timer_base_deferrable); __run_timers(this_cpu_ptr(&timer_bases[BASE_DEF])); + } } /*