aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2006-03-26 04:38:05 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-26 11:57:02 -0500
commit92127c7a45d4d167d9b015a5f9de6b41ed66f1d0 (patch)
tree4742cc36ff0b26c999365d1e84133886bb694096
parenta0e9285233a32edf267d27cd03fe0056951422cf (diff)
[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>
-rw-r--r--include/linux/hrtimer.h20
-rw-r--r--kernel/hrtimer.c28
2 files changed, 38 insertions, 10 deletions
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 6401c31d6add..64e2754ca734 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -72,14 +72,16 @@ struct hrtimer {
72/** 72/**
73 * struct hrtimer_base - the timer base for a specific clock 73 * struct hrtimer_base - the timer base for a specific clock
74 * 74 *
75 * @index: clock type index for per_cpu support when moving a timer 75 * @index: clock type index for per_cpu support when moving a timer
76 * to a base on another cpu. 76 * to a base on another cpu.
77 * @lock: lock protecting the base and associated timers 77 * @lock: lock protecting the base and associated timers
78 * @active: red black tree root node for the active timers 78 * @active: red black tree root node for the active timers
79 * @first: pointer to the timer node which expires first 79 * @first: pointer to the timer node which expires first
80 * @resolution: the resolution of the clock, in nanoseconds 80 * @resolution: the resolution of the clock, in nanoseconds
81 * @get_time: function to retrieve the current time of the clock 81 * @get_time: function to retrieve the current time of the clock
82 * @curr_timer: the timer which is executing a callback right now 82 * @get_sofirq_time: function to retrieve the current time from the softirq
83 * @curr_timer: the timer which is executing a callback right now
84 * @softirq_time: the time when running the hrtimer queue in the softirq
83 */ 85 */
84struct hrtimer_base { 86struct hrtimer_base {
85 clockid_t index; 87 clockid_t index;
@@ -88,7 +90,9 @@ struct hrtimer_base {
88 struct rb_node *first; 90 struct rb_node *first;
89 ktime_t resolution; 91 ktime_t resolution;
90 ktime_t (*get_time)(void); 92 ktime_t (*get_time)(void);
93 ktime_t (*get_softirq_time)(void);
91 struct hrtimer *curr_timer; 94 struct hrtimer *curr_timer;
95 ktime_t softirq_time;
92}; 96};
93 97
94/* 98/*
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)
123EXPORT_SYMBOL_GPL(ktime_get_ts); 123EXPORT_SYMBOL_GPL(ktime_get_ts);
124 124
125/* 125/*
126 * Get the coarse grained time at the softirq based on xtime and
127 * wall_to_monotonic.
128 */
129static void hrtimer_get_softirq_time(struct hrtimer_base *base)
130{
131 ktime_t xtim, tomono;
132 unsigned long seq;
133
134 do {
135 seq = read_seqbegin(&xtime_lock);
136 xtim = timespec_to_ktime(xtime);
137 tomono = timespec_to_ktime(wall_to_monotonic);
138
139 } while (read_seqretry(&xtime_lock, seq));
140
141 base[CLOCK_REALTIME].softirq_time = xtim;
142 base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono);
143}
144
145/*
126 * Functions and macros which are different for UP/SMP systems are kept in a 146 * Functions and macros which are different for UP/SMP systems are kept in a
127 * single place 147 * single place
128 */ 148 */
@@ -586,9 +606,11 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
586 */ 606 */
587static inline void run_hrtimer_queue(struct hrtimer_base *base) 607static inline void run_hrtimer_queue(struct hrtimer_base *base)
588{ 608{
589 ktime_t now = base->get_time();
590 struct rb_node *node; 609 struct rb_node *node;
591 610
611 if (base->get_softirq_time)
612 base->softirq_time = base->get_softirq_time();
613
592 spin_lock_irq(&base->lock); 614 spin_lock_irq(&base->lock);
593 615
594 while ((node = base->first)) { 616 while ((node = base->first)) {
@@ -598,7 +620,7 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
598 void *data; 620 void *data;
599 621
600 timer = rb_entry(node, struct hrtimer, node); 622 timer = rb_entry(node, struct hrtimer, node);
601 if (now.tv64 <= timer->expires.tv64) 623 if (base->softirq_time.tv64 <= timer->expires.tv64)
602 break; 624 break;
603 625
604 fn = timer->function; 626 fn = timer->function;
@@ -641,6 +663,8 @@ void hrtimer_run_queues(void)
641 struct hrtimer_base *base = __get_cpu_var(hrtimer_bases); 663 struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
642 int i; 664 int i;
643 665
666 hrtimer_get_softirq_time(base);
667
644 for (i = 0; i < MAX_HRTIMER_BASES; i++) 668 for (i = 0; i < MAX_HRTIMER_BASES; i++)
645 run_hrtimer_queue(&base[i]); 669 run_hrtimer_queue(&base[i]);
646} 670}