[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] More time-interface fixes.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 217fb2d1f364176571396fb7b4bf89222927631e
# Parent  7931f14bd447465bfdf2a458f70ccac55edcad03
More time-interface fixes.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 7931f14bd447 -r 217fb2d1f364 
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Sat Aug  6 09:54:57 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Sat Aug  6 15:24:22 2005
@@ -115,7 +115,8 @@
        u32 version;
 };
 static DEFINE_PER_CPU(struct shadow_time_info, shadow_time);
-static struct timeval shadow_tv;
+static struct timespec shadow_tv;
+static u32 shadow_tv_version;
 
 /* Keep track of last time we did processing/updating of jiffies and xtime. */
 static u64 processed_system_time;   /* System time (ns) at last processing. */
@@ -123,18 +124,6 @@
 
 #define NS_PER_TICK (1000000000ULL/HZ)
 
-#define HANDLE_USEC_UNDERFLOW(_tv) do {                \
-       while ((_tv).tv_usec < 0) {             \
-               (_tv).tv_usec += USEC_PER_SEC;  \
-               (_tv).tv_sec--;                 \
-       }                                       \
-} while (0)
-#define HANDLE_USEC_OVERFLOW(_tv) do {         \
-       while ((_tv).tv_usec >= USEC_PER_SEC) { \
-               (_tv).tv_usec -= USEC_PER_SEC;  \
-               (_tv).tv_sec++;                 \
-       }                                       \
-} while (0)
 static inline void __normalize_time(time_t *sec, s64 *nsec)
 {
        while (*nsec >= NSEC_PER_SEC) {
@@ -231,14 +220,16 @@
        shared_info_t *s = HYPERVISOR_shared_info;
        long wtm_nsec, xtime_nsec;
        time_t wtm_sec, xtime_sec;
-       u64 tmp, usec;
-
-       if ((shadow_tv.tv_sec == s->wc_sec) &&
-           (shadow_tv.tv_usec == s->wc_usec))
-               return;
-
-       shadow_tv.tv_sec  = s->wc_sec;
-       shadow_tv.tv_usec = s->wc_usec;
+       u64 tmp, nsec;
+
+       do {
+               shadow_tv_version = s->wc_version;
+               rmb();
+               shadow_tv.tv_sec  = s->wc_sec;
+               shadow_tv.tv_nsec = s->wc_nsec;
+               rmb();
+       }
+       while ((s->wc_version & 1) | (shadow_tv_version ^ s->wc_version));
 
        if (INDEPENDENT_WALLCLOCK())
                return;
@@ -247,15 +238,14 @@
                return;
 
        /* Adjust wall-clock time base based on wall_jiffies ticks. */
-       usec = processed_system_time;
-       do_div(usec, 1000);
-       usec += (u64)shadow_tv.tv_sec * 1000000ULL;
-       usec += (u64)shadow_tv.tv_usec;
-       usec -= (jiffies - wall_jiffies) * (USEC_PER_SEC / HZ);
+       nsec = processed_system_time;
+       nsec += (u64)shadow_tv.tv_sec * 1000000000ULL;
+       nsec += (u64)shadow_tv.tv_nsec;
+       nsec -= (jiffies - wall_jiffies) * (u64)(NSEC_PER_SEC / HZ);
 
        /* Split wallclock base into seconds and nanoseconds. */
-       tmp = usec;
-       xtime_nsec = do_div(tmp, 1000000) * 1000ULL;
+       tmp = nsec;
+       xtime_nsec = do_div(tmp, 1000000000);
        xtime_sec  = (time_t)tmp;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
@@ -279,7 +269,7 @@
        dst = &per_cpu(shadow_time, smp_processor_id());
 
        do {
-               dst->version = src->time_version2;
+               dst->version = src->version;
                rmb();
                dst->tsc_timestamp     = src->tsc_timestamp;
                dst->system_timestamp  = src->system_time;
@@ -287,7 +277,7 @@
                dst->tsc_shift         = src->tsc_shift;
                rmb();
        }
-       while (dst->version != src->time_version1);
+       while ((src->version & 1) | (dst->version ^ src->version));
 
        dst->tsc_to_usec_mul = dst->tsc_to_nsec_mul / 1000;
 }
@@ -300,7 +290,7 @@
        src = &HYPERVISOR_shared_info->vcpu_time[cpu]; 
        dst = &per_cpu(shadow_time, cpu); 
 
-       return (dst->version == src->time_version2);
+       return (dst->version == src->version);
 }
 
 /*
@@ -469,7 +459,7 @@
                dom0_op_t op;
                op.cmd = DOM0_SETTIME;
                op.u.settime.secs        = xentime.tv_sec;
-               op.u.settime.usecs       = xentime.tv_nsec / NSEC_PER_USEC;
+               op.u.settime.nsecs       = xentime.tv_nsec;
                op.u.settime.system_time = shadow->system_timestamp;
                write_sequnlock_irq(&xtime_lock);
                HYPERVISOR_dom0_op(&op);
@@ -574,7 +564,7 @@
        }
        while (!time_values_up_to_date(cpu));
 
-       if (unlikely(delta < 0) || unlikely(delta_cpu < 0)) {
+       if (unlikely(delta < (s64)-1000000) || unlikely(delta_cpu < 0)) {
                printk("Timer ISR/%d: Time went backwards: "
                       "delta=%lld cpu_delta=%lld shadow=%lld "
                       "off=%lld processed=%lld cpu_processed=%lld\n",
@@ -603,7 +593,8 @@
                profile_tick(CPU_PROFILING, regs);
        }
 
-       update_wallclock();
+       if (unlikely(shadow_tv_version != HYPERVISOR_shared_info->wc_version))
+               update_wallclock();
 }
 
 /*
@@ -792,8 +783,6 @@
 #endif
        get_time_values_from_xen();
        update_wallclock();
-       xtime.tv_sec = shadow_tv.tv_sec;
-       xtime.tv_nsec = shadow_tv.tv_usec * NSEC_PER_USEC;
        set_normalized_timespec(&wall_to_monotonic,
                -xtime.tv_sec, -xtime.tv_nsec);
        processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
diff -r 7931f14bd447 -r 217fb2d1f364 xen/arch/ia64/xentime.c
--- a/xen/arch/ia64/xentime.c   Sat Aug  6 09:54:57 2005
+++ b/xen/arch/ia64/xentime.c   Sat Aug  6 15:24:22 2005
@@ -48,7 +48,7 @@
 static s_time_t        stime_irq = 0x0;       /* System time at last 'time 
update' */
 unsigned long itc_scale;
 unsigned long itc_at_irq;
