aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/hrtimer.c36
-rw-r--r--kernel/time/timekeeping.c15
2 files changed, 50 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
90static inline int hrtimer_clockid_to_base(clockid_t clock_id) 96static 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
489static 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
1243static 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/*
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index a61b8fa2d39a..342408cf68dd 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1099,6 +1099,21 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
1099} 1099}
1100 1100
1101/** 1101/**
1102 * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format
1103 */
1104ktime_t ktime_get_monotonic_offset(void)
1105{
1106 unsigned long seq;
1107 struct timespec wtom;
1108
1109 do {
1110 seq = read_seqbegin(&xtime_lock);
1111 wtom = wall_to_monotonic;
1112 } while (read_seqretry(&xtime_lock, seq));
1113 return timespec_to_ktime(wtom);
1114}
1115
1116/**
1102 * xtime_update() - advances the timekeeping infrastructure 1117 * xtime_update() - advances the timekeeping infrastructure
1103 * @ticks: number of ticks, that have elapsed since the last call. 1118 * @ticks: number of ticks, that have elapsed since the last call.
1104 * 1119 *