[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |