From feb39db90c5e9d7c8db472d726195462a03f5902 Mon Sep 17 00:00:00 2001 From: aglab2 Date: Thu, 7 Nov 2024 21:46:05 +0800 Subject: [PATCH] Core: Fixed race condition deadlock in Enhancements --- Source/Common/CriticalSection.h | 39 ++++++++++++++++ .../N64System/Enhancement/Enhancements.cpp | 45 ++++++++++--------- .../N64System/Enhancement/Enhancements.h | 6 ++- 3 files changed, 67 insertions(+), 23 deletions(-) diff --git a/Source/Common/CriticalSection.h b/Source/Common/CriticalSection.h index 0ca1fbbb4..3c2f1f63f 100644 --- a/Source/Common/CriticalSection.h +++ b/Source/Common/CriticalSection.h @@ -34,3 +34,42 @@ private: CGuard(const CGuard & copy); CGuard & operator=(const CGuard & rhs); }; + +class CUniqueLock +{ +public: + CUniqueLock(CriticalSection & sectionName) : + m_cs(sectionName), m_locked(true) + { + m_cs.enter(); + } + ~CUniqueLock() + { + if (m_locked) + m_cs.leave(); + } + + inline void lock() + { + if (!m_locked) + { + m_cs.enter(); + m_locked = true; + } + } + + inline void unlock() + { + if (m_locked) + { + m_cs.leave(); + m_locked = false; + } + } + +private: + CriticalSection & m_cs; + bool m_locked; + CUniqueLock(const CUniqueLock & copy); + CUniqueLock & operator=(const CUniqueLock & rhs); +}; diff --git a/Source/Project64-core/N64System/Enhancement/Enhancements.cpp b/Source/Project64-core/N64System/Enhancement/Enhancements.cpp index ad015b839..1e3f36723 100644 --- a/Source/Project64-core/N64System/Enhancement/Enhancements.cpp +++ b/Source/Project64-core/N64System/Enhancement/Enhancements.cpp @@ -32,7 +32,7 @@ CEnhancements::GAMESHARK_CODE::GAMESHARK_CODE(uint32_t Command, uint16_t Value, CEnhancements::CEnhancements() : m_ScanFileThread((CThread::CTHREAD_START_ROUTINE)stScanFileThread), m_Scan(true), - m_Scanned(false), + m_Scanned(true /*manual reset*/), m_UpdateCheats(false), m_OverClock(false), m_OverClockModifier(1) @@ -48,11 +48,11 @@ CEnhancements::~CEnhancements() void CEnhancements::ApplyActive(CMipsMemoryVM & MMU, CPlugins * Plugins, bool UpdateChanges) { - CGuard Guard(m_CS); + CUniqueLock Guard(m_CS); if (m_UpdateCheats && UpdateChanges) { m_UpdateCheats = false; - LoadActive(&MMU, Plugins); + LoadActiveImpl(Guard, &MMU, Plugins); } for (size_t i = 0, n = m_ActiveCodes.size(); i < n; i++) { @@ -263,20 +263,20 @@ void CEnhancements::LoadEnhancements(const char * Ident, SectionFiles & Files, s } } -void CEnhancements::Load(void) +void CEnhancements::LoadImpl(CUniqueLock & guard) { + guard.unlock(); WaitScanDone(); - CGuard Guard(m_CS); + guard.lock(); LoadEnhancements(CEnhancement::CheatIdent, m_CheatFiles, m_CheatFile, m_Cheats); LoadEnhancements(CEnhancement::EnhancementIdent, m_EnhancementFiles, m_EnhancementFile, m_Enhancements); } -void CEnhancements::LoadActive(CMipsMemoryVM * MMU, CPlugins * Plugins) +void CEnhancements::LoadActiveImpl(CUniqueLock & guard, CMipsMemoryVM * MMU, CPlugins * Plugins) { - Load(); + LoadImpl(guard); - CGuard Guard(m_CS); m_OverClock = false; m_OverClockModifier = 1; @@ -703,25 +703,14 @@ void CEnhancements::ScanFileThread(void) CGuard Guard(m_CS); m_CheatFiles = CheatFiles; m_EnhancementFiles = EnhancementFiles; - m_Scanned = true; } + + m_Scanned.Trigger(); } void CEnhancements::WaitScanDone() { - for (uint32_t i = 0; i < 500; i++) - { - bool Scanned = false; - { - CGuard Guard(m_CS); - Scanned = m_Scanned; - } - if (Scanned) - { - break; - } - pjutil::Sleep(100); - } + m_Scanned.IsTriggered(50 * 1000 /*ms*/); } uint32_t CEnhancements::ConvertXP64Address(uint32_t Address) @@ -739,3 +728,15 @@ uint16_t CEnhancements::ConvertXP64Value(uint16_t Value) tmpValue += ((Value + 0x002B) ^ 0x0085) & 0x00FF; return tmpValue; } + +void CEnhancements::Load(void) +{ + CUniqueLock Guard(m_CS); + return LoadImpl(Guard); +} + +void CEnhancements::LoadActive(CMipsMemoryVM * MMU, CPlugins * Plugins) +{ + CUniqueLock Guard(m_CS); + return LoadActiveImpl(Guard, MMU, Plugins); +} diff --git a/Source/Project64-core/N64System/Enhancement/Enhancements.h b/Source/Project64-core/N64System/Enhancement/Enhancements.h index f1e61f59f..b7a96f68e 100644 --- a/Source/Project64-core/N64System/Enhancement/Enhancements.h +++ b/Source/Project64-core/N64System/Enhancement/Enhancements.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include #include #include @@ -33,6 +34,9 @@ public: CEnhancementList Enhancements(void); private: + void LoadImpl(CUniqueLock &); + void LoadActiveImpl(CUniqueLock &, CMipsMemoryVM * MMU, CPlugins * Plugins); + class GAMESHARK_CODE { public: @@ -115,7 +119,7 @@ private: ORIGINAL_VALUES8 m_OriginalValues8; CThread m_ScanFileThread; bool m_Scan; - bool m_Scanned; + SyncEvent m_Scanned; bool m_UpdateCheats; bool m_OverClock; uint32_t m_OverClockModifier;