Commit 9d64273c authored by David Mosberger's avatar David Mosberger Committed by Linus Torvalds

[PATCH] time-offset patch

On ia64 MP machines, we use the cycle counter register of each CPU to
obtain fine-grained time-stamps.  At boot-time, we synchronize the
counters as close as possible (similar to x86, though with a different
algorithm).  But even with this synchronization, there is still a
small (really: tiny) chance that a process bouncing from one CPU to
another could observe time going backwards.  To guard against this, I
maintain a global variable called "last_time_offset" which keeps track
of the largest time-interpolation value returned so far.  Most of this
is in platform-specific code (arch/ia64/kernel/time.c), but there are
a handful of places in platform-independent code where this variable
needs to be cleared to zero.  This is what the patch below does.  I
didn't put it inside CONFIG_IA64 because I think this can be useful
for other platforms, too.  I suppose I could put it inside CONFIG_SMP
though this would make the code uglier.  If you think it's OK, please
apply, otherwise, I'd appreciate your feedback.
parent 5d29ce55
...@@ -39,6 +39,7 @@ struct timezone sys_tz; ...@@ -39,6 +39,7 @@ struct timezone sys_tz;
/* The xtime_lock is not only serializing the xtime read/writes but it's also /* The xtime_lock is not only serializing the xtime read/writes but it's also
serializing all accesses to the global NTP variables now. */ serializing all accesses to the global NTP variables now. */
extern rwlock_t xtime_lock; extern rwlock_t xtime_lock;
extern unsigned long last_time_offset;
#if !defined(__alpha__) && !defined(__ia64__) #if !defined(__alpha__) && !defined(__ia64__)
...@@ -82,6 +83,7 @@ asmlinkage long sys_stime(int * tptr) ...@@ -82,6 +83,7 @@ asmlinkage long sys_stime(int * tptr)
write_lock_irq(&xtime_lock); write_lock_irq(&xtime_lock);
xtime.tv_sec = value; xtime.tv_sec = value;
xtime.tv_usec = 0; xtime.tv_usec = 0;
last_time_offset = 0;
time_adjust = 0; /* stop active adjtime() */ time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC; time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT; time_maxerror = NTP_PHASE_LIMIT;
...@@ -127,6 +129,7 @@ inline static void warp_clock(void) ...@@ -127,6 +129,7 @@ inline static void warp_clock(void)
{ {
write_lock_irq(&xtime_lock); write_lock_irq(&xtime_lock);
xtime.tv_sec += sys_tz.tz_minuteswest * 60; xtime.tv_sec += sys_tz.tz_minuteswest * 60;
last_time_offset = 0;
write_unlock_irq(&xtime_lock); write_unlock_irq(&xtime_lock);
} }
...@@ -386,6 +389,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 ...@@ -386,6 +389,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
txc->calcnt = pps_calcnt; txc->calcnt = pps_calcnt;
txc->errcnt = pps_errcnt; txc->errcnt = pps_errcnt;
txc->stbcnt = pps_stbcnt; txc->stbcnt = pps_stbcnt;
last_time_offset = 0;
write_unlock_irq(&xtime_lock); write_unlock_irq(&xtime_lock);
do_gettimeofday(&txc->time); do_gettimeofday(&txc->time);
return(result); return(result);
......
...@@ -630,6 +630,7 @@ unsigned long wall_jiffies; ...@@ -630,6 +630,7 @@ unsigned long wall_jiffies;
* This spinlock protect us from races in SMP while playing with xtime. -arca * This spinlock protect us from races in SMP while playing with xtime. -arca
*/ */
rwlock_t xtime_lock = RW_LOCK_UNLOCKED; rwlock_t xtime_lock = RW_LOCK_UNLOCKED;
unsigned long last_time_offset;
static inline void update_times(void) static inline void update_times(void)
{ {
...@@ -647,6 +648,7 @@ static inline void update_times(void) ...@@ -647,6 +648,7 @@ static inline void update_times(void)
wall_jiffies += ticks; wall_jiffies += ticks;
update_wall_time(ticks); update_wall_time(ticks);
} }
last_time_offset = 0;
write_unlock_irq(&xtime_lock); write_unlock_irq(&xtime_lock);
calc_load(ticks); calc_load(ticks);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment