]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
timers: Optimize get_timer_[this_]cpu_base()
authorZhongqiu Han <quic_zhonhan@quicinc.com>
Tue, 31 Dec 2024 15:01:15 +0000 (23:01 +0800)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 16 Jan 2025 08:04:23 +0000 (09:04 +0100)
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
kernel/time/timer.c

index a5860bf6d16f97f5457a89c6e481ec8963c20c3f..40706cb3692053a0fcfbe8187a223ac4386dd0e6 100644 (file)
@@ -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)