aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-09-01 18:47:08 -0400
committerArjan van de Ven <arjan@linux.intel.com>2008-09-06 00:35:27 -0400
commit654c8e0b1c623b156c5b92f28d914ab38c9c2c90 (patch)
treeb3b1f8cfa8f3b12170f0d8b8770857182a2f0309 /kernel
parent799b64de256ea68fbb5db63bb55f61c305870643 (diff)
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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/hrtimer.c56
1 files changed, 52 insertions, 4 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index ae307feec74c..01483004183d 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -1309,7 +1309,20 @@ void hrtimer_interrupt(struct clock_event_device *dev)
1309 1309
1310 timer = rb_entry(node, struct hrtimer, node); 1310 timer = rb_entry(node, struct hrtimer, node);
1311 1311
1312 if (basenow.tv64 < hrtimer_get_expires_tv64(timer)) { 1312 /*
1313 * The immediate goal for using the softexpires is
1314 * minimizing wakeups, not running timers at the
1315 * earliest interrupt after their soft expiration.
1316 * This allows us to avoid using a Priority Search
1317 * Tree, which can answer a stabbing querry for
1318 * overlapping intervals and instead use the simple
1319 * BST we already have.
1320 * We don't add extra wakeups by delaying timers that
1321 * are right-of a not yet expired timer, because that
1322 * timer will have to trigger a wakeup anyway.
1323 */
1324
1325 if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) {
1313 ktime_t expires; 1326 ktime_t expires;
1314 1327
1315 expires = ktime_sub(hrtimer_get_expires(timer), 1328 expires = ktime_sub(hrtimer_get_expires(timer),
@@ -1681,14 +1694,20 @@ void __init hrtimers_init(void)
1681} 1694}
1682 1695
1683/** 1696/**
1684 * schedule_hrtimeout - sleep until timeout 1697 * schedule_hrtimeout_range - sleep until timeout
1685 * @expires: timeout value (ktime_t) 1698 * @expires: timeout value (ktime_t)
1699 * @delta: slack in expires timeout (ktime_t)
1686 * @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL 1700 * @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
1687 * 1701 *
1688 * Make the current task sleep until the given expiry time has 1702 * Make the current task sleep until the given expiry time has
1689 * elapsed. The routine will return immediately unless 1703 * elapsed. The routine will return immediately unless
1690 * the current task state has been set (see set_current_state()). 1704 * the current task state has been set (see set_current_state()).
1691 * 1705 *
1706 * The @delta argument gives the kernel the freedom to schedule the
1707 * actual wakeup to a time that is both power and performance friendly.
1708 * The kernel give the normal best effort behavior for "@expires+@delta",
1709 * but may decide to fire the timer earlier, but no earlier than @expires.
1710 *
1692 * You can set the task state as follows - 1711 * You can set the task state as follows -
1693 * 1712 *
1694 * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to 1713 * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
@@ -1702,7 +1721,7 @@ void __init hrtimers_init(void)
1702 * 1721 *
1703 * Returns 0 when the timer has expired otherwise -EINTR 1722 * Returns 0 when the timer has expired otherwise -EINTR
1704 */ 1723 */
1705int __sched schedule_hrtimeout(ktime_t *expires, 1724int __sched schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
1706 const enum hrtimer_mode mode) 1725 const enum hrtimer_mode mode)
1707{ 1726{
1708 struct hrtimer_sleeper t; 1727 struct hrtimer_sleeper t;
@@ -1726,7 +1745,7 @@ int __sched schedule_hrtimeout(ktime_t *expires,
1726 } 1745 }
1727 1746
1728 hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, mode); 1747 hrtimer_init_on_stack(&t.timer, CLOCK_MONOTONIC, mode);
1729 hrtimer_set_expires(&t.timer, *expires); 1748 hrtimer_set_expires_range_ns(&t.timer, *expires, delta);
1730 1749
1731 hrtimer_init_sleeper(&t, current); 1750 hrtimer_init_sleeper(&t, current);
1732 1751
@@ -1744,4 +1763,33 @@ int __sched schedule_hrtimeout(ktime_t *expires,
1744 1763
1745 return !t.task ? 0 : -EINTR; 1764 return !t.task ? 0 : -EINTR;
1746} 1765}
1766EXPORT_SYMBOL_GPL(schedule_hrtimeout_range);
1767
1768/**
1769 * schedule_hrtimeout - sleep until timeout
1770 * @expires: timeout value (ktime_t)
1771 * @mode: timer mode, HRTIMER_MODE_ABS or HRTIMER_MODE_REL
1772 *
1773 * Make the current task sleep until the given expiry time has
1774 * elapsed. The routine will return immediately unless
1775 * the current task state has been set (see set_current_state()).
1776 *
1777 * You can set the task state as follows -
1778 *
1779 * %TASK_UNINTERRUPTIBLE - at least @timeout time is guaranteed to
1780 * pass before the routine returns.
1781 *
1782 * %TASK_INTERRUPTIBLE - the routine may return early if a signal is
1783 * delivered to the current task.
1784 *
1785 * The current task state is guaranteed to be TASK_RUNNING when this
1786 * routine returns.
1787 *
1788 * Returns 0 when the timer has expired otherwise -EINTR
1789 */
1790int __sched schedule_hrtimeout(ktime_t *expires,
1791 const enum hrtimer_mode mode)
1792{
1793 return schedule_hrtimeout_range(expires, 0, mode);
1794}
1747EXPORT_SYMBOL_GPL(schedule_hrtimeout); 1795EXPORT_SYMBOL_GPL(schedule_hrtimeout);