diff options
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r-- | kernel/hrtimer.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index c145ed643bca..eabcbd781433 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -78,6 +78,11 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = | |||
78 | .get_time = &ktime_get_boottime, | 78 | .get_time = &ktime_get_boottime, |
79 | .resolution = KTIME_LOW_RES, | 79 | .resolution = KTIME_LOW_RES, |
80 | }, | 80 | }, |
81 | { | ||
82 | .index = CLOCK_REALTIME_COS, | ||
83 | .get_time = &ktime_get_real, | ||
84 | .resolution = KTIME_LOW_RES, | ||
85 | }, | ||
81 | } | 86 | } |
82 | }; | 87 | }; |
83 | 88 | ||
@@ -85,6 +90,7 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { | |||
85 | [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, | 90 | [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, |
86 | [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, | 91 | [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, |
87 | [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, | 92 | [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, |
93 | [CLOCK_REALTIME_COS] = HRTIMER_BASE_REALTIME_COS, | ||
88 | }; | 94 | }; |
89 | 95 | ||
90 | static inline int hrtimer_clockid_to_base(clockid_t clock_id) | 96 | static inline int hrtimer_clockid_to_base(clockid_t clock_id) |
@@ -110,6 +116,7 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) | |||
110 | base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim; | 116 | base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim; |
111 | base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time = mono; | 117 | base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time = mono; |
112 | base->clock_base[HRTIMER_BASE_BOOTTIME].softirq_time = boot; | 118 | base->clock_base[HRTIMER_BASE_BOOTTIME].softirq_time = boot; |
119 | base->clock_base[HRTIMER_BASE_REALTIME_COS].softirq_time = xtim; | ||
113 | } | 120 | } |
114 | 121 | ||
115 | /* | 122 | /* |
@@ -479,6 +486,8 @@ static inline void debug_deactivate(struct hrtimer *timer) | |||
479 | trace_hrtimer_cancel(timer); | 486 | trace_hrtimer_cancel(timer); |
480 | } | 487 | } |
481 | 488 | ||
489 | static void hrtimer_expire_cancelable(struct hrtimer_cpu_base *cpu_base); | ||
490 | |||
482 | /* High resolution timer related functions */ | 491 | /* High resolution timer related functions */ |
483 | #ifdef CONFIG_HIGH_RES_TIMERS | 492 | #ifdef CONFIG_HIGH_RES_TIMERS |
484 | 493 | ||
@@ -715,9 +724,14 @@ static void retrigger_next_event(void *arg) | |||
715 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); | 724 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); |
716 | struct timespec realtime_offset, xtim, wtm, sleep; | 725 | struct timespec realtime_offset, xtim, wtm, sleep; |
717 | 726 | ||
718 | if (!hrtimer_hres_active()) | 727 | if (!hrtimer_hres_active()) { |
728 | raw_spin_lock(&base->lock); | ||
729 | hrtimer_expire_cancelable(base); | ||
730 | raw_spin_unlock(&base->lock); | ||
719 | return; | 731 | return; |
732 | } | ||
720 | 733 | ||
734 | /* Optimized out for !HIGH_RES */ | ||
721 | get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); | 735 | get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); |
722 | set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); | 736 | set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); |
723 | 737 | ||
@@ -727,6 +741,10 @@ static void retrigger_next_event(void *arg) | |||
727 | timespec_to_ktime(realtime_offset); | 741 | timespec_to_ktime(realtime_offset); |
728 | base->clock_base[HRTIMER_BASE_BOOTTIME].offset = | 742 | base->clock_base[HRTIMER_BASE_BOOTTIME].offset = |
729 | timespec_to_ktime(sleep); | 743 | timespec_to_ktime(sleep); |
744 | base->clock_base[HRTIMER_BASE_REALTIME_COS].offset = | ||
745 | timespec_to_ktime(realtime_offset); | ||
746 | |||
747 | hrtimer_expire_cancelable(base); | ||
730 | 748 | ||
731 | hrtimer_force_reprogram(base, 0); | 749 | hrtimer_force_reprogram(base, 0); |
732 | raw_spin_unlock(&base->lock); | 750 | raw_spin_unlock(&base->lock); |
@@ -1222,6 +1240,22 @@ static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) | |||
1222 | timer->state &= ~HRTIMER_STATE_CALLBACK; | 1240 | timer->state &= ~HRTIMER_STATE_CALLBACK; |
1223 | } | 1241 | } |
1224 | 1242 | ||
1243 | static void hrtimer_expire_cancelable(struct hrtimer_cpu_base *cpu_base) | ||
1244 | { | ||
1245 | struct timerqueue_node *node; | ||
1246 | struct hrtimer_clock_base *base; | ||
1247 | ktime_t now = ktime_get_real(); | ||
1248 | |||
1249 | base = &cpu_base->clock_base[HRTIMER_BASE_REALTIME_COS]; | ||
1250 | |||
1251 | while ((node = timerqueue_getnext(&base->active))) { | ||
1252 | struct hrtimer *timer; | ||
1253 | |||
1254 | timer = container_of(node, struct hrtimer, node); | ||
1255 | __run_hrtimer(timer, &now); | ||
1256 | } | ||
1257 | } | ||
1258 | |||
1225 | #ifdef CONFIG_HIGH_RES_TIMERS | 1259 | #ifdef CONFIG_HIGH_RES_TIMERS |
1226 | 1260 | ||
1227 | /* | 1261 | /* |