Commit 833883d9 authored by Dimitri Sivanich's avatar Dimitri Sivanich Committed by Thomas Gleixner

hrtimer: reduce calls to hrtimer_get_softirq_time()

It seems that hrtimer_run_queues() is calling hrtimer_get_softirq_time() more
often than it needs to.  This can cause frequent contention on systems with
large numbers of processors/cores.

With this patch, hrtimer_run_queues only calls hrtimer_get_softirq_time() if
there is a pending timer in one of the hrtimer bases, and only once.

This also combines hrtimer_run_queues() and the inline run_hrtimer_queue()
into one function.

[ tglx@linutronix.de: coding style ]
Signed-off-by: default avatarDimitri Sivanich <sivanich@sgi.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 833df317
...@@ -1238,15 +1238,27 @@ void hrtimer_run_pending(void) ...@@ -1238,15 +1238,27 @@ void hrtimer_run_pending(void)
/* /*
* Called from hardirq context every jiffy * Called from hardirq context every jiffy
*/ */
static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base, void hrtimer_run_queues(void)
int index)
{ {
struct rb_node *node; struct rb_node *node;
struct hrtimer_clock_base *base = &cpu_base->clock_base[index]; struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
struct hrtimer_clock_base *base;
int index, gettime = 1;
if (!base->first) if (hrtimer_hres_active())
return; return;
for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
base = &cpu_base->clock_base[index];
if (!base->first)
continue;
if (gettime) {
hrtimer_get_softirq_time(cpu_base);
gettime = 0;
}
if (base->get_softirq_time) if (base->get_softirq_time)
base->softirq_time = base->get_softirq_time(); base->softirq_time = base->get_softirq_time();
...@@ -1260,7 +1272,8 @@ static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base, ...@@ -1260,7 +1272,8 @@ static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
break; break;
if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) { if (timer->cb_mode == HRTIMER_CB_SOFTIRQ) {
__remove_hrtimer(timer, base, HRTIMER_STATE_PENDING, 0); __remove_hrtimer(timer, base,
HRTIMER_STATE_PENDING, 0);
list_add_tail(&timer->cb_entry, list_add_tail(&timer->cb_entry,
&base->cpu_base->cb_pending); &base->cpu_base->cb_pending);
continue; continue;
...@@ -1269,20 +1282,7 @@ static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base, ...@@ -1269,20 +1282,7 @@ static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
__run_hrtimer(timer); __run_hrtimer(timer);
} }
spin_unlock(&cpu_base->lock); spin_unlock(&cpu_base->lock);
} }
void hrtimer_run_queues(void)
{
struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
int i;
if (hrtimer_hres_active())
return;
hrtimer_get_softirq_time(cpu_base);
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
run_hrtimer_queue(cpu_base, i);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment