aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-07-16 17:05:15 -0400
committerJohn Stultz <john.stultz@linaro.org>2014-07-23 18:01:52 -0400
commit6d3aadf3e180e09dbefab16478c6876b584ce16e (patch)
tree872068009c7a8fa99a2b5abc11e7b2aa847d4801
parent4a0e637738f06673725792d74eed67f8779b62c7 (diff)
timekeeping: Restructure the timekeeper some more
Access to time requires to touch two cachelines at minimum 1) The timekeeper data structure 2) The clocksource data structure The access to the clocksource data structure can be avoided as almost all clocksource implementations ignore the argument to the read callback, which is a pointer to the clocksource. But the core needs to touch it to access the members @read and @mask. So we are better off by copying the @read function pointer and the @mask from the clocksource to the core data structure itself. For the most used ktime_get() access all required data including the @read and @mask copies fits together with the sequence counter into a single 64 byte cacheline. For the other time access functions we touch in the current code three cache lines in the worst case. But with the clocksource data copies we can reduce that to two adjacent cachelines, which is more efficient than disjunct cache lines. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r--include/linux/timekeeper_internal.h4
-rw-r--r--kernel/time/timekeeping.c35
2 files changed, 19 insertions, 20 deletions
diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index cb88096222c0..75bb8add78f5 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -29,6 +29,10 @@
29struct timekeeper { 29struct timekeeper {
30 /* Current clocksource used for timekeeping. */ 30 /* Current clocksource used for timekeeping. */
31 struct clocksource *clock; 31 struct clocksource *clock;
32 /* Read function of @clock */
33 cycle_t (*read)(struct clocksource *cs);
34 /* Bitmask for two's complement subtraction of non 64bit counters */
35 cycle_t mask;
32 /* Last cycle value */ 36 /* Last cycle value */
33 cycle_t cycle_last; 37 cycle_t cycle_last;
34 /* NTP adjusted clock multiplier */ 38 /* NTP adjusted clock multiplier */
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 4e748c404749..14b7367e6b94 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -121,7 +121,9 @@ static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
121 121
122 old_clock = tk->clock; 122 old_clock = tk->clock;
123 tk->clock = clock; 123 tk->clock = clock;
124 tk->cycle_last = clock->read(clock); 124 tk->read = clock->read;
125 tk->mask = clock->mask;
126 tk->cycle_last = tk->read(clock);
125 127
126 /* Do the ns -> cycle conversion first, using original mult */ 128 /* Do the ns -> cycle conversion first, using original mult */
127 tmp = NTP_INTERVAL_LENGTH; 129 tmp = NTP_INTERVAL_LENGTH;
@@ -174,15 +176,13 @@ static inline u32 arch_gettimeoffset(void) { return 0; }
174static inline s64 timekeeping_get_ns(struct timekeeper *tk) 176static inline s64 timekeeping_get_ns(struct timekeeper *tk)
175{ 177{
176 cycle_t cycle_now, delta; 178 cycle_t cycle_now, delta;
177 struct clocksource *clock;
178 s64 nsec; 179 s64 nsec;
179 180
180 /* read clocksource: */ 181 /* read clocksource: */
181 clock = tk->clock; 182 cycle_now = tk->read(tk->clock);
182 cycle_now = clock->read(clock);
183 183
184 /* calculate the delta since the last update_wall_time: */ 184 /* calculate the delta since the last update_wall_time: */
185 delta = clocksource_delta(cycle_now, tk->cycle_last, clock->mask); 185 delta = clocksource_delta(cycle_now, tk->cycle_last, tk->mask);
186 186
187 nsec = delta * tk->mult + tk->xtime_nsec; 187 nsec = delta * tk->mult + tk->xtime_nsec;
188 nsec >>= tk->shift; 188 nsec >>= tk->shift;
@@ -193,16 +193,15 @@ static inline s64 timekeeping_get_ns(struct timekeeper *tk)
193 193
194static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk) 194static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
195{ 195{
196 struct clocksource *clock = tk->clock;
196 cycle_t cycle_now, delta; 197 cycle_t cycle_now, delta;
197 struct clocksource *clock;
198 s64 nsec; 198 s64 nsec;
199 199
200 /* read clocksource: */ 200 /* read clocksource: */
201 clock = tk->clock; 201 cycle_now = tk->read(clock);
202 cycle_now = clock->read(clock);
203 202
204 /* calculate the delta since the last update_wall_time: */ 203 /* calculate the delta since the last update_wall_time: */
205 delta = clocksource_delta(cycle_now, tk->cycle_last, clock->mask); 204 delta = clocksource_delta(cycle_now, tk->cycle_last, tk->mask);
206 205
207 /* convert delta to nanoseconds. */ 206 /* convert delta to nanoseconds. */
208 nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift); 207 nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift);
@@ -337,13 +336,12 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
337 */ 336 */
338static void timekeeping_forward_now(struct timekeeper *tk) 337static void timekeeping_forward_now(struct timekeeper *tk)
339{ 338{
339 struct clocksource *clock = tk->clock;
340 cycle_t cycle_now, delta; 340 cycle_t cycle_now, delta;
341 struct clocksource *clock;
342 s64 nsec; 341 s64 nsec;
343 342
344 clock = tk->clock; 343 cycle_now = tk->read(clock);
345 cycle_now = clock->read(clock); 344 delta = clocksource_delta(cycle_now, tk->cycle_last, tk->mask);
346 delta = clocksource_delta(cycle_now, tk->cycle_last, clock->mask);
347 tk->cycle_last = cycle_now; 345 tk->cycle_last = cycle_now;
348 346
349 tk->xtime_nsec += delta * tk->mult; 347 tk->xtime_nsec += delta * tk->mult;
@@ -1019,7 +1017,7 @@ static void timekeeping_resume(void)
1019 * The less preferred source will only be tried if there is no better 1017 * The less preferred source will only be tried if there is no better
1020 * usable source. The rtc part is handled separately in rtc core code. 1018 * usable source. The rtc part is handled separately in rtc core code.
1021 */ 1019 */
1022 cycle_now = clock->read(clock); 1020 cycle_now = tk->read(clock);
1023 if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) && 1021 if ((clock->flags & CLOCK_SOURCE_SUSPEND_NONSTOP) &&
1024 cycle_now > tk->cycle_last) { 1022 cycle_now > tk->cycle_last) {
1025 u64 num, max = ULLONG_MAX; 1023 u64 num, max = ULLONG_MAX;
@@ -1028,7 +1026,7 @@ static void timekeeping_resume(void)
1028 s64 nsec = 0; 1026 s64 nsec = 0;
1029 1027
1030 cycle_delta = clocksource_delta(cycle_now, tk->cycle_last, 1028 cycle_delta = clocksource_delta(cycle_now, tk->cycle_last,
1031 clock->mask); 1029 tk->mask);
1032 1030
1033 /* 1031 /*
1034 * "cycle_delta * mutl" may cause 64 bits overflow, if the 1032 * "cycle_delta * mutl" may cause 64 bits overflow, if the
@@ -1415,7 +1413,6 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
1415 */ 1413 */
1416void update_wall_time(void) 1414void update_wall_time(void)
1417{ 1415{
1418 struct clocksource *clock;
1419 struct timekeeper *real_tk = &tk_core.timekeeper; 1416 struct timekeeper *real_tk = &tk_core.timekeeper;
1420 struct timekeeper *tk = &shadow_timekeeper; 1417 struct timekeeper *tk = &shadow_timekeeper;
1421 cycle_t offset; 1418 cycle_t offset;
@@ -1429,13 +1426,11 @@ void update_wall_time(void)
1429 if (unlikely(timekeeping_suspended)) 1426 if (unlikely(timekeeping_suspended))
1430 goto out; 1427 goto out;
1431 1428
1432 clock = real_tk->clock;
1433
1434#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET 1429#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
1435 offset = real_tk->cycle_interval; 1430 offset = real_tk->cycle_interval;
1436#else 1431#else
1437 offset = clocksource_delta(clock->read(clock), tk->cycle_last, 1432 offset = clocksource_delta(tk->read(tk->clock), tk->cycle_last,
1438 clock->mask); 1433 tk->mask);
1439#endif 1434#endif
1440 1435
1441 /* Check if there's really nothing to do */ 1436 /* Check if there's really nothing to do */