hrtimers: Avoid touching inactive timer bases
Instead of iterating over all possible timer bases avoid it by marking
the active bases in the cpu base.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Peter Zijlstra <peterz@infradead.org>
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 26dd32f..1b08f6d 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -64,17 +64,20 @@
.clock_base =
{
{
- .index = CLOCK_REALTIME,
+ .index = HRTIMER_BASE_REALTIME,
+ .clockid = CLOCK_REALTIME,
.get_time = &ktime_get_real,
.resolution = KTIME_LOW_RES,
},
{
- .index = CLOCK_MONOTONIC,
+ .index = HRTIMER_BASE_MONOTONIC,
+ .clockid = CLOCK_MONOTONIC,
.get_time = &ktime_get,
.resolution = KTIME_LOW_RES,
},
{
- .index = CLOCK_BOOTTIME,
+ .index = HRTIMER_BASE_BOOTTIME,
+ .clockid = CLOCK_BOOTTIME,
.get_time = &ktime_get_boottime,
.resolution = KTIME_LOW_RES,
},
@@ -196,7 +199,7 @@
struct hrtimer_cpu_base *new_cpu_base;
int this_cpu = smp_processor_id();
int cpu = hrtimer_get_target(this_cpu, pinned);
- int basenum = hrtimer_clockid_to_base(base->index);
+ int basenum = base->index;
again:
new_cpu_base = &per_cpu(hrtimer_bases, cpu);
@@ -857,6 +860,7 @@
debug_activate(timer);
timerqueue_add(&base->active, &timer->node);
+ base->cpu_base->active_bases |= 1 << base->index;
/*
* HRTIMER_STATE_ENQUEUED is or'ed to the current state to preserve the
@@ -898,6 +902,8 @@
#endif
}
timerqueue_del(&base->active, &timer->node);
+ if (!timerqueue_getnext(&base->active))
+ base->cpu_base->active_bases &= ~(1 << base->index);
out:
timer->state = newstate;
}
@@ -1235,7 +1241,6 @@
void hrtimer_interrupt(struct clock_event_device *dev)
{
struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
- struct hrtimer_clock_base *base;
ktime_t expires_next, now, entry_time, delta;
int i, retries = 0;
@@ -1257,12 +1262,15 @@
*/
cpu_base->expires_next.tv64 = KTIME_MAX;
- base = cpu_base->clock_base;
-
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
- ktime_t basenow;
+ struct hrtimer_clock_base *base;
struct timerqueue_node *node;
+ ktime_t basenow;
+ if (!(cpu_base->active_bases & (1 << i)))
+ continue;
+
+ base = cpu_base->clock_base + i;
basenow = ktime_add(now, base->offset);
while ((node = timerqueue_getnext(&base->active))) {
@@ -1295,7 +1303,6 @@
__run_hrtimer(timer, &basenow);
}
- base++;
}
/*
@@ -1526,7 +1533,7 @@
struct timespec __user *rmtp;
int ret = 0;
- hrtimer_init_on_stack(&t.timer, restart->nanosleep.index,
+ hrtimer_init_on_stack(&t.timer, restart->nanosleep.clockid,
HRTIMER_MODE_ABS);
hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires);
@@ -1578,7 +1585,7 @@
restart = ¤t_thread_info()->restart_block;
restart->fn = hrtimer_nanosleep_restart;
- restart->nanosleep.index = t.timer.base->index;
+ restart->nanosleep.clockid = t.timer.base->clockid;
restart->nanosleep.rmtp = rmtp;
restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 0791b13..58f405b 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -1514,7 +1514,7 @@
return -EFAULT;
restart_block->fn = posix_cpu_nsleep_restart;
- restart_block->nanosleep.index = which_clock;
+ restart_block->nanosleep.clockid = which_clock;
restart_block->nanosleep.rmtp = rmtp;
restart_block->nanosleep.expires = timespec_to_ns(rqtp);
}
@@ -1523,7 +1523,7 @@
static long posix_cpu_nsleep_restart(struct restart_block *restart_block)
{
- clockid_t which_clock = restart_block->nanosleep.index;
+ clockid_t which_clock = restart_block->nanosleep.clockid;
struct timespec t;
struct itimerspec it;
int error;
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index e5498d7..a1b5edf 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -1056,7 +1056,7 @@
*/
long clock_nanosleep_restart(struct restart_block *restart_block)
{
- clockid_t which_clock = restart_block->nanosleep.index;
+ clockid_t which_clock = restart_block->nanosleep.clockid;
struct k_clock *kc = clockid_to_kclock(which_clock);
if (WARN_ON_ONCE(!kc || !kc->nsleep_restart))
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index c6027fe..2d96624 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -494,7 +494,7 @@
*/
static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
{
- enum alarmtimer_type type = restart->nanosleep.index;
+ enum alarmtimer_type type = restart->nanosleep.clockid;
ktime_t exp;
struct timespec __user *rmtp;
struct alarm alarm;
@@ -573,7 +573,7 @@
restart = ¤t_thread_info()->restart_block;
restart->fn = alarm_timer_nsleep_restart;
- restart->nanosleep.index = type;
+ restart->nanosleep.clockid = type;
restart->nanosleep.expires = exp.tv64;
restart->nanosleep.rmtp = rmtp;
ret = -ERESTART_RESTARTBLOCK;