Kernel: Make TSC based timer monotonic
Prior to this I was just blindly rebasing the current TSC stats every once in a while. Now I check for drift and scale the multiplier accordingly to keep the timer from drifting
This commit is contained in:
@@ -18,9 +18,8 @@ namespace Kernel::API
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t shift;
|
||||
uint64_t mult;
|
||||
uint64_t realtime_seconds;
|
||||
uint64_t realtime_s;
|
||||
uint32_t realtime_ns;
|
||||
} gettime_shared;
|
||||
|
||||
struct
|
||||
@@ -28,6 +27,8 @@ namespace Kernel::API
|
||||
struct
|
||||
{
|
||||
uint32_t seq;
|
||||
uint32_t mult;
|
||||
int8_t shift;
|
||||
uint64_t last_ns;
|
||||
uint64_t last_tsc;
|
||||
} gettime_local;
|
||||
|
||||
@@ -82,5 +82,6 @@ namespace CPUID
|
||||
bool has_pat();
|
||||
bool has_1gib_pages();
|
||||
bool has_invariant_tsc();
|
||||
uint64_t get_tsc_frequency();
|
||||
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace Kernel
|
||||
static void yield();
|
||||
static Scheduler& scheduler() { return *read_gs_sized<Scheduler*>(offsetof(Processor, m_scheduler)); }
|
||||
|
||||
static void initialize_tsc(uint8_t shift, uint64_t mult, uint64_t realtime_seconds);
|
||||
static void initialize_tsc(uint64_t realtime_seconds);
|
||||
static void update_tsc();
|
||||
static uint64_t ns_since_boot_tsc();
|
||||
|
||||
|
||||
@@ -30,6 +30,13 @@ namespace Kernel
|
||||
|
||||
class SystemTimer : public Timer
|
||||
{
|
||||
public:
|
||||
struct TSCInfo
|
||||
{
|
||||
int8_t shift;
|
||||
uint32_t mult;
|
||||
};
|
||||
|
||||
public:
|
||||
static void initialize();
|
||||
static SystemTimer& get();
|
||||
@@ -49,8 +56,10 @@ namespace Kernel
|
||||
|
||||
void dont_invoke_scheduler() { m_timer->m_should_invoke_scheduler = false; }
|
||||
|
||||
void update_tsc() const;
|
||||
uint64_t ns_since_boot_no_tsc() const;
|
||||
void update_tsc();
|
||||
TSCInfo tsc_info() const;
|
||||
|
||||
uint64_t ns_since_boot_no_tsc() const { return m_timer->ns_since_boot(); }
|
||||
|
||||
timespec real_time() const;
|
||||
|
||||
@@ -59,14 +68,29 @@ namespace Kernel
|
||||
|
||||
void initialize_timers();
|
||||
|
||||
uint64_t get_tsc_frequency() const;
|
||||
void initialize_invariant_tsc();
|
||||
|
||||
private:
|
||||
enum class TSCType
|
||||
{
|
||||
None,
|
||||
Invariant,
|
||||
};
|
||||
|
||||
uint64_t m_boot_time { 0 };
|
||||
BAN::UniqPtr<RTC> m_rtc;
|
||||
BAN::UniqPtr<Timer> m_timer;
|
||||
bool m_has_invariant_tsc { false };
|
||||
mutable uint32_t m_timer_ticks { 0 };
|
||||
|
||||
TSCType m_tsc_type = TSCType::None;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int8_t shift;
|
||||
uint32_t mult;
|
||||
} invariant;
|
||||
} m_tsc_info;
|
||||
|
||||
uint64_t m_tsc_update_ns { 0 };
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user