diff options
Diffstat (limited to 'kernel/time/timekeeping.c')
-rw-r--r-- | kernel/time/timekeeping.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index acf049144cf6..657414cf2e46 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -126,9 +126,9 @@ static void timekeeping_check_update(struct timekeeper *tk, cycle_t offset) | |||
126 | const char *name = tk->tkr.clock->name; | 126 | const char *name = tk->tkr.clock->name; |
127 | 127 | ||
128 | if (offset > max_cycles) { | 128 | if (offset > max_cycles) { |
129 | printk_deferred("WARNING: timekeeping: Cycle offset (%lld) is larger than allowed by the '%s' clock's max_cycles value (%lld): time overflow\n", | 129 | printk_deferred("WARNING: timekeeping: Cycle offset (%lld) is larger than allowed by the '%s' clock's max_cycles value (%lld): time overflow danger\n", |
130 | offset, name, max_cycles); | 130 | offset, name, max_cycles); |
131 | printk_deferred(" timekeeping: Your kernel is sick, but tries to cope\n"); | 131 | printk_deferred(" timekeeping: Your kernel is sick, but tries to cope by capping time updates\n"); |
132 | } else { | 132 | } else { |
133 | if (offset > (max_cycles >> 1)) { | 133 | if (offset > (max_cycles >> 1)) { |
134 | printk_deferred("INFO: timekeeping: Cycle offset (%lld) is larger than the the '%s' clock's 50%% safety margin (%lld)\n", | 134 | printk_deferred("INFO: timekeeping: Cycle offset (%lld) is larger than the the '%s' clock's 50%% safety margin (%lld)\n", |
@@ -137,10 +137,39 @@ static void timekeeping_check_update(struct timekeeper *tk, cycle_t offset) | |||
137 | } | 137 | } |
138 | } | 138 | } |
139 | } | 139 | } |
140 | |||
141 | static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr) | ||
142 | { | ||
143 | cycle_t cycle_now, delta; | ||
144 | |||
145 | /* read clocksource */ | ||
146 | cycle_now = tkr->read(tkr->clock); | ||
147 | |||
148 | /* calculate the delta since the last update_wall_time */ | ||
149 | delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask); | ||
150 | |||
151 | /* Cap delta value to the max_cycles values to avoid mult overflows */ | ||
152 | if (unlikely(delta > tkr->clock->max_cycles)) | ||
153 | delta = tkr->clock->max_cycles; | ||
154 | |||
155 | return delta; | ||
156 | } | ||
140 | #else | 157 | #else |
141 | static inline void timekeeping_check_update(struct timekeeper *tk, cycle_t offset) | 158 | static inline void timekeeping_check_update(struct timekeeper *tk, cycle_t offset) |
142 | { | 159 | { |
143 | } | 160 | } |
161 | static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr) | ||
162 | { | ||
163 | cycle_t cycle_now, delta; | ||
164 | |||
165 | /* read clocksource */ | ||
166 | cycle_now = tkr->read(tkr->clock); | ||
167 | |||
168 | /* calculate the delta since the last update_wall_time */ | ||
169 | delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask); | ||
170 | |||
171 | return delta; | ||
172 | } | ||
144 | #endif | 173 | #endif |
145 | 174 | ||
146 | /** | 175 | /** |
@@ -218,14 +247,10 @@ static inline u32 arch_gettimeoffset(void) { return 0; } | |||
218 | 247 | ||
219 | static inline s64 timekeeping_get_ns(struct tk_read_base *tkr) | 248 | static inline s64 timekeeping_get_ns(struct tk_read_base *tkr) |
220 | { | 249 | { |
221 | cycle_t cycle_now, delta; | 250 | cycle_t delta; |
222 | s64 nsec; | 251 | s64 nsec; |
223 | 252 | ||
224 | /* read clocksource: */ | 253 | delta = timekeeping_get_delta(tkr); |
225 | cycle_now = tkr->read(tkr->clock); | ||
226 | |||
227 | /* calculate the delta since the last update_wall_time: */ | ||
228 | delta = clocksource_delta(cycle_now, tkr->cycle_last, tkr->mask); | ||
229 | 254 | ||
230 | nsec = delta * tkr->mult + tkr->xtime_nsec; | 255 | nsec = delta * tkr->mult + tkr->xtime_nsec; |
231 | nsec >>= tkr->shift; | 256 | nsec >>= tkr->shift; |
@@ -237,14 +262,10 @@ static inline s64 timekeeping_get_ns(struct tk_read_base *tkr) | |||
237 | static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) | 262 | static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) |
238 | { | 263 | { |
239 | struct clocksource *clock = tk->tkr.clock; | 264 | struct clocksource *clock = tk->tkr.clock; |
240 | cycle_t cycle_now, delta; | 265 | cycle_t delta; |
241 | s64 nsec; | 266 | s64 nsec; |
242 | 267 | ||
243 | /* read clocksource: */ | 268 | delta = timekeeping_get_delta(&tk->tkr); |
244 | cycle_now = tk->tkr.read(clock); | ||
245 | |||
246 | /* calculate the delta since the last update_wall_time: */ | ||
247 | delta = clocksource_delta(cycle_now, tk->tkr.cycle_last, tk->tkr.mask); | ||
248 | 269 | ||
249 | /* convert delta to nanoseconds. */ | 270 | /* convert delta to nanoseconds. */ |
250 | nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift); | 271 | nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift); |