# HG changeset patch # User moel.mich # Date 1287077451 0 # Node ID ba64bb91ebe4e38f29758f2e17a38b581c13d275 # Parent a950ba30d4dd4e8657f2463b502f58a5cff1bca6 Improved the invariant TSC frequency estimation code to ignore readings with a large error. diff -r a950ba30d4dd -r ba64bb91ebe4 Hardware/CPU/GenericCPU.cs --- a/Hardware/CPU/GenericCPU.cs Thu Oct 14 16:52:23 2010 +0000 +++ b/Hardware/CPU/GenericCPU.cs Thu Oct 14 17:30:51 2010 +0000 @@ -121,19 +121,9 @@ if (hasTimeStampCounter) { estimatedTimeStampCounterFrequency = - EstimateTimeStampCounterFrequency(); - - // set initial values - uint lsb, msb; - WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1); - lastTime = Stopwatch.GetTimestamp(); - lastTimeStampCount = ((ulong)msb << 32) | lsb; - + EstimateTimeStampCounterFrequency(); } else { estimatedTimeStampCounterFrequency = 0; - - lastTime = 0; - lastTimeStampCount = 0; } timeStampCounterFrequency = estimatedTimeStampCounterFrequency; @@ -259,18 +249,29 @@ } public override void Update() { - if (hasTimeStampCounter) { + if (hasTimeStampCounter && isInvariantTimeStampCounter) { uint lsb, msb; + + // read time before and after getting the TSC to estimate the error + long firstTime = Stopwatch.GetTimestamp(); WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1); long time = Stopwatch.GetTimestamp(); + ulong timeStampCount = ((ulong)msb << 32) | lsb; double delta = ((double)(time - lastTime)) / Stopwatch.Frequency; - if (delta > 0.5) { - if (isInvariantTimeStampCounter) - timeStampCounterFrequency = + double error = ((double)(time - firstTime)) / Stopwatch.Frequency; + + // only use data if they are measured accuarte enough (max 0.1ms delay) + if (error < 0.0001) { + + // ignore the first reading because there are no initial values + // ignore readings with too large or too small time window + if (lastTime != 0 && delta > 0.5 && delta < 2) { + + // update the TSC frequency with the new value + timeStampCounterFrequency = (timeStampCount - lastTimeStampCount) / (1e6 * delta); - else - timeStampCounterFrequency = estimatedTimeStampCounterFrequency; + } lastTimeStampCount = timeStampCount; lastTime = time;