diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2012-07-10 18:43:24 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2012-07-11 17:34:39 -0400 |
commit | f6c06abfb3972ad4914cef57d8348fcb2932bc3b (patch) | |
tree | 5882f90d98d0429b30d0f7f7d35c14f6e0a5125a /kernel/time | |
parent | 196951e91262fccda81147d2bcf7fdab08668b40 (diff) |
timekeeping: Provide hrtimer update function
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>
Cc: stable@vger.kernel.org
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>
Diffstat (limited to 'kernel/time')
-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 1c038dac71a2..269b1fe5f2ae 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -1271,6 +1271,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, | |||
1271 | } while (read_seqretry(&timekeeper.lock, seq)); | 1271 | } while (read_seqretry(&timekeeper.lock, seq)); |
1272 | } | 1272 | } |
1273 | 1273 | ||
1274 | #ifdef CONFIG_HIGH_RES_TIMERS | ||
1275 | /** | ||
1276 | * ktime_get_update_offsets - hrtimer helper | ||
1277 | * @offs_real: pointer to storage for monotonic -> realtime offset | ||
1278 | * @offs_boot: pointer to storage for monotonic -> boottime offset | ||
1279 | * | ||
1280 | * Returns current monotonic time and updates the offsets | ||
1281 | * Called from hrtimer_interupt() or retrigger_next_event() | ||
1282 | */ | ||
1283 | ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) | ||
1284 | { | ||
1285 | ktime_t now; | ||
1286 | unsigned int seq; | ||
1287 | u64 secs, nsecs; | ||
1288 | |||
1289 | do { | ||
1290 | seq = read_seqbegin(&timekeeper.lock); | ||
1291 | |||
1292 | secs = timekeeper.xtime.tv_sec; | ||
1293 | nsecs = timekeeper.xtime.tv_nsec; | ||
1294 | nsecs += timekeeping_get_ns(); | ||
1295 | /* If arch requires, add in gettimeoffset() */ | ||
1296 | nsecs += arch_gettimeoffset(); | ||
1297 | |||
1298 | *offs_real = timekeeper.offs_real; | ||
1299 | *offs_boot = timekeeper.offs_boot; | ||
1300 | } while (read_seqretry(&timekeeper.lock, seq)); | ||
1301 | |||
1302 | now = ktime_add_ns(ktime_set(secs, 0), nsecs); | ||
1303 | now = ktime_sub(now, *offs_real); | ||
1304 | return now; | ||
1305 | } | ||
1306 | #endif | ||
1307 | |||
1274 | /** | 1308 | /** |
1275 | * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format | 1309 | * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format |
1276 | */ | 1310 | */ |