-static unsigned long   wc_sec, wc_usec; /* UTC time at last 'time update'.   */
+static unsigned long   wc_sec, wc_nsec; /* UTC time at last 'time update'.   */
 //static rwlock_t        time_lock = RW_LOCK_UNLOCKED;
 static irqreturn_t vmx_timer_interrupt (int irq, void *dev_id, struct pt_regs 
*regs);
 
@@ -103,25 +103,22 @@
 }
 
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
-void do_settime(unsigned long secs, unsigned long usecs, u64 system_time_base)
+void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
 {
 #ifdef  CONFIG_VTI
-    s64 delta;
-    long _usecs = (long)usecs;
+    u64 _nsecs;
 
     write_lock_irq(&xtime_lock);
 
-    delta = (s64)(stime_irq - system_time_base);
-
-    _usecs += (long)(delta/1000);
-    while ( _usecs >= 1000000 ) 
+    _nsecs = (u64)nsecs + (s64)(stime_irq - system_time_base);
+    while ( _nsecs >= 1000000000 ) 
     {
-        _usecs -= 1000000;
+        _nsecs -= 1000000000;
         secs++;
     }
 
     wc_sec  = secs;
-    wc_usec = _usecs;
+    wc_nsec = (unsigned long)_nsecs;
 
     write_unlock_irq(&xtime_lock);
 
@@ -290,13 +287,13 @@
     /* Wallclock time starts as the initial RTC time. */
     efi_gettimeofday(&tm);
     wc_sec  = tm.tv_sec;
-    wc_usec = tm.tv_nsec/1000;
+    wc_nsec = tm.tv_nsec;
 
 
     printk("Time init:\n");
     printk(".... System Time: %ldns\n", NOW());
     printk(".... scale:       %16lX\n", itc_scale);
-    printk(".... Wall Clock:  %lds %ldus\n", wc_sec, wc_usec);
+    printk(".... Wall Clock:  %lds %ldus\n", wc_sec, wc_nsec/1000);
 
     return 0;
 }
