Account for partial milliseconds in KiClockIsr

This fixes the slowness in The lord of the rings: the third era
This commit is contained in:
ergo720 2023-03-20 13:27:26 +01:00 committed by RadWolfie
parent c7b028b3e7
commit 46d0173673
3 changed files with 13 additions and 7 deletions

View File

@ -102,7 +102,7 @@ static uint64_t pit_next(uint64_t now)
uint64_t next = pit_last + pit_period;
if (now >= next) {
xbox::KiClockIsr((now - pit_last - pit_period) / 1000);
xbox::KiClockIsr(now - pit_last);
pit_last = get_now();
return pit_period;
}
@ -151,7 +151,7 @@ static uint64_t get_next(uint64_t now)
xbox::void_xt NTAPI system_events(xbox::PVOID arg)
{
// Testing shows that, if this thread has the same priority of the other xbox threads, it can take tens, even hundreds of ms to complete a single loop.
// So we increase its priority to above normal, so that it completes a loop roughly every 3.1ms
// So we increase its priority to above normal, so that it scheduled more often
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
while (true) {

View File

@ -146,19 +146,25 @@ xbox::void_xt xbox::KiWaitListUnlock()
KiWaitListMtx.Mtx.unlock();
}
xbox::void_xt xbox::KiClockIsr(ulonglong_xt ExtraMs)
xbox::void_xt xbox::KiClockIsr(ulonglong_xt TotalUs)
{
KIRQL OldIrql;
LARGE_INTEGER InterruptTime, SystemTime;
ULONG Hand;
DWORD OldKeTickCount;
static uint64_t LostUs;
uint64_t TotalMs = TotalUs / 1000;
LostUs += (TotalUs - TotalMs * 1000);
uint64_t RecoveredMs = LostUs / 1000;
TotalMs += RecoveredMs;
LostUs -= (RecoveredMs * 1000);
OldIrql = KfRaiseIrql(CLOCK_LEVEL);
// Update the interrupt time
InterruptTime.u.LowPart = KeInterruptTime.LowPart;
InterruptTime.u.HighPart = KeInterruptTime.High1Time;
InterruptTime.QuadPart += (CLOCK_TIME_INCREMENT * (1 + ExtraMs));
InterruptTime.QuadPart += (CLOCK_TIME_INCREMENT * TotalMs);
KeInterruptTime.High2Time = InterruptTime.u.HighPart;
KeInterruptTime.LowPart = InterruptTime.u.LowPart;
KeInterruptTime.High1Time = InterruptTime.u.HighPart;
@ -178,7 +184,7 @@ xbox::void_xt xbox::KiClockIsr(ulonglong_xt ExtraMs)
else {
SystemTime.u.LowPart = KeSystemTime.LowPart;
SystemTime.u.HighPart = KeSystemTime.High1Time;
SystemTime.QuadPart += (CLOCK_TIME_INCREMENT * (1 + ExtraMs));
SystemTime.QuadPart += (CLOCK_TIME_INCREMENT * TotalMs);
KeSystemTime.High2Time = SystemTime.u.HighPart;
KeSystemTime.LowPart = SystemTime.u.LowPart;
KeSystemTime.High1Time = SystemTime.u.HighPart;
@ -186,7 +192,7 @@ xbox::void_xt xbox::KiClockIsr(ulonglong_xt ExtraMs)
// Update the tick counter
OldKeTickCount = KeTickCount;
KeTickCount += (1 + static_cast<dword_xt>(ExtraMs));
KeTickCount += (1 + static_cast<dword_xt>(TotalMs));
// Because this function must be fast to continuously update the kernel clocks, if somebody else is currently
// holding the lock, we won't wait and instead skip the check of the timers for this cycle

View File

@ -66,7 +66,7 @@ namespace xbox
void_xt KiWaitListUnlock();
void_xt KiClockIsr(ulonglong_xt ExtraMs);
void_xt KiClockIsr(ulonglong_xt TotalUs);
xbox::void_xt NTAPI KiCheckTimerTable
(