From: David Mosberger Date: Fri, 31 May 2002 04:13:19 +0000 (-0700) Subject: [PATCH] time-offset patch X-Git-Tag: v2.5.20~18 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=9d64273c4f865c0a1cd76a3450a3d2bba8262e66;p=history.git [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. --- diff --git a/kernel/time.c b/kernel/time.c index 05a005c3a012..edb7eb7b8b73 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -39,6 +39,7 @@ struct timezone sys_tz; /* The xtime_lock is not only serializing the xtime read/writes but it's also serializing all accesses to the global NTP variables now. */ extern rwlock_t xtime_lock; +extern unsigned long last_time_offset; #if !defined(__alpha__) && !defined(__ia64__) @@ -82,6 +83,7 @@ asmlinkage long sys_stime(int * tptr) write_lock_irq(&xtime_lock); xtime.tv_sec = value; xtime.tv_usec = 0; + last_time_offset = 0; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -127,6 +129,7 @@ inline static void warp_clock(void) { write_lock_irq(&xtime_lock); xtime.tv_sec += sys_tz.tz_minuteswest * 60; + last_time_offset = 0; write_unlock_irq(&xtime_lock); } @@ -386,6 +389,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0 txc->calcnt = pps_calcnt; txc->errcnt = pps_errcnt; txc->stbcnt = pps_stbcnt; + last_time_offset = 0; write_unlock_irq(&xtime_lock); do_gettimeofday(&txc->time); return(result); diff --git a/kernel/timer.c b/kernel/timer.c index 5175ebf0bf32..62a36b5740a7 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -630,6 +630,7 @@ unsigned long wall_jiffies; * This spinlock protect us from races in SMP while playing with xtime. -arca */ rwlock_t xtime_lock = RW_LOCK_UNLOCKED; +unsigned long last_time_offset; static inline void update_times(void) { @@ -647,6 +648,7 @@ static inline void update_times(void) wall_jiffies += ticks; update_wall_time(ticks); } + last_time_offset = 0; write_unlock_irq(&xtime_lock); calc_load(ticks); }