Commit-ID:  c272ca58c3ec5631f4ab507489d9477f74efe645
Gitweb:     https://git.kernel.org/tip/c272ca58c3ec5631f4ab507489d9477f74efe645
Author:     Anna-Maria Gleixner <[email protected]>
AuthorDate: Thu, 21 Dec 2017 11:41:39 +0100
Committer:  Ingo Molnar <[email protected]>
CommitDate: Tue, 16 Jan 2018 02:35:46 +0100

hrtimer: Switch 'for' loop to _ffs() evaluation

Looping over all clock bases to find active bits is suboptimal if not all
bases are active.

Avoid this by converting it to a __ffs() evaluation. The functionallity is
outsourced into its own function and is called via a macro as suggested by
Peter Zijlstra.

Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Anna-Maria Gleixner <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: John Stultz <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: [email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
 kernel/time/hrtimer.c | 31 +++++++++++++++++++++----------
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index f4f4658..cfcf8de 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -448,6 +448,23 @@ static inline void debug_deactivate(struct hrtimer *timer)
        trace_hrtimer_cancel(timer);
 }
 
+static struct hrtimer_clock_base *
+__next_base(struct hrtimer_cpu_base *cpu_base, unsigned int *active)
+{
+       unsigned int idx;
+
+       if (!*active)
+               return NULL;
+
+       idx = __ffs(*active);
+       *active &= ~(1U << idx);
+
+       return &cpu_base->clock_base[idx];
+}
+
+#define for_each_active_base(base, cpu_base, active)   \
+       while ((base = __next_base((cpu_base), &(active))))
+
 #if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
 static inline void hrtimer_update_next_timer(struct hrtimer_cpu_base *cpu_base,
                                             struct hrtimer *timer)
@@ -459,18 +476,15 @@ static inline void hrtimer_update_next_timer(struct 
hrtimer_cpu_base *cpu_base,
 
 static ktime_t __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base)
 {
-       struct hrtimer_clock_base *base = cpu_base->clock_base;
+       struct hrtimer_clock_base *base;
        unsigned int active = cpu_base->active_bases;
        ktime_t expires, expires_next = KTIME_MAX;
 
        hrtimer_update_next_timer(cpu_base, NULL);
-       for (; active; base++, active >>= 1) {
+       for_each_active_base(base, cpu_base, active) {
                struct timerqueue_node *next;
                struct hrtimer *timer;
 
-               if (!(active & 0x01))
-                       continue;
-
                next = timerqueue_getnext(&base->active);
                timer = container_of(next, struct hrtimer, node);
                expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
@@ -1241,16 +1255,13 @@ static void __run_hrtimer(struct hrtimer_cpu_base 
*cpu_base,
 
 static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t 
now)
 {
-       struct hrtimer_clock_base *base = cpu_base->clock_base;
+       struct hrtimer_clock_base *base;
        unsigned int active = cpu_base->active_bases;
 
-       for (; active; base++, active >>= 1) {
+       for_each_active_base(base, cpu_base, active) {
                struct timerqueue_node *node;
                ktime_t basenow;
 
-               if (!(active & 0x01))
-                       continue;
-
                basenow = ktime_add(now, base->offset);
 
                while ((node = timerqueue_getnext(&base->active))) {

Reply via email to