WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] xen/x86: fix for special behavior of

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] xen/x86: fix for special behavior of first sys_settimeofday(NULL, &tz) invocation
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 09 Jul 2010 04:51:13 -0700
Delivery-date: Fri, 09 Jul 2010 04:54:21 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1276866717 -3600
# Node ID 7b350604ce957e12146afc432c37c81c0b75e8fc
# Parent  a24d8631a0007dcb31b128452c6162ea796b05aa
xen/x86: fix for special behavior of first sys_settimeofday(NULL, &tz) 
invocation

The data Xen's time implementation maintains to make do_gettimeofday()
return values monotonic needs to be reset not only during normal
do_gettimeofday() invocations, but also when the clock gets warped
due to the hardware (CMOS) clock running on local (rather than UTC)
time.

Additionally there was a time window in do_gettimeofday() (between
the end of the xtime read loop and the acquiring of the monotonicity
data lock) where, if on another processor do_settimeofday() would
execute to completion, the zeroes written by the latter could get
overwritten by the former with values obtained before the time was
updated. This now gets prevented by maintaining a version for the
monotonicity data.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---
 arch/i386/kernel/time-xen.c |   55 ++++++++++++++++++++++++++++----------------
 kernel/time.c               |    3 ++
 2 files changed, 38 insertions(+), 20 deletions(-)

diff -r a24d8631a000 -r 7b350604ce95 arch/i386/kernel/time-xen.c
--- a/arch/i386/kernel/time-xen.c       Fri Jun 11 09:37:25 2010 +0100
+++ b/arch/i386/kernel/time-xen.c       Fri Jun 18 14:11:57 2010 +0100
@@ -114,9 +114,6 @@ static struct timespec shadow_tv;
 static struct timespec shadow_tv;
 static u32 shadow_tv_version;
 
-static struct timeval monotonic_tv;
-static spinlock_t monotonic_lock = SPIN_LOCK_UNLOCKED;
-
 /* Keep track of last time we did processing/updating of jiffies and xtime. */
 static u64 processed_system_time;   /* System time (ns) at last processing. */
 static DEFINE_PER_CPU(u64, processed_system_time);
@@ -377,6 +374,12 @@ void rtc_cmos_write(unsigned char val, u
 }
 EXPORT_SYMBOL(rtc_cmos_write);
 
+static struct {
+       spinlock_t lock;
+       struct timeval tv;
+       u32 version;
+} monotonic = { .lock = SPIN_LOCK_UNLOCKED };
+
 /*
  * This version of gettimeofday has microsecond resolution
  * and better than microsecond precision on fast x86 machines with TSC.
@@ -389,7 +392,7 @@ void do_gettimeofday(struct timeval *tv)
        s64 nsec;
        unsigned int cpu;
        struct shadow_time_info *shadow;
-       u32 local_time_version;
+       u32 local_time_version, monotonic_version;
 
        cpu = get_cpu();
        shadow = &per_cpu(shadow_time, cpu);
@@ -412,6 +415,8 @@ void do_gettimeofday(struct timeval *tv)
                nsec = shadow->system_timestamp - processed_system_time;
                __normalize_time(&sec, &nsec);
                usec += (long)nsec / NSEC_PER_USEC;
+
+               monotonic_version = monotonic.version;
 
                if (unlikely(!time_values_up_to_date(cpu))) {
                        /*
@@ -434,23 +439,32 @@ void do_gettimeofday(struct timeval *tv)
                sec++;
        }
 
-       spin_lock_irqsave(&monotonic_lock, flags);
-       if ((sec > monotonic_tv.tv_sec) ||
-           ((sec == monotonic_tv.tv_sec) && (usec > monotonic_tv.tv_usec)))
-       {
-               monotonic_tv.tv_sec = sec;
-               monotonic_tv.tv_usec = usec;
-       } else {
-               sec = monotonic_tv.tv_sec;
-               usec = monotonic_tv.tv_usec;
-       }
-       spin_unlock_irqrestore(&monotonic_lock, flags);
+       spin_lock_irqsave(&monotonic.lock, flags);
+       if (unlikely(sec < monotonic.tv.tv_sec) ||
+           (sec == monotonic.tv.tv_sec && usec <= monotonic.tv.tv_usec)) {
+               sec = monotonic.tv.tv_sec;
+               usec = monotonic.tv.tv_usec;
+       } else if (likely(monotonic_version == monotonic.version)) {
+               monotonic.tv.tv_sec = sec;
+               monotonic.tv.tv_usec = usec;
+       }
+       spin_unlock_irqrestore(&monotonic.lock, flags);
 
        tv->tv_sec = sec;
        tv->tv_usec = usec;
 }
 
 EXPORT_SYMBOL(do_gettimeofday);
+
+/* Reset monotonic gettimeofday() timeval. */
+static inline void monotonic_reset(void)
+{
+       spin_lock(&monotonic.lock);
+       monotonic.tv.tv_sec = 0;
+       monotonic.tv.tv_usec = 0;
+       ++monotonic.version;
+       spin_unlock(&monotonic.lock);
+}
 
 int do_settimeofday(struct timespec *tv)
 {
@@ -459,6 +473,11 @@ int do_settimeofday(struct timespec *tv)
        unsigned int cpu;
        struct shadow_time_info *shadow;
        struct xen_platform_op op;
+
+       if (unlikely(!tv)) {
+               monotonic_reset();
+               return 0;
+       }
 
        if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
                return -EINVAL;
@@ -499,11 +518,7 @@ int do_settimeofday(struct timespec *tv)
        }
        ntp_clear();
 
-       /* Reset monotonic gettimeofday() timeval. */
-       spin_lock(&monotonic_lock);
-       monotonic_tv.tv_sec = 0;
-       monotonic_tv.tv_usec = 0;
-       spin_unlock(&monotonic_lock);
+       monotonic_reset();
 
        write_sequnlock_irq(&xtime_lock);
 
diff -r a24d8631a000 -r 7b350604ce95 kernel/time.c
--- a/kernel/time.c     Fri Jun 11 09:37:25 2010 +0100
+++ b/kernel/time.c     Fri Jun 18 14:11:57 2010 +0100
@@ -135,6 +135,9 @@ static inline void warp_clock(void)
        wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60;
        xtime.tv_sec += sys_tz.tz_minuteswest * 60;
        time_interpolator_reset();
+#if defined(CONFIG_XEN) && defined(CONFIG_X86)
+       do_settimeofday(NULL);
+#endif
        write_sequnlock_irq(&xtime_lock);
        clock_was_set();
 }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] xen/x86: fix for special behavior of first sys_settimeofday(NULL, &tz) invocation, Xen patchbot-linux-2.6.18-xen <=