Improved the invariant TSC frequency estimation code to ignore readings with a large error.

This commit is contained in:
Michael Möller
2010-10-14 17:30:51 +00:00
parent d78e37b480
commit e7ab97fd84

View File

@@ -121,19 +121,9 @@ namespace OpenHardwareMonitor.Hardware.CPU {
if (hasTimeStampCounter) { if (hasTimeStampCounter) {
estimatedTimeStampCounterFrequency = estimatedTimeStampCounterFrequency =
EstimateTimeStampCounterFrequency(); EstimateTimeStampCounterFrequency();
// set initial values
uint lsb, msb;
WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
lastTime = Stopwatch.GetTimestamp();
lastTimeStampCount = ((ulong)msb << 32) | lsb;
} else { } else {
estimatedTimeStampCounterFrequency = 0; estimatedTimeStampCounterFrequency = 0;
lastTime = 0;
lastTimeStampCount = 0;
} }
timeStampCounterFrequency = estimatedTimeStampCounterFrequency; timeStampCounterFrequency = estimatedTimeStampCounterFrequency;
@@ -259,18 +249,29 @@ namespace OpenHardwareMonitor.Hardware.CPU {
} }
public override void Update() { public override void Update() {
if (hasTimeStampCounter) { if (hasTimeStampCounter && isInvariantTimeStampCounter) {
uint lsb, msb; 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); WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
long time = Stopwatch.GetTimestamp(); long time = Stopwatch.GetTimestamp();
ulong timeStampCount = ((ulong)msb << 32) | lsb; ulong timeStampCount = ((ulong)msb << 32) | lsb;
double delta = ((double)(time - lastTime)) / Stopwatch.Frequency; double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
if (delta > 0.5) { double error = ((double)(time - firstTime)) / Stopwatch.Frequency;
if (isInvariantTimeStampCounter)
timeStampCounterFrequency = // 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); (timeStampCount - lastTimeStampCount) / (1e6 * delta);
else }
timeStampCounterFrequency = estimatedTimeStampCounterFrequency;
lastTimeStampCount = timeStampCount; lastTimeStampCount = timeStampCount;
lastTime = time; lastTime = time;