From: Arjan van de Ven <arjan@linux.intel.com>
To: Andrew Morton <akpm@osdl.org>
Cc: linux-kernel@vger.kernel.org, mingo@elte.hu
Subject: Re: [patch 1/2] round_jiffies infrastructure
Date: Tue, 10 Oct 2006 22:48:00 +0200 [thread overview]
Message-ID: <1160513281.3000.333.camel@laptopd505.fenrus.org> (raw)
In-Reply-To: <20061010115652.4ef068bd.akpm@osdl.org>
> c'mon Arjan. If we're going to create new, kernel-wide,
> exported-to-modules infrastructure then it deserves slightly more than zero
> documentation.
ok I had a weak moment; updated patch below
(lightly tested because current 2.6.19-rc1-git6 dies on x86_64 with an
interrupt issue within a few minutes even unpatched on my machines)
From: Arjan van de Ven <arjan@linux.intel.com>
Subject: round_jiffies infrastructure
This patch introduces a round_jiffies() function as well as a
round_jiffies_relative() function. These functions round a jiffies value
to the next whole second. The primary purpose of this rounding is to
cause all "we don't care exactly when" timers to happen at the same
jiffy.
This avoids multiple timers to fire within the second for no real
reason; with dynamic ticks these extra timers cause wakeups from deep
sleep CPU sleep states and thus waste power.
The exact wakeup moment is skewed by the cpu number, to avoid all
cpus from waking up at the exact same time (and hitting the same
lock/cachelines there)
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Index: linux-2.6.19-rc1-git6/include/linux/timer.h
===================================================================
--- linux-2.6.19-rc1-git6.orig/include/linux/timer.h
+++ linux-2.6.19-rc1-git6/include/linux/timer.h
@@ -98,4 +98,10 @@ extern void run_local_timers(void);
struct hrtimer;
extern int it_real_fn(struct hrtimer *);
+unsigned long __round_jiffies(unsigned long j, int cpu);
+unsigned long __round_jiffies_relative(unsigned long j, int cpu);
+unsigned long round_jiffies(unsigned long j);
+unsigned long round_jiffies_relative(unsigned long j);
+
+
#endif
Index: linux-2.6.19-rc1-git6/kernel/timer.c
===================================================================
--- linux-2.6.19-rc1-git6.orig/kernel/timer.c
+++ linux-2.6.19-rc1-git6/kernel/timer.c
@@ -80,6 +80,139 @@ tvec_base_t boot_tvec_bases;
EXPORT_SYMBOL(boot_tvec_bases);
static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases;
+/**
+ * __round_jiffies - function to round jiffies to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * __round_jiffies rounds an absolute time in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The exact rounding is skewed for each processor to avoid all
+ * processors firing at the exact same time, which could lead
+ * to lock contention or spurious cache line bouncing.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long __round_jiffies(unsigned long j, int cpu)
+{
+ int rem;
+ int original = j;
+
+ /*
+ * We don't want all cpus firing their timers at once hitting the
+ * same lock or cachelines, so we skew each extra cpu with an extra
+ * 3 jiffies. This 3 jiffies came originally from the mm/ code which
+ * already did this.
+ * The skew is done by adding 3*cpunr, then round, then subtract this
+ * extra offset again.
+ */
+ j += cpu * 3;
+
+ rem = j % HZ;
+
+ /*
+ * If the target jiffie is just after a whole second (which can happen
+ * due to delays of the timer irq, long irq off times etc etc) then
+ * we should round down to the whole second, not up. Use 1/4th second
+ * as cutoff for this rounding as an extreme upper bound for this.
+ */
+ if (rem < HZ/4) /* round down */
+ j = j - rem;
+ else /* round up */
+ j = j - rem + HZ;
+
+ /* now that we have rounded, subtract the extra skew again */
+ j -= cpu * 3;
+
+ if (j <= jiffies) /* rounding ate our timeout entirely; */
+ return original;
+ return j;
+}
+EXPORT_SYMBOL_GPL(__round_jiffies);
+
+/**
+ * __round_jiffies_relative - function to round jiffies to a full second
+ * @j: the time in (relative) jiffies that should be rounded
+ * @cpu: the processor number on which the timeout will happen
+ *
+ * __round_jiffies_relative rounds a time delta in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The exact rounding is skewed for each processor to avoid all
+ * processors firing at the exact same time, which could lead
+ * to lock contention or spurious cache line bouncing.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long __round_jiffies_relative(unsigned long j, int cpu)
+{
+ /*
+ * In theory the following code can skip a jiffy in case jiffies
+ * increments right between the addition and the later subtraction.
+ * However since the entire point of this function is to use approximate
+ * timeouts, it's entirely ok to not handle that.
+ */
+ return __round_jiffies(j + jiffies, cpu) - jiffies;
+}
+EXPORT_SYMBOL_GPL(__round_jiffies_relative);
+
+/**
+ * round_jiffies - function to round jiffies to a full second
+ * @j: the time in (absolute) jiffies that should be rounded
+ *
+ * round_jiffies rounds an absolute time in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long round_jiffies(unsigned long j)
+{
+ return __round_jiffies(j, raw_smp_processor_id());
+}
+EXPORT_SYMBOL_GPL(round_jiffies);
+
+/**
+ * round_jiffies_relative - function to round jiffies to a full second
+ * @j: the time in (relative) jiffies that should be rounded
+ *
+ * round_jiffies_relative rounds a time delta in the future (in jiffies)
+ * up or down to (approximately) full seconds. This is useful for timers
+ * for which the exact time they fire does not matter too much, as long as
+ * they fire approximately every X seconds.
+ *
+ * By rounding these timers to whole seconds, all such timers will fire
+ * at the same time, rather than at various times spread out. The goal
+ * of this is to have the CPU wake up less, which saves power.
+ *
+ * The return value is the rounded version of the "j" parameter.
+ */
+unsigned long round_jiffies_relative(unsigned long j)
+{
+ return __round_jiffies_relative(j, raw_smp_processor_id());
+}
+EXPORT_SYMBOL_GPL(round_jiffies_relative);
+
+
+
static inline void set_running_timer(tvec_base_t *base,
struct timer_list *timer)
{
next prev parent reply other threads:[~2006-10-10 20:48 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-10-10 16:02 [patch 0/2] Introduce round_jiffies() to save spurious wakeups Arjan van de Ven
2006-10-10 16:03 ` [patch 1/2] round_jiffies infrastructure Arjan van de Ven
2006-10-10 16:04 ` [patch 2/2] round_jiffies users Arjan van de Ven
2006-10-10 16:47 ` Ingo Oeser
2006-10-10 16:59 ` Arjan van de Ven
2006-10-10 22:47 ` Paul Dickson
2006-10-10 23:52 ` Arjan van de Ven
2006-10-10 18:56 ` [patch 1/2] round_jiffies infrastructure Andrew Morton
2006-10-10 20:48 ` Arjan van de Ven [this message]
2006-10-16 13:42 ` Andi Kleen
2006-10-11 17:23 ` [patch 0/2] Introduce round_jiffies() to save spurious wakeups Christoph Hellwig
2006-10-11 17:54 ` Arjan van de Ven
2006-10-12 19:02 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1160513281.3000.333.camel@laptopd505.fenrus.org \
--to=arjan@linux.intel.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®