提交 ab8177bc 编写于 作者: T Thomas Gleixner

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: NThomas Gleixner <tglx@linutronix.de>
Reviewed-by: NPeter Zijlstra <peterz@infradead.org>
上级 f24444b0
...@@ -143,7 +143,8 @@ struct hrtimer_sleeper { ...@@ -143,7 +143,8 @@ struct hrtimer_sleeper {
*/ */
struct hrtimer_clock_base { struct hrtimer_clock_base {
struct hrtimer_cpu_base *cpu_base; struct hrtimer_cpu_base *cpu_base;
clockid_t index; int index;
clockid_t clockid;
struct timerqueue_head active; struct timerqueue_head active;
ktime_t resolution; ktime_t resolution;
ktime_t (*get_time)(void); ktime_t (*get_time)(void);
...@@ -162,7 +163,7 @@ enum hrtimer_base_type { ...@@ -162,7 +163,7 @@ enum hrtimer_base_type {
* struct hrtimer_cpu_base - the per cpu clock bases * struct hrtimer_cpu_base - the per cpu clock bases
* @lock: lock protecting the base and associated clock bases * @lock: lock protecting the base and associated clock bases
* and timers * and timers
* @clock_base: array of clock bases for this cpu * @active_bases: Bitfield to mark bases with active timers
* @expires_next: absolute time of the next event which was scheduled * @expires_next: absolute time of the next event which was scheduled
* via clock_set_next_event() * via clock_set_next_event()
* @hres_active: State of high resolution mode * @hres_active: State of high resolution mode
...@@ -171,9 +172,11 @@ enum hrtimer_base_type { ...@@ -171,9 +172,11 @@ enum hrtimer_base_type {
* @nr_retries: Total number of hrtimer interrupt retries * @nr_retries: Total number of hrtimer interrupt retries
* @nr_hangs: Total number of hrtimer interrupt hangs * @nr_hangs: Total number of hrtimer interrupt hangs
* @max_hang_time: Maximum time spent in hrtimer_interrupt * @max_hang_time: Maximum time spent in hrtimer_interrupt
* @clock_base: array of clock bases for this cpu
*/ */
struct hrtimer_cpu_base { struct hrtimer_cpu_base {
raw_spinlock_t lock; raw_spinlock_t lock;
unsigned long active_bases;
#ifdef CONFIG_HIGH_RES_TIMERS #ifdef CONFIG_HIGH_RES_TIMERS
ktime_t expires_next; ktime_t expires_next;
int hres_active; int hres_active;
......
...@@ -29,7 +29,7 @@ struct restart_block { ...@@ -29,7 +29,7 @@ struct restart_block {
} futex; } futex;
/* For nanosleep */ /* For nanosleep */
struct { struct {
clockid_t index; clockid_t clockid;
struct timespec __user *rmtp; struct timespec __user *rmtp;
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
struct compat_timespec __user *compat_rmtp; struct compat_timespec __user *compat_rmtp;
......
...@@ -64,17 +64,20 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = ...@@ -64,17 +64,20 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
.clock_base = .clock_base =
{ {
{ {
.index = CLOCK_REALTIME, .index = HRTIMER_BASE_REALTIME,
.clockid = CLOCK_REALTIME,
.get_time = &ktime_get_real, .get_time = &ktime_get_real,
.resolution = KTIME_LOW_RES, .resolution = KTIME_LOW_RES,
}, },
{ {
.index = CLOCK_MONOTONIC, .index = HRTIMER_BASE_MONOTONIC,
.clockid = CLOCK_MONOTONIC,
.get_time = &ktime_get, .get_time = &ktime_get,
.resolution = KTIME_LOW_RES, .resolution = KTIME_LOW_RES,
}, },
{ {
.index = CLOCK_BOOTTIME, .index = HRTIMER_BASE_BOOTTIME,
.clockid = CLOCK_BOOTTIME,
.get_time = &ktime_get_boottime, .get_time = &ktime_get_boottime,
.resolution = KTIME_LOW_RES, .resolution = KTIME_LOW_RES,
}, },
...@@ -196,7 +199,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base, ...@@ -196,7 +199,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
struct hrtimer_cpu_base *new_cpu_base; struct hrtimer_cpu_base *new_cpu_base;
int this_cpu = smp_processor_id(); int this_cpu = smp_processor_id();
int cpu = hrtimer_get_target(this_cpu, pinned); int cpu = hrtimer_get_target(this_cpu, pinned);
int basenum = hrtimer_clockid_to_base(base->index); int basenum = base->index;
again: again:
new_cpu_base = &per_cpu(hrtimer_bases, cpu); new_cpu_base = &per_cpu(hrtimer_bases, cpu);
...@@ -857,6 +860,7 @@ static int enqueue_hrtimer(struct hrtimer *timer, ...@@ -857,6 +860,7 @@ static int enqueue_hrtimer(struct hrtimer *timer,
debug_activate(timer); debug_activate(timer);
timerqueue_add(&base->active, &timer->node); 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 * HRTIMER_STATE_ENQUEUED is or'ed to the current state to preserve the
...@@ -898,6 +902,8 @@ static void __remove_hrtimer(struct hrtimer *timer, ...@@ -898,6 +902,8 @@ static void __remove_hrtimer(struct hrtimer *timer,
#endif #endif
} }
timerqueue_del(&base->active, &timer->node); timerqueue_del(&base->active, &timer->node);
if (!timerqueue_getnext(&base->active))
base->cpu_base->active_bases &= ~(1 << base->index);
out: out:
timer->state = newstate; timer->state = newstate;
} }
...@@ -1235,7 +1241,6 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) ...@@ -1235,7 +1241,6 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
void hrtimer_interrupt(struct clock_event_device *dev) void hrtimer_interrupt(struct clock_event_device *dev)
{ {
struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
struct hrtimer_clock_base *base;
ktime_t expires_next, now, entry_time, delta; ktime_t expires_next, now, entry_time, delta;
int i, retries = 0; int i, retries = 0;
...@@ -1257,12 +1262,15 @@ void hrtimer_interrupt(struct clock_event_device *dev) ...@@ -1257,12 +1262,15 @@ void hrtimer_interrupt(struct clock_event_device *dev)
*/ */
cpu_base->expires_next.tv64 = KTIME_MAX; cpu_base->expires_next.tv64 = KTIME_MAX;
base = cpu_base->clock_base;
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
ktime_t basenow; struct hrtimer_clock_base *base;
struct timerqueue_node *node; 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); basenow = ktime_add(now, base->offset);
while ((node = timerqueue_getnext(&base->active))) { while ((node = timerqueue_getnext(&base->active))) {
...@@ -1295,7 +1303,6 @@ void hrtimer_interrupt(struct clock_event_device *dev) ...@@ -1295,7 +1303,6 @@ void hrtimer_interrupt(struct clock_event_device *dev)
__run_hrtimer(timer, &basenow); __run_hrtimer(timer, &basenow);
} }
base++;
} }
/* /*
...@@ -1526,7 +1533,7 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart) ...@@ -1526,7 +1533,7 @@ long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
struct timespec __user *rmtp; struct timespec __user *rmtp;
int ret = 0; 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_MODE_ABS);
hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires); hrtimer_set_expires_tv64(&t.timer, restart->nanosleep.expires);
...@@ -1578,7 +1585,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, ...@@ -1578,7 +1585,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
restart = &current_thread_info()->restart_block; restart = &current_thread_info()->restart_block;
restart->fn = hrtimer_nanosleep_restart; 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.rmtp = rmtp;
restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer); restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer);
......
...@@ -1514,7 +1514,7 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags, ...@@ -1514,7 +1514,7 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
return -EFAULT; return -EFAULT;
restart_block->fn = posix_cpu_nsleep_restart; 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.rmtp = rmtp;
restart_block->nanosleep.expires = timespec_to_ns(rqtp); restart_block->nanosleep.expires = timespec_to_ns(rqtp);
} }
...@@ -1523,7 +1523,7 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags, ...@@ -1523,7 +1523,7 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
static long posix_cpu_nsleep_restart(struct restart_block *restart_block) 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 timespec t;
struct itimerspec it; struct itimerspec it;
int error; int error;
......
...@@ -1056,7 +1056,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags, ...@@ -1056,7 +1056,7 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
*/ */
long clock_nanosleep_restart(struct restart_block *restart_block) 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); struct k_clock *kc = clockid_to_kclock(which_clock);
if (WARN_ON_ONCE(!kc || !kc->nsleep_restart)) if (WARN_ON_ONCE(!kc || !kc->nsleep_restart))
......
...@@ -494,7 +494,7 @@ static int update_rmtp(ktime_t exp, enum alarmtimer_type type, ...@@ -494,7 +494,7 @@ static int update_rmtp(ktime_t exp, enum alarmtimer_type type,
*/ */
static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) 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; ktime_t exp;
struct timespec __user *rmtp; struct timespec __user *rmtp;
struct alarm alarm; struct alarm alarm;
...@@ -573,7 +573,7 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, ...@@ -573,7 +573,7 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
restart = &current_thread_info()->restart_block; restart = &current_thread_info()->restart_block;
restart->fn = alarm_timer_nsleep_restart; restart->fn = alarm_timer_nsleep_restart;
restart->nanosleep.index = type; restart->nanosleep.clockid = type;
restart->nanosleep.expires = exp.tv64; restart->nanosleep.expires = exp.tv64;
restart->nanosleep.rmtp = rmtp; restart->nanosleep.rmtp = rmtp;
ret = -ERESTART_RESTARTBLOCK; ret = -ERESTART_RESTARTBLOCK;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册