diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2006-03-26 01:38:05 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-26 08:57:02 -0800 |
commit | 92127c7a45d4d167d9b015a5f9de6b41ed66f1d0 (patch) | |
tree | 4742cc36ff0b26c999365d1e84133886bb694096 /kernel/hrtimer.c | |
parent | a0e9285233a32edf267d27cd03fe0056951422cf (diff) | |
download | lwn-92127c7a45d4d167d9b015a5f9de6b41ed66f1d0.tar.gz lwn-92127c7a45d4d167d9b015a5f9de6b41ed66f1d0.zip |
[PATCH] hrtimers: optimize softirq runqueues
The hrtimer softirq is called from the timer softirq every tick. Retrieve the
current time from xtime and wall_to_monotonic instead of calling
base->get_time() for each timer base. Store the time in the base structure
and provide a hook once clock source abstractions are in place and to keep the
code open for new base clocks.
Based on a patch from: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r-- | kernel/hrtimer.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 14bc9cfa6399..b728cc53452b 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -123,6 +123,26 @@ void ktime_get_ts(struct timespec *ts) EXPORT_SYMBOL_GPL(ktime_get_ts); /* + * Get the coarse grained time at the softirq based on xtime and + * wall_to_monotonic. + */ +static void hrtimer_get_softirq_time(struct hrtimer_base *base) +{ + ktime_t xtim, tomono; + unsigned long seq; + + do { + seq = read_seqbegin(&xtime_lock); + xtim = timespec_to_ktime(xtime); + tomono = timespec_to_ktime(wall_to_monotonic); + + } while (read_seqretry(&xtime_lock, seq)); + + base[CLOCK_REALTIME].softirq_time = xtim; + base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono); +} + +/* * Functions and macros which are different for UP/SMP systems are kept in a * single place */ @@ -586,9 +606,11 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp) */ static inline void run_hrtimer_queue(struct hrtimer_base *base) { - ktime_t now = base->get_time(); struct rb_node *node; + if (base->get_softirq_time) + base->softirq_time = base->get_softirq_time(); + spin_lock_irq(&base->lock); while ((node = base->first)) { @@ -598,7 +620,7 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base) void *data; timer = rb_entry(node, struct hrtimer, node); - if (now.tv64 <= timer->expires.tv64) + if (base->softirq_time.tv64 <= timer->expires.tv64) break; fn = timer->function; @@ -641,6 +663,8 @@ void hrtimer_run_queues(void) struct hrtimer_base *base = __get_cpu_var(hrtimer_bases); int i; + hrtimer_get_softirq_time(base); + for (i = 0; i < MAX_HRTIMER_BASES; i++) run_hrtimer_queue(&base[i]); } |