Skip to content

Commit

Permalink
clocksource: Make delta calculation a function
Browse files Browse the repository at this point in the history
We want to move the TSC sanity check into core code to make NMI safe
accessors to clock monotonic[_raw] possible. For this we need to
sanity check the delta calculation. Create a helper function and
convert all sites to use it.

[ Build fix from jstultz ]

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: John Stultz <john.stultz@linaro.org>
  • Loading branch information
Thomas Gleixner authored and John Stultz committed Jul 23, 2014
1 parent 6438e0d commit 3a97837
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 17 deletions.
12 changes: 7 additions & 5 deletions kernel/time/clocksource.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <linux/kthread.h>

#include "tick-internal.h"
#include "timekeeping_internal.h"

void timecounter_init(struct timecounter *tc,
const struct cyclecounter *cc,
Expand Down Expand Up @@ -249,7 +250,7 @@ void clocksource_mark_unstable(struct clocksource *cs)
static void clocksource_watchdog(unsigned long data)
{
struct clocksource *cs;
cycle_t csnow, wdnow;
cycle_t csnow, wdnow, delta;
int64_t wd_nsec, cs_nsec;
int next_cpu, reset_pending;

Expand Down Expand Up @@ -282,11 +283,12 @@ static void clocksource_watchdog(unsigned long data)
continue;
}

wd_nsec = clocksource_cyc2ns((wdnow - cs->wd_last) & watchdog->mask,
watchdog->mult, watchdog->shift);
delta = clocksource_delta(wdnow, cs->wd_last, watchdog->mask);
wd_nsec = clocksource_cyc2ns(delta, watchdog->mult,
watchdog->shift);

cs_nsec = clocksource_cyc2ns((csnow - cs->cs_last) &
cs->mask, cs->mult, cs->shift);
delta = clocksource_delta(csnow, cs->cs_last, cs->mask);
cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift);
cs->cs_last = csnow;
cs->wd_last = wdnow;

Expand Down
26 changes: 14 additions & 12 deletions kernel/time/timekeeping.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ static inline u32 arch_gettimeoffset(void) { return 0; }

static inline s64 timekeeping_get_ns(struct timekeeper *tk)
{
cycle_t cycle_now, cycle_delta;
cycle_t cycle_now, delta;
struct clocksource *clock;
s64 nsec;

Expand All @@ -182,9 +182,9 @@ static inline s64 timekeeping_get_ns(struct timekeeper *tk)
cycle_now = clock->read(clock);

/* calculate the delta since the last update_wall_time: */
cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
delta = clocksource_delta(cycle_now, clock->cycle_last, clock->mask);

nsec = cycle_delta * tk->mult + tk->xtime_nsec;
nsec = delta * tk->mult + tk->xtime_nsec;
nsec >>= tk->shift;

/* If arch requires, add in get_arch_timeoffset() */
Expand All @@ -193,7 +193,7 @@ static inline s64 timekeeping_get_ns(struct timekeeper *tk)

static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
{
cycle_t cycle_now, cycle_delta;
cycle_t cycle_now, delta;
struct clocksource *clock;
s64 nsec;

Expand All @@ -202,10 +202,10 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
cycle_now = clock->read(clock);

/* calculate the delta since the last update_wall_time: */
cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
delta = clocksource_delta(cycle_now, clock->cycle_last, clock->mask);

/* convert delta to nanoseconds. */
nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift);

/* If arch requires, add in get_arch_timeoffset() */
return nsec + arch_gettimeoffset();
Expand Down Expand Up @@ -336,23 +336,23 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
*/
static void timekeeping_forward_now(struct timekeeper *tk)
{
cycle_t cycle_now, cycle_delta;
cycle_t cycle_now, delta;
struct clocksource *clock;
s64 nsec;

clock = tk->clock;
cycle_now = clock->read(clock);
cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
delta = clocksource_delta(cycle_now, clock->cycle_last, clock->mask);
tk->cycle_last = clock->cycle_last = cycle_now;

tk->xtime_nsec += cycle_delta * tk->mult;
tk->xtime_nsec += delta * tk->mult;

/* If arch requires, add in get_arch_timeoffset() */
tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift;

tk_normalize_xtime(tk);

nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
nsec = clocksource_cyc2ns(delta, clock->mult, clock->shift);
timespec64_add_ns(&tk->raw_time, nsec);
}

Expand Down Expand Up @@ -1026,7 +1026,8 @@ static void timekeeping_resume(void)
u32 shift = clock->shift;
s64 nsec = 0;

cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
cycle_delta = clocksource_delta(cycle_now, clock->cycle_last,
clock->mask);

/*
* "cycle_delta * mutl" may cause 64 bits overflow, if the
Expand Down Expand Up @@ -1432,7 +1433,8 @@ void update_wall_time(void)
#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
offset = real_tk->cycle_interval;
#else
offset = (clock->read(clock) - clock->cycle_last) & clock->mask;
offset = clocksource_delta(clock->read(clock), clock->cycle_last,
clock->mask);
#endif

/* Check if there's really nothing to do */
Expand Down
6 changes: 6 additions & 0 deletions kernel/time/timekeeping_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/*
* timekeeping debug functions
*/
#include <linux/clocksource.h>
#include <linux/time.h>

#ifdef CONFIG_DEBUG_FS
Expand All @@ -11,4 +12,9 @@ extern void tk_debug_account_sleep_time(struct timespec64 *t);
#define tk_debug_account_sleep_time(x)
#endif

static inline cycle_t clocksource_delta(cycle_t now, cycle_t last, cycle_t mask)
{
return (now - last) & mask;
}

#endif /* _TIMEKEEPING_INTERNAL_H */

0 comments on commit 3a97837

Please sign in to comment.