diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2012-07-17 13:33:56 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-07-19 11:58:46 -0400 |
commit | 22f4bbcfb131e2392c78ad67af35fdd436d4dd54 (patch) | |
tree | fda47805e997a513b7f3c9d86d1e974c5726ca15 /kernel | |
parent | 6c89f2ce05ea7e26a7580ad9eb950f2c4f10891b (diff) |
timekeeping: Provide hrtimer update function
This is a backport of f6c06abfb3972ad4914cef57d8348fcb2932bc3b
To finally fix the infamous leap second issue and other race windows
caused by functions which change the offsets between the various time
bases (CLOCK_MONOTONIC, CLOCK_REALTIME and CLOCK_BOOTTIME) we need a
function which atomically gets the current monotonic time and updates
the offsets of CLOCK_REALTIME and CLOCK_BOOTTIME with minimalistic
overhead. The previous patch which provides ktime_t offsets allows us
to make this function almost as cheap as ktime_get() which is going to
be replaced in hrtimer_interrupt().
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Link: http://lkml.kernel.org/r/1341960205-56738-7-git-send-email-johnstul@us.ibm.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/time/timekeeping.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index d6477733fc0..f0c7565db31 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -1126,6 +1126,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | |||
1126 | } while (read_seqretry(&xtime_lock, seq)); | 1126 | } while (read_seqretry(&xtime_lock, seq)); |
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | #ifdef CONFIG_HIGH_RES_TIMERS | ||
1130 | /** | ||
1131 | * ktime_get_update_offsets - hrtimer helper | ||
1132 | * @real: pointer to storage for monotonic -> realtime offset | ||
1133 | * @_boot: pointer to storage for monotonic -> boottime offset | ||
1134 | * | ||
1135 | * Returns current monotonic time and updates the offsets | ||
1136 | * Called from hrtimer_interupt() or retrigger_next_event() | ||
1137 | */ | ||
1138 | ktime_t ktime_get_update_offsets(ktime_t *real, ktime_t *boot) | ||
1139 | { | ||
1140 | ktime_t now; | ||
1141 | unsigned int seq; | ||
1142 | u64 secs, nsecs; | ||
1143 | |||
1144 | do { | ||
1145 | seq = read_seqbegin(&xtime_lock); | ||
1146 | |||
1147 | secs = xtime.tv_sec; | ||
1148 | nsecs = xtime.tv_nsec; | ||
1149 | nsecs += timekeeping_get_ns(); | ||
1150 | /* If arch requires, add in gettimeoffset() */ | ||
1151 | nsecs += arch_gettimeoffset(); | ||
1152 | |||
1153 | *real = offs_real; | ||
1154 | *boot = offs_boot; | ||
1155 | } while (read_seqretry(&xtime_lock, seq)); | ||
1156 | |||
1157 | now = ktime_add_ns(ktime_set(secs, 0), nsecs); | ||
1158 | now = ktime_sub(now, *real); | ||
1159 | return now; | ||
1160 | } | ||
1161 | #endif | ||
1162 | |||
1129 | /** | 1163 | /** |
1130 | * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format | 1164 | * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format |
1131 | */ | 1165 | */ |