Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 90984
b: refs/heads/master
c: d8bb6f4
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Gleixner authored and Ingo Molnar committed Apr 19, 2008
1 parent 12459fd commit b2ecc4a
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f1326973262382150c26bf4dfccd0fce310c4a9c
refs/heads/master: d8bb6f4c1670c8324e4135c61ef07486f7f17379
15 changes: 14 additions & 1 deletion trunk/arch/x86/kernel/tsc_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,27 @@ core_initcall(cpufreq_tsc);
/* clock source code */

static unsigned long current_tsc_khz;
static struct clocksource clocksource_tsc;

/*
* We compare the TSC to the cycle_last value in the clocksource
* structure to avoid a nasty time-warp issue. This can be observed in
* a very small window right after one CPU updated cycle_last under
* xtime lock and the other CPU reads a TSC value which is smaller
* than the cycle_last reference value due to a TSC which is slighty
* behind. This delta is nowhere else observable, but in that case it
* results in a forward time jump in the range of hours due to the
* unsigned delta calculation of the time keeping core code, which is
* necessary to support wrapping clocksources like pm timer.
*/
static cycle_t read_tsc(void)
{
cycle_t ret;

rdtscll(ret);

return ret;
return ret >= clocksource_tsc.cycle_last ?
ret : clocksource_tsc.cycle_last;
}

static struct clocksource clocksource_tsc = {
Expand Down
23 changes: 20 additions & 3 deletions trunk/arch/x86/kernel/tsc_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <asm/hpet.h>
#include <asm/timex.h>
#include <asm/timer.h>
#include <asm/vgtod.h>

static int notsc __initdata = 0;

Expand Down Expand Up @@ -287,18 +288,34 @@ int __init notsc_setup(char *s)

__setup("notsc", notsc_setup);

static struct clocksource clocksource_tsc;

/* clock source code: */
/*
* We compare the TSC to the cycle_last value in the clocksource
* structure to avoid a nasty time-warp. This can be observed in a
* very small window right after one CPU updated cycle_last under
* xtime/vsyscall_gtod lock and the other CPU reads a TSC value which
* is smaller than the cycle_last reference value due to a TSC which
* is slighty behind. This delta is nowhere else observable, but in
* that case it results in a forward time jump in the range of hours
* due to the unsigned delta calculation of the time keeping core
* code, which is necessary to support wrapping clocksources like pm
* timer.
*/
static cycle_t read_tsc(void)
{
cycle_t ret = (cycle_t)get_cycles();
return ret;

return ret >= clocksource_tsc.cycle_last ?
ret : clocksource_tsc.cycle_last;
}

static cycle_t __vsyscall_fn vread_tsc(void)
{
cycle_t ret = (cycle_t)vget_cycles();
return ret;

return ret >= __vsyscall_gtod_data.clock.cycle_last ?
ret : __vsyscall_gtod_data.clock.cycle_last;
}

static struct clocksource clocksource_tsc = {
Expand Down
2 changes: 2 additions & 0 deletions trunk/kernel/time/timekeeping.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ static void change_clocksource(void)
if (clock == new)
return;

new->cycle_last = 0;
now = clocksource_read(new);
nsec = __get_nsec_offset();
timespec_add_ns(&xtime, nsec);
Expand Down Expand Up @@ -295,6 +296,7 @@ static int timekeeping_resume(struct sys_device *dev)
timespec_add_ns(&xtime, timekeeping_suspend_nsecs);
update_xtime_cache(0);
/* re-base the last cycle value */
clock->cycle_last = 0;
clock->cycle_last = clocksource_read(clock);
clock->error = 0;
timekeeping_suspended = 0;
Expand Down

0 comments on commit b2ecc4a

Please sign in to comment.