From fec61f89a3bce9bf857a15ed4789629624e66584 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Mon, 18 Jul 2022 11:48:20 -0700 Subject: [PATCH] Timer: protect usages of ms timers from rollover --- Source/Core/Common/Timer.cpp | 24 +++++---------------- Source/Core/Common/Timer.h | 1 - Source/Core/VideoCommon/HiresTextures.cpp | 6 +++--- Source/Core/VideoCommon/OnScreenDisplay.cpp | 16 +++++++------- 4 files changed, 16 insertions(+), 31 deletions(-) diff --git a/Source/Core/Common/Timer.cpp b/Source/Core/Common/Timer.cpp index 1b80e02880..fb81164390 100644 --- a/Source/Core/Common/Timer.cpp +++ b/Source/Core/Common/Timer.cpp @@ -48,8 +48,7 @@ void Timer::Start() void Timer::StartWithOffset(u64 offset) { Start(); - if (m_start_ms > offset) - m_start_ms -= offset; + m_start_ms -= offset; } void Timer::Stop() @@ -60,23 +59,10 @@ void Timer::Stop() u64 Timer::ElapsedMs() const { - // If we have not started yet, return zero - if (m_start_ms == 0) - return 0; - - if (m_running) - { - u64 now = NowMs(); - if (m_start_ms >= now) - return 0; - return now - m_start_ms; - } - else - { - if (m_start_ms >= m_end_ms) - return 0; - return m_end_ms - m_start_ms; - } + const u64 end = m_running ? NowMs() : m_end_ms; + // Can handle up to 1 rollover event (underflow produces correct result) + // If Start() has never been called, will return 0 + return end - m_start_ms; } u64 Timer::GetLocalTimeSinceJan1970() diff --git a/Source/Core/Common/Timer.h b/Source/Core/Common/Timer.h index cf194e773e..7298f4a368 100644 --- a/Source/Core/Common/Timer.h +++ b/Source/Core/Common/Timer.h @@ -18,7 +18,6 @@ public: // Effectively "resumes" a timer void StartWithOffset(u64 offset); void Stop(); - bool IsRunning() const { return m_running; } u64 ElapsedMs() const; // The rest of these functions probably belong somewhere else diff --git a/Source/Core/VideoCommon/HiresTextures.cpp b/Source/Core/VideoCommon/HiresTextures.cpp index 5b0104f9f3..f3d6d77373 100644 --- a/Source/Core/VideoCommon/HiresTextures.cpp +++ b/Source/Core/VideoCommon/HiresTextures.cpp @@ -159,7 +159,8 @@ void HiresTexture::Prefetch() const size_t max_mem = (sys_mem / 2 < recommended_min_mem) ? (sys_mem / 2) : (sys_mem - recommended_min_mem); - const u64 start_time = Common::Timer::NowMs(); + Common::Timer timer; + timer.Start(); for (const auto& entry : s_textureMap) { const std::string& base_filename = entry.first; @@ -207,9 +208,8 @@ void HiresTexture::Prefetch() } } - const u64 stop_time = Common::Timer::NowMs(); OSD::AddMessage(fmt::format("Custom Textures loaded, {:.1f} MB in {:.1f}s", - size_sum / (1024.0 * 1024.0), (stop_time - start_time) / 1000.0), + size_sum / (1024.0 * 1024.0), timer.ElapsedMs() / 1000.0), 10000); } diff --git a/Source/Core/VideoCommon/OnScreenDisplay.cpp b/Source/Core/VideoCommon/OnScreenDisplay.cpp index d2c211c861..e860c53ec0 100644 --- a/Source/Core/VideoCommon/OnScreenDisplay.cpp +++ b/Source/Core/VideoCommon/OnScreenDisplay.cpp @@ -32,12 +32,14 @@ static std::atomic s_obscured_pixels_top = 0; struct Message { Message() = default; - Message(std::string text_, u64 timestamp_, u32 duration_, u32 color_) - : text(std::move(text_)), timestamp(timestamp_), duration(duration_), color(color_) + Message(std::string text_, u32 duration_, u32 color_) + : text(std::move(text_)), duration(duration_), color(color_) { + timer.Start(); } + s64 TimeRemaining() const { return duration - timer.ElapsedMs(); } std::string text; - u64 timestamp = 0; + Common::Timer timer; u32 duration = 0; bool ever_drawn = false; u32 color = 0; @@ -93,20 +95,18 @@ void AddTypedMessage(MessageType type, std::string message, u32 ms, u32 argb) { std::lock_guard lock{s_messages_mutex}; s_messages.erase(type); - s_messages.emplace(type, Message(std::move(message), Common::Timer::NowMs() + ms, ms, argb)); + s_messages.emplace(type, Message(std::move(message), ms, argb)); } void AddMessage(std::string message, u32 ms, u32 argb) { std::lock_guard lock{s_messages_mutex}; - s_messages.emplace(MessageType::Typeless, - Message(std::move(message), Common::Timer::NowMs() + ms, ms, argb)); + s_messages.emplace(MessageType::Typeless, Message(std::move(message), ms, argb)); } void DrawMessages() { const bool draw_messages = Config::Get(Config::MAIN_OSD_MESSAGES); - const u64 now = Common::Timer::NowMs(); const float current_x = LEFT_MARGIN * ImGui::GetIO().DisplayFramebufferScale.x + s_obscured_pixels_left; float current_y = TOP_MARGIN * ImGui::GetIO().DisplayFramebufferScale.y + s_obscured_pixels_top; @@ -117,7 +117,7 @@ void DrawMessages() for (auto it = s_messages.begin(); it != s_messages.end();) { Message& msg = it->second; - const int time_left = static_cast(msg.timestamp - now); + const s64 time_left = msg.TimeRemaining(); // Make sure we draw them at least once if they were printed with 0ms, // unless enough time has expired, in that case, we drop them