Improved the invariant TSC frequency estimation code to ignore readings with a large error.
authormoel.mich
Thu, 14 Oct 2010 17:30:51 +0000
changeset 222ba64bb91ebe4
parent 221 a950ba30d4dd
child 223 39f73ac8c2f4
Improved the invariant TSC frequency estimation code to ignore readings with a large error.
Hardware/CPU/GenericCPU.cs
     1.1 --- a/Hardware/CPU/GenericCPU.cs	Thu Oct 14 16:52:23 2010 +0000
     1.2 +++ b/Hardware/CPU/GenericCPU.cs	Thu Oct 14 17:30:51 2010 +0000
     1.3 @@ -121,19 +121,9 @@
     1.4  
     1.5        if (hasTimeStampCounter) {
     1.6          estimatedTimeStampCounterFrequency = 
     1.7 -          EstimateTimeStampCounterFrequency();
     1.8 -        
     1.9 -        // set initial values 
    1.10 -        uint lsb, msb;
    1.11 -        WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
    1.12 -        lastTime = Stopwatch.GetTimestamp();
    1.13 -        lastTimeStampCount = ((ulong)msb << 32) | lsb;
    1.14 -
    1.15 +          EstimateTimeStampCounterFrequency();        
    1.16        } else {
    1.17          estimatedTimeStampCounterFrequency = 0;
    1.18 -
    1.19 -        lastTime = 0;
    1.20 -        lastTimeStampCount = 0;
    1.21        }
    1.22  
    1.23        timeStampCounterFrequency = estimatedTimeStampCounterFrequency;                  
    1.24 @@ -259,18 +249,29 @@
    1.25      }
    1.26  
    1.27      public override void Update() {
    1.28 -      if (hasTimeStampCounter) {
    1.29 +      if (hasTimeStampCounter && isInvariantTimeStampCounter) {
    1.30          uint lsb, msb;
    1.31 +
    1.32 +        // read time before and after getting the TSC to estimate the error
    1.33 +        long firstTime = Stopwatch.GetTimestamp();
    1.34          WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
    1.35          long time = Stopwatch.GetTimestamp();
    1.36 +
    1.37          ulong timeStampCount = ((ulong)msb << 32) | lsb;
    1.38          double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
    1.39 -        if (delta > 0.5) {
    1.40 -          if (isInvariantTimeStampCounter)
    1.41 -            timeStampCounterFrequency = 
    1.42 +        double error = ((double)(time - firstTime)) / Stopwatch.Frequency;
    1.43 +
    1.44 +        // only use data if they are measured accuarte enough (max 0.1ms delay)
    1.45 +        if (error < 0.0001) {
    1.46 +
    1.47 +          // ignore the first reading because there are no initial values 
    1.48 +          // ignore readings with too large or too small time window
    1.49 +          if (lastTime != 0 && delta > 0.5 && delta < 2) {
    1.50 +
    1.51 +            // update the TSC frequency with the new value
    1.52 +            timeStampCounterFrequency =
    1.53                (timeStampCount - lastTimeStampCount) / (1e6 * delta);
    1.54 -          else
    1.55 -            timeStampCounterFrequency = estimatedTimeStampCounterFrequency;
    1.56 +          }
    1.57  
    1.58            lastTimeStampCount = timeStampCount;
    1.59            lastTime = time;