Monotonic count of he number of microseconds since restart Uses PIT interrupts to calibrate the TSC
()
| 57 | /// Uses PIT interrupts to calibrate the TSC |
| 58 | /// |
| 59 | pub fn microseconds_monotonic() -> u64 { |
| 60 | // Number of PIT ticks |
| 61 | let pit = PIT_TICKS.load(Ordering::Relaxed); |
| 62 | // Number of TSC ticks since last PIT interrupt |
| 63 | let tsc = time_stamp_counter() - LAST_TSC.load(Ordering::Relaxed); |
| 64 | |
| 65 | // Number of TSC counts per PIT tick |
| 66 | let tsc_per_pit = TSC_PER_PIT.load(Ordering::Relaxed); |
| 67 | |
| 68 | // PIT frequency is 3_579_545 / 3 = 1_193_181.666 Hz |
| 69 | // each PIT tick is 0.83809534452 microseconds |
| 70 | // 878807 / (1024*1024) = 0.83809566497 |
| 71 | // |
| 72 | // Calculate total TSC then divide to get microseconds |
| 73 | // Note: Don't use TSC directly because jitter in tsc_per_pit would lead to |
| 74 | // non-monotonic outputs |
| 75 | |
| 76 | // Note! This next expression will overflow in about 2 hours : |
| 77 | // 2**64 / (1024 * 1024 * 2270) microseconds |
| 78 | //((pit * tsc_per_pit + tsc) * 878807) / (1024*1024 * tsc_per_pit) |
| 79 | |
| 80 | const SCALED_TSC_RATE: u64 = 16; |
| 81 | let scaled_tsc = (tsc * SCALED_TSC_RATE) / tsc_per_pit; |
| 82 | |
| 83 | // Factorize 878807 = 437 * 2011 |
| 84 | // This will overflow in about 142 years : 2**64 / 4096 microseconds |
| 85 | ((((pit * SCALED_TSC_RATE + scaled_tsc) * 2011) / 4096) * 437) / (256 * SCALED_TSC_RATE) |
| 86 | } |
no test coverage detected