Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92127c7a authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Linus Torvalds
Browse files

[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: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a0e92852
Loading
Loading
Loading
Loading
+12 −8
Original line number Diff line number Diff line
@@ -79,7 +79,9 @@ struct hrtimer {
 * @first:		pointer to the timer node which expires first
 * @resolution:		the resolution of the clock, in nanoseconds
 * @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
 * @softirq_time:	the time when running the hrtimer queue in the softirq
 */
struct hrtimer_base {
	clockid_t		index;
@@ -88,7 +90,9 @@ struct hrtimer_base {
	struct rb_node		*first;
	ktime_t			resolution;
	ktime_t			(*get_time)(void);
	ktime_t			(*get_softirq_time)(void);
	struct hrtimer		*curr_timer;
	ktime_t			softirq_time;
};

/*
+26 −2
Original line number Diff line number Diff line
@@ -122,6 +122,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]);
}