diff --git a/FEXCore/Source/Interface/Core/LookupCache.cpp b/FEXCore/Source/Interface/Core/LookupCache.cpp index 1c52a93b5..7aae65d7e 100644 --- a/FEXCore/Source/Interface/Core/LookupCache.cpp +++ b/FEXCore/Source/Interface/Core/LookupCache.cpp @@ -76,7 +76,7 @@ LookupCache::~LookupCache() { // These will get freed when their memory allocators are deallocated. } -void LookupCache::ClearL2Cache(const FEXCore::LookupCacheWriteLockToken& lk) { +void LookupCache::ClearL2Cache(const FEXCore::LookupCacheReadLockToken& lk) { // Clear out the page memory // PagePointer and PageMemory are sequential with each other. Clear both at once. FEXCore::Allocator::VirtualDontNeed(reinterpret_cast(PagePointer), diff --git a/FEXCore/Source/Interface/Core/LookupCache.h b/FEXCore/Source/Interface/Core/LookupCache.h index cdfea603c..c0e2b4e39 100644 --- a/FEXCore/Source/Interface/Core/LookupCache.h +++ b/FEXCore/Source/Interface/Core/LookupCache.h @@ -3,6 +3,8 @@ #include "Interface/Context/Context.h" #include #include +#include "Utils/WritePriorityMutex.h" + #include #include #include @@ -15,22 +17,35 @@ #include namespace FEXCore { - struct LookupCacheWriteLockToken { private: // Only constructible by GuestToHostMap friend struct GuestToHostMap; - LookupCacheWriteLockToken(std::mutex& Mutex) + LookupCacheWriteLockToken(FEXCore::Utils::WritePriorityMutex::Mutex& Mutex) : Lock {Mutex} {} - std::lock_guard Lock; + std::lock_guard Lock; +}; + +struct LookupCacheReadLockToken { +private: + // Only constructible by GuestToHostMap + friend struct GuestToHostMap; + LookupCacheReadLockToken(FEXCore::Utils::WritePriorityMutex::Mutex& Mutex) + : Lock {Mutex} {} + std::shared_lock Lock; }; struct GuestToHostMap { - std::mutex WriteLock; + FEXCore::Utils::WritePriorityMutex::Mutex Lock {}; [[nodiscard]] LookupCacheWriteLockToken AcquireWriteLock() { - return LookupCacheWriteLockToken {WriteLock}; + return LookupCacheWriteLockToken {Lock}; + } + + [[nodiscard]] + LookupCacheReadLockToken AcquireReadLock() { + return LookupCacheReadLockToken {Lock}; } struct BlockLinkTag { @@ -75,7 +90,7 @@ struct GuestToHostMap { BlockList[Address] = (uintptr_t)HostCode; } - std::optional FindBlock(uint64_t Address, const LookupCacheWriteLockToken&) { + std::optional FindBlock(uint64_t Address, const LookupCacheReadLockToken&) { auto HostCode = BlockList.find(Address); if (HostCode == BlockList.end()) { return std::nullopt; @@ -144,7 +159,7 @@ public: { std::optional> LockTime( Thread->ThreadStats ? &Thread->ThreadStats->AccumulatedCacheReadLockTime : nullptr); - auto lk = Shared->AcquireWriteLock(); + auto lk = Shared->AcquireReadLock(); LockTime.reset(); if (!DisableL2Cache()) { @@ -302,7 +317,7 @@ public: } void ClearCache(const LookupCacheWriteLockToken&); - void ClearL2Cache(const LookupCacheWriteLockToken&); + void ClearL2Cache(const LookupCacheReadLockToken&); void ClearThreadLocalCaches(const LookupCacheWriteLockToken&); uintptr_t GetL1Pointer() const { @@ -330,7 +345,7 @@ public: } private: - void CacheBlockMapping(uint64_t Address, uintptr_t HostCode, const LookupCacheWriteLockToken& lk) { + void CacheBlockMapping(uint64_t Address, uintptr_t HostCode, const LookupCacheReadLockToken& lk) { // Do L1 auto& L1Entry = reinterpret_cast(L1Pointer)[Address & L1PointerMask]; L1Entry.GuestCode = Address;