summaryrefslogtreecommitdiffstats
path: root/kernel/time/timekeeping.c
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2011-02-01 13:52:17 +0000
committerThomas Gleixner <tglx@linutronix.de>2011-02-02 15:28:18 +0100
commitc528f7c6c208f1fae6b4025957173dec045e5f21 (patch)
tree86986bf39f82622ea81179dad3382fc4580875a8 /kernel/time/timekeeping.c
parent0061748dd2400d0bcd4d49d258db5d7b5d106ca0 (diff)
downloadlinux-c528f7c6c208f1fae6b4025957173dec045e5f21.tar.gz
linux-c528f7c6c208f1fae6b4025957173dec045e5f21.tar.bz2
linux-c528f7c6c208f1fae6b4025957173dec045e5f21.zip
time: Introduce timekeeping_inject_offset
This adds a kernel-internal timekeeping interface to add or subtract a fixed amount from CLOCK_REALTIME. This makes it so kernel users or interfaces trying to do so do not have to read the time, then add an offset and then call settimeofday(), which adds some extra error in comparision to just simply adding the offset in the kernel timekeeping core. Signed-off-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Richard Cochran <richard.cochran@omicron.at> LKML-Reference: <20110201134419.584311693@linutronix.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r--kernel/time/timekeeping.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 4f9f65b91323..6262c1d18397 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -387,6 +387,42 @@ int do_settimeofday(const struct timespec *tv)
EXPORT_SYMBOL(do_settimeofday);
+
+/**
+ * timekeeping_inject_offset - Adds or subtracts from the current time.
+ * @tv: pointer to the timespec variable containing the offset
+ *
+ * Adds or subtracts an offset value from the current time.
+ */
+int timekeeping_inject_offset(struct timespec *ts)
+{
+ unsigned long flags;
+
+ if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
+ return -EINVAL;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+
+ timekeeping_forward_now();
+
+ xtime = timespec_add(xtime, *ts);
+ wall_to_monotonic = timespec_sub(wall_to_monotonic, *ts);
+
+ timekeeper.ntp_error = 0;
+ ntp_clear();
+
+ update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
+ timekeeper.mult);
+
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ /* signal hrtimers about time change */
+ clock_was_set();
+
+ return 0;
+}
+EXPORT_SYMBOL(timekeeping_inject_offset);
+
/**
* change_clocksource - Swaps clocksources if a new one is available
*