Subject: kern_microtime.c and Xen
To: None <tech-kern@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.eu.org>
List: tech-kern
Date: 01/22/2006 21:32:17
--k+w/mQv8wyuph6w0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,
one of the issues with Xen is that the clock can stall for long period of
time (eventually several clock ticks). When this happens, the code will 
catch up calling hardclock() several time in a row. But this makes
cc_microtime() unhappy.
One of the problems here is that kern_microtime.c uses 32bit arithmetic for
the cpu cycle counter (even if the variables are all 64 bits),
and on fast CPU it can overflow, leading to the time going backward
by about 31mn, as discovered by Jed Davis (see the "Strange numbers from
gettimeofday(2)" thread on port-xen).

cc_microset() isn't really suitable for Xen anyway because of the
way the clock instability, and I'll use a private implementation to
compensate this. However, cc_microtime() is almost OK, and I'd like to avoid
code duplicate if possible.

The problem here is that cc_microtime() uses cpu_counter32() - ci->ci_cc.cc_cc.
This is fine as long as ci_cc_cc is alaso initialised with cpu_counter32,
but because of the overflow issue I want to use a 64bit value for
ci_cc.cc_cc (and I don't want to keep a private variable for this).
This can easily be solved by masking the ci_cc.cc_cc value, as in the
patch below. Is it OK to commit and pullup to netbsd-3 ?

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--

--k+w/mQv8wyuph6w0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff2

Index: kern/kern_microtime.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_microtime.c,v
retrieving revision 1.15
diff -u -r1.15 kern_microtime.c
--- kern/kern_microtime.c	11 Dec 2005 12:24:29 -0000	1.15
+++ kern/kern_microtime.c	22 Jan 2006 20:11:47 -0000
@@ -112,7 +112,7 @@
 		 */
 		simple_lock(&microtime_slock);
 		t = ci->ci_cc_time;
-		cc = cpu_counter32() - ci->ci_cc_cc;
+		cc = cpu_counter32() - (ci->ci_cc_cc & 0xffffffff);
 		if (cc < 0)
 			cc += 0x100000000LL;
 		t.tv_usec += (cc * ci->ci_cc_ms_delta) / ci->ci_cc_denom;

--k+w/mQv8wyuph6w0--