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

[Xen-changelog] Fix wallclock time when the offset relative to the epoch



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID f6d6d17eaeb5f04efea7f9d8f753a91ffff0479d
# Parent  37ee6b4b409e67001d2c3054e9300bc08bc49fa9
Fix wallclock time when the offset relative to the epoch
(1 Jan 1970 00:00:00) is negative. This happens in some
LTP tests, for example.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 37ee6b4b409e -r f6d6d17eaeb5 
linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Fri Aug 12 09:14:02 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c  Fri Aug 12 13:06:23 2005
@@ -231,18 +231,32 @@
 {
        long wtm_nsec, xtime_nsec;
        time_t wtm_sec, xtime_sec;
-       u64 tmp, wc_nsec;
+       s64 tmp, wc_nsec;
 
        /* Adjust wall-clock time base based on wall_jiffies ticks. */
        wc_nsec = processed_system_time;
-       wc_nsec += (u64)sec * 1000000000ULL;
-       wc_nsec += (u64)nsec;
+       wc_nsec += (sec * 1000000000LL) + nsec;
        wc_nsec -= (jiffies - wall_jiffies) * (u64)(NSEC_PER_SEC / HZ);
 
        /* Split wallclock base into seconds and nanoseconds. */
-       tmp = wc_nsec;
-       xtime_nsec = do_div(tmp, 1000000000);
-       xtime_sec  = (time_t)tmp;
+       if ( (tmp = wc_nsec) < 0 )
+       {
+               /* -ve UTC offset => -ve seconds, +ve nanoseconds. */
+               tmp = -tmp;
+               xtime_nsec = do_div(tmp, 1000000000);
+               tmp = -tmp;
+               if ( xtime_nsec != 0 )
+               {
+                       xtime_nsec = 1000000000 - xtime_nsec;
+                       tmp--;
+               }
+       }
+       else
+       {
+               /* +ve UTC offset => +ve seconds, +ve nanoseconds. */
+               xtime_nsec = do_div(tmp, 1000000000);
+       }
+       xtime_sec = (time_t)tmp;
 
        wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - xtime_sec);
        wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - xtime_nsec);
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/arch/ia64/xentime.c
--- a/xen/arch/ia64/xentime.c   Fri Aug 12 09:14:02 2005
+++ b/xen/arch/ia64/xentime.c   Fri Aug 12 13:06:23 2005
@@ -103,7 +103,7 @@
 }
 
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
-void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
+void do_settime(s64 secs, u32 nsecs, u64 system_time_base)
 {
 #ifdef  CONFIG_VTI
     u64 _nsecs;
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Fri Aug 12 09:14:02 2005
+++ b/xen/arch/x86/time.c       Fri Aug 12 13:06:23 2005
@@ -43,7 +43,10 @@
 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
 int timer_ack = 0;
 unsigned long volatile jiffies;
-static u32 wc_sec, wc_nsec; /* UTC time at last 'time update'. */
+
+/* UTC time at system boot. */
+static s64 wc_sec;
+static u32 wc_nsec;
 static spinlock_t wc_lock = SPIN_LOCK_UNLOCKED;
 
 struct time_scale {
@@ -693,18 +696,33 @@
 }
 
 /* Set clock to <secs,usecs> after 00:00:00 UTC, 1 January, 1970. */
-void do_settime(unsigned long secs, unsigned long nsecs, u64 system_time_base)
-{
-    u64 x;
-    u32 y, _wc_sec, _wc_nsec;
+void do_settime(s64 secs, u32 nsecs, u64 system_time_base)
+{
+    s64 x;
+    u32 y;
     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;
+    x = (secs * 1000000000LL) + (u64)nsecs - system_time_base;
+    if ( x < 0 )
+    {
+        /* -ve UTC offset => -ve seconds, +ve nanoseconds. */
+        x = -x;
+        y = do_div(x, 1000000000);
+        x = -x;
+        if ( y != 0 )
+        {
+            y = 1000000000 - y;
+            x--;
+        }
+    }
+    else
+    {
+        y = do_div(x, 1000000000);
+    }
+
+    wc_sec  = x;
+    wc_nsec = y;
 
     read_lock(&domlist_lock);
     spin_lock(&wc_lock);
@@ -713,8 +731,8 @@
     {
         s = d->shared_info;
         version_update_begin(&s->wc_version);
-        s->wc_sec  = _wc_sec;
-        s->wc_nsec = _wc_nsec;
+        s->wc_sec  = x;
+        s->wc_nsec = y;
         version_update_end(&s->wc_version);
     }
 
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h     Fri Aug 12 09:14:02 2005
+++ b/xen/include/public/dom0_ops.h     Fri Aug 12 13:06:23 2005
@@ -133,11 +133,12 @@
 /*
  * 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>.
+ * NB. <secs> can be negative, but <nsecs> must always be non-negative.
  */
 #define DOM0_SETTIME          17
 typedef struct {
     /* IN variables. */
-    u32 secs;
+    s64 secs;
     u32 nsecs;
     u64 system_time;
 } dom0_settime_t;
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/include/public/xen.h
--- a/xen/include/public/xen.h  Fri Aug 12 09:14:02 2005
+++ b/xen/include/public/xen.h  Fri Aug 12 13:06:23 2005
@@ -399,11 +399,12 @@
 
     /*
      * Wallclock time: updated only by control software. Guests should base
-     * their gettimeofday() syscall on this wallclock-base value.
+     * their gettimeofday() syscall on this wallclock-base value, which
+     * indicates UTC when system_time == 0 (i.e., at boot).
      */
     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.  */
+    u32 wc_nsec;         /* Nsecs since 00:00:00 UTC, Jan 1, 1970.  */
+    s64 wc_sec;          /* Secs  since 00:00:00 UTC, Jan 1, 1970.  */
 
     arch_shared_info_t arch;
 
diff -r 37ee6b4b409e -r f6d6d17eaeb5 xen/include/xen/time.h
--- a/xen/include/xen/time.h    Fri Aug 12 09:14:02 2005
+++ b/xen/include/xen/time.h    Fri Aug 12 13:06:23 2005
@@ -56,8 +56,7 @@
 #define MICROSECS(_us)  ((s_time_t)((_us) * 1000ULL))
 
 extern void update_dom_time(struct vcpu *v);
-extern void do_settime(
-    unsigned long secs, unsigned long nsecs, u64 system_time_base);
+extern void do_settime(s64 secs, u32 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®.