Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1683

kernel-2.6.18-238.el5.src.rpm

From: Rik van Riel <riel@redhat.com>
Subject: [PATCH RHEL5.1] fix time going backwards in Xen gettimeofday
Date: Thu, 12 Jul 2007 16:25:08 -0400
Bugzilla: 245761
Message-Id: <46968E24.6070006@redhat.com>
Changelog: [XEN] fix time going backwards in gettimeofday


The attached patch is a simple fix to make sure gettimeofday in
x86 and x86-64 Xen is monotonically increasing.  x86-64 is fixed
because it also compiles the arch/i386 file through Makefile
magic.

This patch is in the upstream Xen codebase.

Fixes bug 245761

-- 
Politics is the struggle between those who want to make their country
the best in the world, and those who believe it already is.  Each group
calls the other unpatriotic.


# HG changeset patch
# User kfraser@localhost.localdomain
# Date 1182263776 -3600
# Node ID 87bb8705768a66ceabb15a419c5f86580bffb6bf
# Parent a413dd61e7e5e1bba11bab447184cf5e6b43513a
x86 time: Ensure gettimeofday() is monotonically increasing.
Signed-off-by: Atsushi SAKAI <sakaia@jp.fujitsu.com>

--- a/arch/i386/kernel/time-xen.c	Fri Jun 15 13:33:47 2007 -0600
+++ b/arch/i386/kernel/time-xen.c	Tue Jun 19 15:36:16 2007 +0100
@@ -113,6 +113,9 @@ 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);
@@ -363,6 +366,7 @@ void do_gettimeofday(struct timeval *tv)
 	unsigned long seq;
 	unsigned long usec, sec;
 	unsigned long max_ntp_tick;
+	unsigned long flags;
 	s64 nsec;
 	unsigned int cpu;
 	struct shadow_time_info *shadow;
@@ -423,6 +427,18 @@ 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);
+
 	tv->tv_sec = sec;
 	tv->tv_usec = usec;
 }
@@ -471,6 +487,12 @@ int do_settimeofday(struct timespec *tv)
 		__normalize_time(&sec, &nsec);
 		__update_wallclock(sec, nsec);
 	}
+
+	/* Reset monotonic gettimeofday() timeval. */
+	spin_lock(&monotonic_lock);
+	monotonic_tv.tv_sec = 0;
+	monotonic_tv.tv_usec = 0;
+	spin_unlock(&monotonic_lock);
 
 	write_sequnlock_irq(&xtime_lock);