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-devel

[Xen-devel] [PATCH] linux/x86: fix for special behavior of first sys_set

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] linux/x86: fix for special behavior of first sys_settimeofday(NULL, &tz) invocation
From: "Jan Beulich" <JBeulich@xxxxxxxxxx>
Date: Fri, 18 Jun 2010 11:00:18 +0100
Delivery-date: Fri, 18 Jun 2010 03:01:16 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
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>

--- sle10sp3-2010-06-17.orig/arch/i386/kernel/time-xen.c        2009-07-27 
10:22:10.000000000 +0200
+++ sle10sp3-2010-06-17/arch/i386/kernel/time-xen.c     2010-06-18 
08:21:37.000000000 +0200
@@ -119,9 +119,6 @@ static DEFINE_PER_CPU(struct shadow_time
 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);
@@ -384,6 +381,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.
@@ -396,7 +399,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);
@@ -420,6 +423,8 @@ void do_gettimeofday(struct timeval *tv)
                __normalize_time(&sec, &nsec);
                usec += (long)nsec / NSEC_PER_USEC;
 
+               monotonic_version = monotonic.version;
+
                if (unlikely(!time_values_up_to_date(cpu))) {
                        /*
                         * We may have blocked for a long time,
@@ -441,17 +446,16 @@ 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_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);
+       spin_unlock_irqrestore(&monotonic.lock, flags);
 
        tv->tv_sec = sec;
        tv->tv_usec = usec;
@@ -459,6 +463,16 @@ void do_gettimeofday(struct timeval *tv)
 
 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)
 {
        time_t sec;
@@ -467,6 +481,11 @@ int do_settimeofday(struct timespec *tv)
        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;
 
@@ -506,11 +525,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);
 
--- sle10sp3-2010-06-17.orig/kernel/time.c      2010-06-18 08:19:43.000000000 
+0200
+++ sle10sp3-2010-06-17/kernel/time.c   2010-06-17 17:46:07.000000000 +0200
@@ -136,6 +136,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-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] linux/x86: fix for special behavior of first sys_settimeofday(NULL, &tz) invocation, Jan Beulich <=