From 807ea52b02aa761c4e864d4850956c2c90cf346b Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Thu, 6 Aug 2026 17:34:25 +1000 Subject: [PATCH] [idd] scheduler: reject isolated work timing stalls --- idd/LGIdd/CFrameScheduler.cpp | 34 +++++++++++++++++++++++++++++++--- idd/LGIdd/CFrameScheduler.h | 16 ++++++++++------ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/idd/LGIdd/CFrameScheduler.cpp b/idd/LGIdd/CFrameScheduler.cpp index 4eefa867..3e20db3a 100644 --- a/idd/LGIdd/CFrameScheduler.cpp +++ b/idd/LGIdd/CFrameScheduler.cpp @@ -260,6 +260,9 @@ void CFrameScheduler::Reset() m_lastArrival = 0; m_guestPeriod = 0; m_workEstimate = 0; + memset(m_workTiming, 0, sizeof(m_workTiming)); + m_workTimingCount = 0; + m_workTimingIndex = 0; m_nextDeadline = 0; m_deadlineSerial = 0; m_pendingCorrection = 0; @@ -1017,10 +1020,35 @@ void CFrameScheduler::TryRecordFrameTiming(uint64_t duration) if (!TryAcquireSRWLockExclusive(&m_lock)) return; - if (!m_workEstimate || duration > m_workEstimate) - m_workEstimate = duration; + m_workTiming[m_workTimingIndex] = duration; + m_workTimingIndex = + (m_workTimingIndex + 1) % WORK_TIMING_HISTORY_SIZE; + if (m_workTimingCount < WORK_TIMING_HISTORY_SIZE) + ++m_workTimingCount; + + uint64_t sorted[WORK_TIMING_HISTORY_SIZE]; + memcpy(sorted, m_workTiming, + m_workTimingCount * sizeof(*sorted)); + for (unsigned i = 1; i < m_workTimingCount; ++i) + { + const uint64_t sample = sorted[i]; + unsigned j = i; + while (j && sorted[j - 1] > sample) + { + sorted[j] = sorted[j - 1]; + --j; + } + sorted[j] = sample; + } + + if (m_workTimingCount == 1) + m_workEstimate = sorted[0]; else - m_workEstimate = (m_workEstimate * 31 + duration) / 32; + { + const unsigned discarded = min(m_workTimingCount - 1, + max(1U, m_workTimingCount / 10)); + m_workEstimate = sorted[m_workTimingCount - discarded - 1]; + } ReleaseSRWLockExclusive(&m_lock); } diff --git a/idd/LGIdd/CFrameScheduler.h b/idd/LGIdd/CFrameScheduler.h index 3c685531..b3cde9c6 100644 --- a/idd/LGIdd/CFrameScheduler.h +++ b/idd/LGIdd/CFrameScheduler.h @@ -80,6 +80,7 @@ private: }; static const unsigned PUBLICATION_HISTORY_SIZE = 128; + static const unsigned WORK_TIMING_HISTORY_SIZE = 32; mutable SRWLOCK m_lock = SRWLOCK_INIT; HANDLE m_wakeEvent = nullptr; @@ -94,12 +95,15 @@ private: uint64_t m_republishRequestTicket = 0; uint64_t m_republishAckTicket = 0; - uint64_t m_lastArrival = 0; - uint64_t m_guestPeriod = 0; - uint64_t m_workEstimate = 0; - uint64_t m_nextDeadline = 0; - uint32_t m_deadlineSerial = 0; - int64_t m_pendingCorrection = 0; + uint64_t m_lastArrival = 0; + uint64_t m_guestPeriod = 0; + uint64_t m_workEstimate = 0; + uint64_t m_workTiming[WORK_TIMING_HISTORY_SIZE] = {}; + unsigned m_workTimingCount = 0; + unsigned m_workTimingIndex = 0; + uint64_t m_nextDeadline = 0; + uint32_t m_deadlineSerial = 0; + int64_t m_pendingCorrection = 0; Publication m_publications[PUBLICATION_HISTORY_SIZE] = {}; unsigned m_publicationIndex = 0;