Skip to content

Commit

Permalink
timers: Optimize get_timer_[this_]cpu_base()
Browse files Browse the repository at this point in the history
If a timer is deferrable and NO_HZ_COMMON is enabled, get_timer_cpu_base()
and get_timer_this_cpu_base() invoke per_cpu_ptr() and this_cpu_ptr()
twice.

While this seems to be cheap, get_timer_cpu_base() can be called in a loop
in lock_timer_base().

Optimize the functions by updating the base index for deferrable timers and
retrieving the actual base pointer once.

In both cases the resulting assembly code of those helpers becomes smaller,
which results in a ~30% execution time reduction for a lock_timer_base()
micro bench mark.

Signed-off-by: Zhongqiu Han <quic_zhonhan@quicinc.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/all/20241231150115.1978342-1-quic_zhonhan@quicinc.com
  • Loading branch information
Zhongqiu Han authored and Thomas Gleixner committed Jan 16, 2025
1 parent 2d2a46c commit 3ec9557
Showing 1 changed file with 6 additions and 10 deletions.
16 changes: 6 additions & 10 deletions kernel/time/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,33 +956,29 @@ static int detach_if_pending(struct timer_list *timer, struct timer_base *base,
static inline struct timer_base *get_timer_cpu_base(u32 tflags, u32 cpu)
{
int index = tflags & TIMER_PINNED ? BASE_LOCAL : BASE_GLOBAL;
struct timer_base *base;

base = per_cpu_ptr(&timer_bases[index], 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);
return base;
index = BASE_DEF;

return per_cpu_ptr(&timer_bases[index], cpu);
}

static inline struct timer_base *get_timer_this_cpu_base(u32 tflags)
{
int index = tflags & TIMER_PINNED ? BASE_LOCAL : BASE_GLOBAL;
struct timer_base *base;

base = this_cpu_ptr(&timer_bases[index]);

/*
* 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]);
return base;
index = BASE_DEF;

return this_cpu_ptr(&timer_bases[index]);
}

static inline struct timer_base *get_timer_base(u32 tflags)
Expand Down

0 comments on commit 3ec9557

Please sign in to comment.