diff --git a/External/FEXCore/Source/Interface/Config/Config.json.in b/External/FEXCore/Source/Interface/Config/Config.json.in index 84f9ddcf0..a9f4c801e 100644 --- a/External/FEXCore/Source/Interface/Config/Config.json.in +++ b/External/FEXCore/Source/Interface/Config/Config.json.in @@ -260,6 +260,14 @@ "Highly likely to break any multithreaded application if disabled." ] }, + "TSOAutoMigration": { + "Type": "bool", + "Default": "true", + "Desc": [ + "Automatically enables TSO when shared memory is used.", + "Should work without issues in most cases." + ] + }, "X87ReducedPrecision": { "Type": "bool", "Default": "false", diff --git a/External/FEXCore/Source/Interface/Context/Context.h b/External/FEXCore/Source/Interface/Context/Context.h index 75917d4d6..56098d012 100644 --- a/External/FEXCore/Source/Interface/Context/Context.h +++ b/External/FEXCore/Source/Interface/Context/Context.h @@ -86,6 +86,7 @@ namespace FEXCore::Context { FEX_CONFIG_OPT(GdbServer, GDBSERVER); FEX_CONFIG_OPT(Is64BitMode, IS64BIT_MODE); FEX_CONFIG_OPT(TSOEnabled, TSOENABLED); + FEX_CONFIG_OPT(TSOAutoMigration, TSOAUTOMIGRATION); FEX_CONFIG_OPT(ABILocalFlags, ABILOCALFLAGS); FEX_CONFIG_OPT(ABINoPF, ABINOPF); FEX_CONFIG_OPT(AOTIRCapture, AOTIRCAPTURE); @@ -297,6 +298,10 @@ namespace FEXCore::Context { FEXCore::Utils::PooledAllocatorMMap OpDispatcherAllocator; FEXCore::Utils::PooledAllocatorMMap FrontendAllocator; + void MarkMemoryShared(); + + bool IsTSOEnabled() { return (IsMemoryShared || !Config.TSOAutoMigration) && Config.TSOEnabled; } + protected: void ClearCodeCache(FEXCore::Core::InternalThreadState *Thread, bool AlsoClearIRCache); @@ -335,6 +340,7 @@ namespace FEXCore::Context { std::unique_ptr CodeObjectCacheService; bool StartPaused = false; + bool IsMemoryShared = false; FEX_CONFIG_OPT(AppFilename, APP_FILENAME); }; diff --git a/External/FEXCore/Source/Interface/Core/Core.cpp b/External/FEXCore/Source/Interface/Core/Core.cpp index 98f272099..eff1f1cfe 100644 --- a/External/FEXCore/Source/Interface/Core/Core.cpp +++ b/External/FEXCore/Source/Interface/Core/Core.cpp @@ -1140,6 +1140,32 @@ namespace FEXCore::Context { } } + void Context::MarkMemoryShared() { + if (!IsMemoryShared) { + IsMemoryShared = true; + + if (Config.TSOAutoMigration) { + LogMan::Msg::IFmt("Migrating to shared memory mode"); + + std::lock_guard lkThreads(ThreadCreationMutex); + LogMan::Throw::AFmt(Threads.size() == 1, "First MarkMemoryShared called must be before creating any threads"); + + auto Thread = Threads[0]; + + // Only the lookup cache is cleared here, so that old code can keep running until next compilation + std::lock_guard lkLookupCache(Thread->LookupCache->WriteLock); + Thread->LookupCache->ClearCache(); + + // IR also needs to be re-generated + Thread->LocalIRCache.clear(); + } + } + } + + void MarkMemoryShared(FEXCore::Context::Context *CTX) { + CTX->MarkMemoryShared(); + } + void Context::RemoveThreadCodeEntry(FEXCore::Core::InternalThreadState *Thread, uint64_t GuestRIP) { std::lock_guard lk(Thread->LookupCache->WriteLock); diff --git a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h index aa59f04f6..20c8bc49b 100644 --- a/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h +++ b/External/FEXCore/Source/Interface/Core/OpcodeDispatcher.h @@ -1236,14 +1236,14 @@ private: uint64_t Entry; OrderedNode* _StoreMemAutoTSO(FEXCore::IR::RegisterClassType Class, uint8_t Size, OrderedNode *Addr, OrderedNode *Value, uint8_t Align = 1) { - if (CTX->Config.TSOEnabled) + if (CTX->IsTSOEnabled()) return _StoreMemTSO(Class, Size, Value, Addr, Invalid(), Align, MEM_OFFSET_SXTX, 1); else return _StoreMem(Class, Size, Value, Addr, Invalid(), Align, MEM_OFFSET_SXTX, 1); } OrderedNode* _LoadMemAutoTSO(FEXCore::IR::RegisterClassType Class, uint8_t Size, OrderedNode *ssa0, uint8_t Align = 1) { - if (CTX->Config.TSOEnabled) + if (CTX->IsTSOEnabled()) return _LoadMemTSO(Class, Size, ssa0, Invalid(), Align, MEM_OFFSET_SXTX, 1); else return _LoadMem(Class, Size, ssa0, Invalid(), Align, MEM_OFFSET_SXTX, 1); diff --git a/External/FEXCore/include/FEXCore/Core/Context.h b/External/FEXCore/include/FEXCore/Core/Context.h index 8fdb63d9d..14550675f 100644 --- a/External/FEXCore/include/FEXCore/Core/Context.h +++ b/External/FEXCore/include/FEXCore/Core/Context.h @@ -250,6 +250,7 @@ namespace FEXCore::Context { FEX_DEFAULT_VISIBILITY void FinalizeAOTIRCache(FEXCore::Context::Context *CTX); FEX_DEFAULT_VISIBILITY void WriteFilesWithCode(FEXCore::Context::Context *CTX, std::function Writer); FEX_DEFAULT_VISIBILITY void InvalidateGuestCodeRange(FEXCore::Context::Context *CTX, uint64_t Start, uint64_t Length); + FEX_DEFAULT_VISIBILITY void MarkMemoryShared(FEXCore::Context::Context *CTX); FEX_DEFAULT_VISIBILITY void ConfigureAOTGen(FEXCore::Core::InternalThreadState *Thread, std::set *ExternalBranches, uint64_t SectionMaxAddress); } diff --git a/Source/Tests/LinuxSyscalls/Syscalls.cpp b/Source/Tests/LinuxSyscalls/Syscalls.cpp index f08d19c81..d6bcb6ab6 100644 --- a/Source/Tests/LinuxSyscalls/Syscalls.cpp +++ b/Source/Tests/LinuxSyscalls/Syscalls.cpp @@ -438,6 +438,10 @@ uint64_t CloneHandler(FEXCore::Core::CpuStateFrame *Frame, FEX::HLE::clone3_args return false; }; + if (flags & CLONE_VM) { + MarkMemoryShared(Frame->Thread->CTX); + } + // If there are flags that can't be handled regularly then we need to hand off to the true clone handler if (HasUnhandledFlags(args)) { if (!AnyFlagsSet(flags, CLONE_THREAD)) { diff --git a/Source/Tests/LinuxSyscalls/SyscallsSMCTracking.cpp b/Source/Tests/LinuxSyscalls/SyscallsSMCTracking.cpp index 31a409c40..31c1b5965 100644 --- a/Source/Tests/LinuxSyscalls/SyscallsSMCTracking.cpp +++ b/Source/Tests/LinuxSyscalls/SyscallsSMCTracking.cpp @@ -189,6 +189,10 @@ static std::string get_fdpath(int fd) { void SyscallHandler::TrackMmap(uintptr_t Base, uintptr_t Size, int Prot, int Flags, int fd, off_t Offset) { Size = FEXCore::AlignUp(Size, FHU::FEX_PAGE_SIZE); + if (Flags & MAP_SHARED) { + MarkMemoryShared(CTX); + } + { FHU::ScopedSignalMaskWithUniqueLock lk(_SyscallHandler->VMATracking.Mutex); @@ -311,6 +315,8 @@ void SyscallHandler::TrackMremap(uintptr_t OldAddress, size_t OldSize, size_t Ne } void SyscallHandler::TrackShmat(int shmid, uintptr_t Base, int shmflg) { + MarkMemoryShared(CTX); + shmid_ds stat; auto res = shmctl(shmid, IPC_STAT, &stat);