@@ -338,10 +335,10 @@
             (*(unsigned long *)&jiffies_64)++;
 
             /* Update wall time. */
-            wc_usec += 1000000/HZ;
-            if ( wc_usec >= 1000000 )
+            wc_nsec += 1000000000/HZ;
+            if ( wc_nsec >= 1000000000 )
             {
-                wc_usec -= 1000000;
+                wc_nsec -= 1000000000;
                 wc_sec++;
             }
 
diff -r 7931f14bd447 -r 217fb2d1f364 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Sat Aug  6 09:54:57 2005
+++ b/xen/arch/x86/domain.c     Sat Aug  6 15:24:22 2005
@@ -279,6 +279,8 @@
     
     shadow_lock_init(d);        
     INIT_LIST_HEAD(&d->arch.free_shadow_frames);
+
+    init_domain_time(d);
 }
 
 void arch_do_boot_vcpu(struct vcpu *v)
diff -r 7931f14bd447 -r 217fb2d1f364 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Sat Aug  6 09:54:57 2005
+++ b/xen/arch/x86/time.c       Sat Aug  6 15:24:22 2005
@@ -43,7 +43,7 @@
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 int timer_ack = 0;
 unsigned long volatile jiffies;
-static unsigned long wc_sec, wc_usec; /* UTC time at last 'time update'. */
+static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
 
 struct time_scale {
     int shift;
@@ -630,25 +630,32 @@
     return now;
 }
 
+static inline void version_update_begin(u32 *version)
+{
+    /* Explicitly OR with 1 just in case version number gets out of sync. */
+    *version = (*version + 1) | 1;
+    wmb();
+}
+
+static inline void version_update_end(u32 *version)
+{
+    wmb();
+    (*version)++;
+}
+
 static inline void __update_dom_time(struct vcpu *v)
 {
     struct cpu_time       *t = &cpu_time[smp_processor_id()];
     struct vcpu_time_info *u = &v->domain->shared_info->vcpu_time[v->vcpu_id];
 
-    u->time_version1++;
-    wmb();
+    version_update_begin(&u->version);
 
     u->tsc_timestamp     = t->local_tsc_stamp;
     u->system_time       = t->stime_local_stamp;
     u->tsc_to_system_mul = t->tsc_scale.mul_frac;
     u->tsc_shift         = (s8)t->tsc_scale.shift;
 
-    wmb();
-    u->time_version2++;
-
-    /* Should only do this during do_settime(). */
-    v->domain->shared_info->wc_sec  = wc_sec;
-    v->domain->shared_info->wc_usec = wc_usec;
+    version_update_end(&u->version);
 }
 
 void update_dom_time(struct vcpu *v)
