[PATCH v2 09/37] hrtimer: Switch for loop to _ffs() evaluation

From: Anna-Maria Gleixner
Date: Sun Oct 22 2017 - 17:50:03 EST


From: Anna-Maria Gleixner <anna-maria@xxxxxxxxxxxxx>

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 an own function and is called via a macro as suggested by
Peter Zijlstra.

Suggested-by: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
Signed-off-by: Anna-Maria Gleixner <anna-maria@xxxxxxxxxxxxx>
---
kernel/time/hrtimer.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)

--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -464,20 +464,34 @@ static inline void hrtimer_update_next_t
#endif
}

+static struct hrtimer_clock_base *
+__next_base(struct hrtimer_cpu_base *cpu_base, unsigned int *active)
+{
+ struct hrtimer_clock_base *base = NULL;
+
+ if (*active) {
+ unsigned int idx = __ffs(*active);
+ *active &= ~(1U << idx);
+ base = &cpu_base->clock_base[idx];
+ }
+
+ return base;
+}
+
+#define for_each_active_base(base, cpu_base, active) \
+ while ((base = __next_base((cpu_base), &(active))))
+
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);
@@ -1250,16 +1264,13 @@ static void __run_hrtimer(struct hrtimer

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))) {