diff options
-rw-r--r-- | drivers/cpuidle/cpuidle.c | 7 | ||||
-rw-r--r-- | include/linux/hrtimer.h | 5 | ||||
-rw-r--r-- | kernel/hrtimer.c | 30 |
3 files changed, 42 insertions, 0 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 5ce07b517c58..2e3148499368 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/cpu.h> | 16 | #include <linux/cpu.h> |
17 | #include <linux/cpuidle.h> | 17 | #include <linux/cpuidle.h> |
18 | #include <linux/ktime.h> | 18 | #include <linux/ktime.h> |
19 | #include <linux/hrtimer.h> | ||
19 | 20 | ||
20 | #include "cpuidle.h" | 21 | #include "cpuidle.h" |
21 | 22 | ||
@@ -60,6 +61,12 @@ static void cpuidle_idle_call(void) | |||
60 | return; | 61 | return; |
61 | } | 62 | } |
62 | 63 | ||
64 | /* | ||
65 | * run any timers that can be run now, at this point | ||
66 | * before calculating the idle duration etc. | ||
67 | */ | ||
68 | hrtimer_peek_ahead_timers(); | ||
69 | |||
63 | /* ask the governor for the next state */ | 70 | /* ask the governor for the next state */ |
64 | next_state = cpuidle_curr_governor->select(dev); | 71 | next_state = cpuidle_curr_governor->select(dev); |
65 | if (need_resched()) | 72 | if (need_resched()) |
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 95db11f62ff2..d93b1e1dc169 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -326,6 +326,11 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer) | |||
326 | extern ktime_t ktime_get(void); | 326 | extern ktime_t ktime_get(void); |
327 | extern ktime_t ktime_get_real(void); | 327 | extern ktime_t ktime_get_real(void); |
328 | 328 | ||
329 | |||
330 | DECLARE_PER_CPU(struct tick_device, tick_cpu_device); | ||
331 | extern void hrtimer_peek_ahead_timers(void); | ||
332 | |||
333 | |||
329 | /* Exported timer functions: */ | 334 | /* Exported timer functions: */ |
330 | 335 | ||
331 | /* Initialize timers: */ | 336 | /* Initialize timers: */ |
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 9a4c90185566..eb2cf984959f 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -1381,6 +1381,36 @@ void hrtimer_interrupt(struct clock_event_device *dev) | |||
1381 | raise_softirq(HRTIMER_SOFTIRQ); | 1381 | raise_softirq(HRTIMER_SOFTIRQ); |
1382 | } | 1382 | } |
1383 | 1383 | ||
1384 | /** | ||
1385 | * hrtimer_peek_ahead_timers -- run soft-expired timers now | ||
1386 | * | ||
1387 | * hrtimer_peek_ahead_timers will peek at the timer queue of | ||
1388 | * the current cpu and check if there are any timers for which | ||
1389 | * the soft expires time has passed. If any such timers exist, | ||
1390 | * they are run immediately and then removed from the timer queue. | ||
1391 | * | ||
1392 | */ | ||
1393 | void hrtimer_peek_ahead_timers(void) | ||
1394 | { | ||
1395 | unsigned long flags; | ||
1396 | struct tick_device *td; | ||
1397 | struct clock_event_device *dev; | ||
1398 | |||
1399 | if (hrtimer_hres_active()) | ||
1400 | return; | ||
1401 | |||
1402 | local_irq_save(flags); | ||
1403 | td = &__get_cpu_var(tick_cpu_device); | ||
1404 | if (!td) | ||
1405 | goto out; | ||
1406 | dev = td->evtdev; | ||
1407 | if (!dev) | ||
1408 | goto out; | ||
1409 | hrtimer_interrupt(dev); | ||
1410 | out: | ||
1411 | local_irq_restore(flags); | ||
1412 | } | ||
1413 | |||
1384 | static void run_hrtimer_softirq(struct softirq_action *h) | 1414 | static void run_hrtimer_softirq(struct softirq_action *h) |
1385 | { | 1415 | { |
1386 | run_hrtimer_pending(&__get_cpu_var(hrtimer_bases)); | 1416 | run_hrtimer_pending(&__get_cpu_var(hrtimer_bases)); |