@@ -659,21 +666,39 @@
 }
 
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
-void do_settime(unsigned long secs, unsigned long usecs, u64 system_time_base)
-{
-    u64 x, base_usecs;
-    u32 y;
-
-    base_usecs = system_time_base;
-    do_div(base_usecs, 1000);
-
-    x = (secs * 1000000ULL) + (u64)usecs + base_usecs;
-    y = do_div(x, 1000000);
-
-    wc_sec  = (unsigned long)x;
-    wc_usec = (unsigned long)y;
-
-    __update_dom_time(current);
+void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
+{
+    u64 x;
+    u32 y, _wc_sec, _wc_nsec;
+    struct domain *d;
+    shared_info_t *s;
+
+    x = (secs * 1000000000ULL) + (u64)nsecs + system_time_base;
+    y = do_div(x, 1000000000);
+
+    wc_sec  = _wc_sec  = (u32)x;
+    wc_nsec = _wc_nsec = (u32)y;
+
+    read_lock(&domlist_lock);
+
+    for_each_domain ( d )
+    {
+        s = d->shared_info;
+        version_update_begin(&s->wc_version);
+        s->wc_sec  = _wc_sec;
+        s->wc_nsec = _wc_nsec;
+        version_update_end(&s->wc_version);
+    }
+
+    read_unlock(&domlist_lock);
+}
+
+void init_domain_time(struct domain *d)
+{
+    version_update_begin(&d->shared_info->wc_version);
+    d->shared_info->wc_sec  = wc_sec;
+    d->shared_info->wc_nsec = wc_nsec;
+    version_update_end(&d->shared_info->wc_version);
 }
 
 static void local_time_calibration(void *unused)
diff -r 7931f14bd447 -r 217fb2d1f364 xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c     Sat Aug  6 09:54:57 2005
+++ b/xen/common/dom0_ops.c     Sat Aug  6 15:24:22 2005
@@ -475,7 +475,7 @@
     case DOM0_SETTIME:
     {
         do_settime(op->u.settime.secs, 
-                   op->u.settime.usecs, 
+                   op->u.settime.nsecs, 
                    op->u.settime.system_time);
         ret = 0;
     }
diff -r 7931f14bd447 -r 217fb2d1f364 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Sat Aug  6 09:54:57 2005
+++ b/xen/include/asm-x86/time.h        Sat Aug  6 15:24:22 2005
@@ -7,4 +7,7 @@
 extern void calibrate_tsc_bp(void);
 extern void calibrate_tsc_ap(void);
 
+struct domain;
+extern void init_domain_time(struct domain *d);
+
 #endif /* __X86_TIME_H__ */
diff -r 7931f14bd447 -r 217fb2d1f364 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h     Sat Aug  6 09:54:57 2005
+++ b/xen/include/public/dom0_ops.h     Sat Aug  6 15:24:22 2005
@@ -131,14 +131,14 @@
 } dom0_debug_t;
 
 /*
- * Set clock such that it would read <secs,usecs> after 00:00:00 UTC,
+ * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC,
  * 1 January, 1970 if the current system time was <system_time>.
  */
 #define DOM0_SETTIME          17
 typedef struct {
     /* IN variables. */
     u32 secs;
-    u32 usecs;
+    u32 nsecs;
     u64 system_time;
 } dom0_settime_t;
 
diff -r 7931f14bd447 -r 217fb2d1f364 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Sat Aug  6 09:54:57 2005
+++ b/xen/include/public/xen.h  Sat Aug  6 15:24:22 2005
@@ -331,14 +331,15 @@
 
 typedef struct vcpu_time_info {
     /*
-     * The following values are updated periodically (and not necessarily
-     * atomically!). The guest OS detects this because 'time_version1' is
-     * incremented just before updating these values, and 'time_version2' is
-     * incremented immediately after. See the Xen-specific Linux code for an
-     * example of how to read these values safely (arch/xen/kernel/time.c).
+     * Updates to the following values are preceded and followed by an
+     * increment of 'version'. The guest can therefore detect updates by
+     * looking for changes to 'version'. If the least-significant bit of
+     * the version number is set then an update is in progress and the guest
+     * must wait to read a consistent set of values.
+     * The correct way to interact with the version number is similar to
+     * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
      */
-    u32 time_version1;
-    u32 time_version2;
+    u32 version;
     u64 tsc_timestamp;   /* TSC at last update of time vals.  */
     u64 system_time;     /* Time, in nanosecs, since boot.    */
     /*
@@ -400,8 +401,9 @@
      * Wallclock time: updated only by control software. Guests should base
      * their gettimeofday() syscall on this wallclock-base value.
      */
-    u32                wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
-    u32                wc_usec;         /* Usecs 00:00:00 UTC, Jan 1, 1970.  */
+    u32 wc_version;      /* Version counter: see vcpu_time_info_t. */
+    u32 wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
+    u32 wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
 
     arch_shared_info_t arch;
 
diff -r 7931f14bd447 -r 217fb2d1f364 xen/include/xen/time.h
--- a/xen/include/xen/time.h    Sat Aug  6 09:54:57 2005
+++ b/xen/include/xen/time.h    Sat Aug  6 15:24:22 2005
@@ -57,7 +57,7 @@
 
 extern void update_dom_time(struct vcpu *v);
 extern void do_settime(
-    unsigned long secs, unsigned long usecs, u64 system_time_base);
+    unsigned long secs, unsigned long nsecs, u64 system_time_base);
 
 #endif /* __XEN_TIME_H__ */
 

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.