From: Arjan van de Ven <arjan@infradead.org>
To: linux-kernel@vger.kernel.org
Cc: Arjan van de Ven <arjan@infradead.org>,
torvalds@linux-foundation.org, dwmw2@infradead.org,
drepper@redhat.com, mingo@elte.hu, tglx@tglx.de
Subject: [PATCH 11/13] hrtimer: turn hrtimers into range timers
Date: Mon, 1 Sep 2008 16:13:36 -0700 [thread overview]
Message-ID: <20080901161336.10a71c9f@infradead.org> (raw)
In-Reply-To: <20080901160343.75a89ec9@infradead.org>
From: Arjan van de Ven <arjan@linux.intel.com>
Subject: [PATCH] hrtimer: turn hrtimers into range timers
this patch turns hrtimers into range timers; they have 2 expire points
1) the soft expire point
2) the hard expire point
the kernel will do it's regular best effort attempt to get the timer run
at the hard expire point. However, if some other time fires after the soft
expire point, the kernel now has the freedom to fire this timer at this point,
and thus grouping the events and preventing a power-expensive wakeup in the
future.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
---
include/linux/hrtimer.h | 31 ++++++++++++++++++++++++++++++-
kernel/hrtimer.c | 43 +++++++++++++++++++++++++++++++++++++++----
2 files changed, 69 insertions(+), 5 deletions(-)
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 485a634..c26b1a5 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -112,6 +112,7 @@ enum hrtimer_cb_mode {
struct hrtimer {
struct rb_node node;
ktime_t _expires;
+ ktime_t _softexpires;
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer_clock_base *base;
unsigned long state;
@@ -220,20 +221,37 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer)
static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
{
timer->_expires = time;
+ timer->_softexpires = time;
}
+
+static inline void hrtimer_set_expires_range(struct hrtimer *timer, ktime_t time, ktime_t delta)
+{
+ timer->_softexpires = time;
+ timer->_expires = ktime_add_safe(time, delta);
+}
+
+static inline void hrtimer_set_expires_range_ns(struct hrtimer *timer, ktime_t time, unsigned long delta)
+{
+ timer->_softexpires = time;
+ timer->_expires = ktime_add_ns(time, delta);
+}
+
static inline void hrtimer_set_expires_tv64(struct hrtimer *timer, s64 tv64)
{
timer->_expires.tv64 = tv64;
+ timer->_softexpires.tv64 = tv64;
}
static inline void hrtimer_add_expires(struct hrtimer *timer, ktime_t time)
{
timer->_expires = ktime_add_safe(timer->_expires, time);
+ timer->_softexpires = ktime_add_safe(timer->_softexpires, time);
}
static inline void hrtimer_add_expires_ns(struct hrtimer *timer, unsigned long ns)
{
timer->_expires = ktime_add_ns(timer->_expires, ns);
+ timer->_softexpires = ktime_add_ns(timer->_softexpires, ns);
}
static inline ktime_t hrtimer_get_expires(const struct hrtimer *timer)
@@ -241,10 +259,19 @@ static inline ktime_t hrtimer_get_expires(const struct hrtimer *timer)
return timer->_expires;
}
+static inline ktime_t hrtimer_get_softexpires(const struct hrtimer *timer)
+{
+ return timer->_expires;
+}
+
static inline s64 hrtimer_get_expires_tv64(const struct hrtimer *timer)
{
return timer->_expires.tv64;
}
+static inline s64 hrtimer_get_softexpires_tv64(const struct hrtimer *timer)
+{
+ return timer->_softexpires.tv64;
+}
static inline s64 hrtimer_get_expires_ns(const struct hrtimer *timer)
{
@@ -334,7 +361,7 @@ static inline int hrtimer_start_expires(struct hrtimer *timer,
static inline int hrtimer_restart(struct hrtimer *timer)
{
- return hrtimer_start(timer, timer->_expires, HRTIMER_MODE_ABS);
+ return hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
}
/* Query timers: */
@@ -391,6 +418,8 @@ extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
struct task_struct *tsk);
+extern int schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
+ const enum hrtimer_mode mode);
extern int schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode);
/* Soft interrupt function to run the hrtimer queues: */
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index ae307fe..dc1ded0 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1309,7 +1309,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
timer = rb_entry(node, struct hrtimer, node);
- if (basenow.tv64 < hrtimer_get_expires_tv64(timer)) {
+ if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) {
ktime_t expires;
expires = ktime_sub(hrtimer_get_expires(timer),
@@ -1681,14 +1681,20 @@ void __init hrtimers_init(void)
}
/**
- * schedule_hrtimeout - sleep until timeout
+ * schedule_hrtimeout_range - sleep until timeout
* @expires: timeout value (ktime_t)
+ * @delta: slack in expires timeout (ktime_t)
* @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
*
* Make the current task sleep until the given expiry time has
* elapsed. The routine will return immediately unless
* the current task state has been set (see set_current_state()).
*
+ * The @delta argument gives the kernel the freedom to schedule the
+ * actual wakeup to a time that is both power and performance friendly.
+ * The kernel give the normal best effort behavior for "@expires+@delta",
+ * but may decide to fire the timer earlier, but no earlier than @expires.
+ *
* You can set the task state as follows -
*
* %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
@@ -1702,7 +1708,7 @@ void __init hrtimers_init(void)
*
* Returns 0 when the timer has expired otherwise -EINTR
*/
-int __sched schedule_hrtimeout(ktime_t *expires,
+int __sched schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
const enum hrtimer_mode mode)
{
struct hrtimer_sleeper t;
@@ -1726,7 +1732,7 @@ int __sched schedule_hrtimeout(ktime_t *expires,
}
hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, mode);
- hrtimer_set_expires(&t.timer, *expires);
+ hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
hrtimer_init_sleeper(&t, current);
@@ -1744,4 +1750,33 @@ int __sched schedule_hrtimeout(ktime_t *expires,
return !t.task ? 0 : -EINTR;
}
+EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
+
+/**
+ * schedule_hrtimeout - sleep until timeout
+ * @expires: timeout value (ktime_t)
+ * @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
+ *
+ * Make the current task sleep until the given expiry time has
+ * elapsed. The routine will return immediately unless
+ * the current task state has been set (see set_current_state()).
+ *
+ * You can set the task state as follows -
+ *
+ * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
+ * pass before the routine returns.
+ *
+ * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
+ * delivered to the current task.
+ *
+ * The current task state is guaranteed to be TASK_RUNNING when this
+ * routine returns.
+ *
+ * Returns 0 when the timer has expired otherwise -EINTR
+ */
+int __sched schedule_hrtimeout(ktime_t *expires,
+ const enum hrtimer_mode mode)
+{
+ return schedule_hrtimeout_range(expires, 0, mode);
+}
EXPORT_SYMBOL_GPL(schedule_hrtimeout);
--
1.5.5.1
next prev parent reply other threads:[~2008-09-01 23:16 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-01 23:03 [PATCH 0/13] Turn hrtimers into a range capable timer Arjan van de Ven
2008-09-01 23:05 ` [PATCH 1/13] hrtimer: add abstraction functions for accessing the "expires" member Arjan van de Ven
2008-09-01 23:05 ` [PATCH 2/13] hrtimer: convert kvm to the new hrtimer apis Arjan van de Ven
2008-09-01 23:06 ` [PATCH 3/13] hrtimer: convert timerfd " Arjan van de Ven
2008-09-01 23:07 ` [PATCH 4/13] hrtimer: convert net::sched_cbq " Arjan van de Ven
2008-09-01 23:08 ` [PATCH 5/13] hrtimer: convert kernel/* " Arjan van de Ven
2008-09-01 23:09 ` [PATCH 6/13] hrtimer: convert powerpc/oprofile " Arjan van de Ven
2008-09-01 23:09 ` [PATCH 7/13] hrtimer: convert kvm-ia64 " Arjan van de Ven
2008-09-01 23:10 ` [PATCH 8/13] hrtimer: convert s390 " Arjan van de Ven
2008-09-01 23:11 ` [PATCH 9/13] hrtimer: convert sound/ " Arjan van de Ven
2008-09-01 23:12 ` [PATCH 10/13] hrtimer: rename the "expires" struct member to avoid accidental usage Arjan van de Ven
2008-09-01 23:12 ` Arjan van de Ven
2008-09-01 23:13 ` Arjan van de Ven [this message]
2008-09-02 8:22 ` [PATCH 11/13] hrtimer: turn hrtimers into range timers Peter Zijlstra
2008-09-02 11:08 ` Peter Zijlstra
2008-09-02 11:15 ` Peter Zijlstra
2008-09-02 13:06 ` Arjan van de Ven
2008-09-02 13:05 ` Arjan van de Ven
2008-09-02 13:47 ` Peter Zijlstra
2008-09-02 16:02 ` Arjan van de Ven
2008-09-01 23:14 ` [PATCH 12/13] hrtimer: create a "timer_slack" field in the task struct Arjan van de Ven
2008-09-02 10:04 ` Pavel Machek
2008-09-02 13:03 ` Arjan van de Ven
2008-09-08 13:27 ` Pavel Machek
2008-09-08 13:40 ` Arjan van de Ven
2008-09-08 14:15 ` Pavel Machek
2008-09-08 14:22 ` Arjan van de Ven
2008-09-13 16:24 ` Pavel Machek
2008-09-14 15:21 ` Ulrich Drepper
2008-09-14 15:27 ` Arjan van de Ven
2008-09-14 15:57 ` Pavel Machek
2008-09-14 16:04 ` Ulrich Drepper
2008-09-14 16:14 ` Arjan van de Ven
2008-09-17 7:42 ` Pavel Machek
2008-09-30 5:16 ` KOSAKI Motohiro
2008-09-30 8:28 ` Arjan van de Ven
2008-09-30 8:54 ` KOSAKI Motohiro
2008-09-01 23:14 ` [PATCH 13/13] hrtimer: make select() and poll() use the hrtimer range feature Arjan van de Ven
2008-09-02 8:22 ` Peter Zijlstra
2008-09-02 16:03 ` Arjan van de Ven
2008-09-06 14:56 ` [PATCH 0/13] Turn hrtimers into a range capable timer Ingo Molnar
2008-09-06 16:30 ` Arjan van de Ven
2008-09-06 16:33 ` Ingo Molnar
2008-09-12 3:39 ` Rusty Russell
2008-09-12 5:42 ` Arjan van de Ven
2008-09-12 20:24 ` Thomas Gleixner
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=20080901161336.10a71c9f@infradead.org \
--to=arjan@infradead.org \
--cc=drepper@redhat.com \
--cc=dwmw2@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=tglx@tglx.de \
--cc=torvalds@linux-foundation.org \
/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
Powered by JetHome