Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 2589

kernel-2.6.18-128.1.10.el5.src.rpm

From: Prarit Bhargava <prarit@redhat.com>
Date: Mon, 22 Sep 2008 14:46:13 -0400
Subject: [x86_64] revert time syscall changes
Message-id: 48D7E7F5.8050208@redhat.com
O-Subject: Re: [RHEL5.3 PATCH] Revert time() syscall changes
Bugzilla: 461184
RH-Acked-by: Aristeu Rozanski <aris@redhat.com>
RH-Acked-by: Jeff Moyer <jmoyer@redhat.com>
RH-Acked-by: Jarod Wilson <jwilson@redhat.com>
RH-Acked-by: Brian Maly <bmaly@redhat.com>

Revert time() syscall changes made in 250708.

In the past two or three years, RH has not run any gettimeofday() or time()
tests on the RHEL5 kernel because of what appeared to be HW issues.

I finally upon the real issue behind the problems with gettimeofday() in 250708,
rounding errors were compounding and returning an occasional "off-by-one"
result on gettimeofday() queries.

After patching the kernel, I turned on the gettimeofday testsuite in RHTS and
noted that all tests but one passed.  The test that didn't pass was
tests/kernel/syscalls/gettimeofday/timedifftest-qa.c

This test does

time()
gettimeofday()
time()

and compares the values to determine if "time" is increasing.  If time
decreases, the test fails.

[Aside: The difference between time() and gettimeofday() is that time() returns
the # of seconds since Jan 1, 1970 and gettimeofday() returns the # of seconds
and microseconds since Jan 1, 1970.]

The test failed after my initial patch for 250708 because the value returned in
time() does not take into account the amount of time since the last timer
interrupt and "now", whereas gettimeofday() does take this small amount into
account in the calculation.  This resulted in an occasional error in the value
that time() reports.

For example,

A timer interrupt is handled.  t(int) = 10001 seconds

time() is called and returns t(time) = t(int) = 10001 seconds

gettimeofday is called and returns t(time) = t(int) + delta(now-t(int)) = 10001
\+ 1 = 10002 seconds

time() is called again, and returns t(time) = t(int) = 10001 seconds

To fix this problem I changed time() to now call gettimeofday() and return the
macroscopic portion of the gettimeofday() calculation.  Coincidentally, this
solution matched upstream.

With the change a call to time() results in a read of the clock which takes
some time and IMO is responsible for the performance hit.

Without this fix, the timedifftest-qa.c test _will fail_ 100% of the time.
IIRC, a similar test is performed in the ltp testsuite and it will fail as
well.

However, jturner noted that performance testing on the new time() syscall
resulted in a 2200% increase in the amount of time to call time().  This is
unacceptable so I am reverting this small change which will leave time()
and gettimeofday() unsynchronized in RHEL5.

Note that this revert does not effect the gettimeofday() syscall modifications.

jburke has already disabled the timedifftest-qa.c test in RHTS.

Resolves BZ 461184.

diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index e8357cd..69719d6 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -137,17 +137,12 @@ int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
  * unlikely */
 time_t __vsyscall(1) vtime(time_t *t)
 {
-	struct timeval tv;
-
 	if (!__sysctl_vsyscall)
 		return time_syscall(t);
+	else if (t)
+		*t = __xtime.tv_sec;
 
-	do_vgettimeofday(&tv);
-
-	if (t)
-		*t = tv.tv_sec;
-
-	return tv.tv_sec;
+	return __xtime.tv_sec;
 }
 
 /* Fast way to get current CPU and node.