mirror of https://gitee.com/openkylin/linux.git
[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>
This commit is contained in:
parent
a0e9285233
commit
92127c7a45
|
@ -79,7 +79,9 @@ struct hrtimer {
|
||||||
* @first: pointer to the timer node which expires first
|
* @first: pointer to the timer node which expires first
|
||||||
* @resolution: the resolution of the clock, in nanoseconds
|
* @resolution: the resolution of the clock, in nanoseconds
|
||||||
* @get_time: function to retrieve the current time of the clock
|
* @get_time: function to retrieve the current time of the clock
|
||||||
|
* @get_sofirq_time: function to retrieve the current time from the softirq
|
||||||
* @curr_timer: the timer which is executing a callback right now
|
* @curr_timer: the timer which is executing a callback right now
|
||||||
|
* @softirq_time: the time when running the hrtimer queue in the softirq
|
||||||
*/
|
*/
|
||||||
struct hrtimer_base {
|
struct hrtimer_base {
|
||||||
clockid_t index;
|
clockid_t index;
|
||||||
|
@ -88,7 +90,9 @@ struct hrtimer_base {
|
||||||
struct rb_node *first;
|
struct rb_node *first;
|
||||||
ktime_t resolution;
|
ktime_t resolution;
|
||||||
ktime_t (*get_time)(void);
|
ktime_t (*get_time)(void);
|
||||||
|
ktime_t (*get_softirq_time)(void);
|
||||||
struct hrtimer *curr_timer;
|
struct hrtimer *curr_timer;
|
||||||
|
ktime_t softirq_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -122,6 +122,26 @@ void ktime_get_ts(struct timespec *ts)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ktime_get_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
|
* Functions and macros which are different for UP/SMP systems are kept in a
|
||||||
* single place
|
* 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)
|
static inline void run_hrtimer_queue(struct hrtimer_base *base)
|
||||||
{
|
{
|
||||||
ktime_t now = base->get_time();
|
|
||||||
struct rb_node *node;
|
struct rb_node *node;
|
||||||
|
|
||||||
|
if (base->get_softirq_time)
|
||||||
|
base->softirq_time = base->get_softirq_time();
|
||||||
|
|
||||||
spin_lock_irq(&base->lock);
|
spin_lock_irq(&base->lock);
|
||||||
|
|
||||||
while ((node = base->first)) {
|
while ((node = base->first)) {
|
||||||
|
@ -598,7 +620,7 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base)
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
timer = rb_entry(node, struct hrtimer, node);
|
timer = rb_entry(node, struct hrtimer, node);
|
||||||
if (now.tv64 <= timer->expires.tv64)
|
if (base->softirq_time.tv64 <= timer->expires.tv64)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
fn = timer->function;
|
fn = timer->function;
|
||||||
|
@ -641,6 +663,8 @@ void hrtimer_run_queues(void)
|
||||||
struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
|
struct hrtimer_base *base = __get_cpu_var(hrtimer_bases);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
hrtimer_get_softirq_time(base);
|
||||||
|
|
||||||
for (i = 0; i < MAX_HRTIMER_BASES; i++)
|
for (i = 0; i < MAX_HRTIMER_BASES; i++)
|
||||||
run_hrtimer_queue(&base[i]);
|
run_hrtimer_queue(&base[i]);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue