diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2012-07-17 13:33:56 -0400 |
|---|---|---|
| committer | Luis Henriques <luis.henriques@canonical.com> | 2012-07-23 05:50:34 -0400 |
| commit | 8b8564ad5fbdbab732f2784733008b95434716a8 (patch) | |
| tree | d7f2b6843e4f4923041338528973605c9f77ae0a /kernel | |
| parent | d3cce85b61cec78576717883f2896be084c58d25 (diff) | |
timekeeping: Provide hrtimer update function
BugLink: http://bugs.launchpad.net/bugs/1026850
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>
Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
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 | */ |
