From e3cb700cf73deb25b8cb8d428f51e526f2fee58d Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Fri, 16 Jan 2026 11:13:49 -0800 Subject: [PATCH] Review --- .../LinuxSyscalls/ThreadManager.h | 2 +- .../LinuxSyscalls/x32/IoctlEmulation.cpp | 136 +++++++++++------- .../LinuxSyscalls/x32/IoctlEmulation.h | 49 +------ 3 files changed, 95 insertions(+), 92 deletions(-) diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h index 603537aed..b55763c74 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/ThreadManager.h @@ -128,7 +128,7 @@ struct ThreadStateObject : public FEXCore::Allocator::FEXAllocOperators { FEXCore::Core::CPUState::gdt_segment* ldt_entries {}; // 32-bit FD cache for DRM handlers. - fextl::unique_ptr DRMLRUCache {}; + fextl::unique_ptr DRMLRUCache {}; }; class ThreadManager final { diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/IoctlEmulation.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/IoctlEmulation.cpp index ac015ef74..4b9e7822e 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/IoctlEmulation.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/IoctlEmulation.cpp @@ -280,52 +280,10 @@ namespace DRM { uint32_t AddAndRunHandler(FEXCore::Core::CpuStateFrame* Frame, int fd, uint32_t cmd, uint32_t args); void AssignDeviceTypeToFD(FEXCore::Core::CpuStateFrame* Frame, int fd, const drm_version& Version); - class LRUCacheFDCacheImpl final : public LRUCacheFDCache { - public: - LRUCacheFDCacheImpl() { - // Set the last element to our handler - // This element will always be the last one - LRUCache[LRUSize] = LRUObject {-1, AddAndRunHandler}; - } - - uint32_t AddAndRunMapHandler(FEXCore::Core::CpuStateFrame* Frame, int fd, uint32_t cmd, uint32_t args) override { - // Couldn't find in cache, check map - { - auto it = FDToHandler.find(fd); - if (it != FDToHandler.end()) { - // Found, add to the cache - AddToFront(fd, it->second); - return it->second(Frame, fd, cmd, args); - } - } - - // Wasn't found in map, query it - drm_version Host_Version {}; - Host_Version.name = reinterpret_cast(alloca(128)); - Host_Version.name_len = 128; - uint64_t Result = ioctl(fd, DRM_IOCTL_VERSION, &Host_Version); - - // Add it to the map and double check that it was added - // Next time around when the ioctl is used then it will be added to cache - if (Result != -1) { - AssignDeviceTypeToFD(Frame, fd, Host_Version); - } - - auto it = FDToHandler.find(fd); - - if (it == FDToHandler.end()) { - // We don't understand this DRM ioctl - return -EPERM; - } - Result = it->second(Frame, fd, cmd, args); - SYSCALL_ERRNO(); - } - }; - - LRUCacheFDCache::HandlerType FindHandler(FEXCore::Core::CpuStateFrame* Frame, int32_t FD) { + DRMLRUCacheFDCache::HandlerType FindHandler(FEXCore::Core::CpuStateFrame* Frame, int32_t FD) { auto Thread = FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame); if (!Thread->DRMLRUCache) { - Thread->DRMLRUCache = fextl::make_unique(); + Thread->DRMLRUCache = fextl::make_unique(); } return Thread->DRMLRUCache->FindHandler(FD); } @@ -333,7 +291,7 @@ namespace DRM { uint32_t AddAndRunHandler(FEXCore::Core::CpuStateFrame* Frame, int fd, uint32_t cmd, uint32_t args) { auto Thread = FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame); if (!Thread->DRMLRUCache) { - Thread->DRMLRUCache = fextl::make_unique(); + Thread->DRMLRUCache = fextl::make_unique(); } return Thread->DRMLRUCache->AddAndRunMapHandler(Frame, fd, cmd, args); @@ -342,7 +300,7 @@ namespace DRM { void CheckAndAddFDDuplication(FEXCore::Core::CpuStateFrame* Frame, int fd, int NewFD) { auto Thread = FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame); if (!Thread->DRMLRUCache) { - Thread->DRMLRUCache = fextl::make_unique(); + Thread->DRMLRUCache = fextl::make_unique(); } Thread->DRMLRUCache->DuplicateFD(fd, NewFD); } @@ -781,7 +739,7 @@ namespace DRM { if (Version.name) { auto Thread = FEX::HLE::ThreadManager::GetStateObjectFromCPUState(Frame); if (!Thread->DRMLRUCache) { - Thread->DRMLRUCache = fextl::make_unique(); + Thread->DRMLRUCache = fextl::make_unique(); } const std::string_view Name(Version.name, Version.name_len); @@ -912,11 +870,91 @@ namespace DRM { } } // namespace DRM -std::array Handlers = []() consteval { +DRMLRUCacheFDCache::DRMLRUCacheFDCache() { + // Set the last element to our handler + // This element will always be the last one + LRUCache[LRUSize] = LRUObject {-1, DRM::AddAndRunHandler}; +} + +void DRMLRUCacheFDCache::SetFDHandler(uint32_t FD, HandlerType Handler) { + FDToHandler[FD] = Handler; +} + +void DRMLRUCacheFDCache::DuplicateFD(int fd, int NewFD) { + auto it = FDToHandler.find(fd); + if (it != FDToHandler.end()) { + FDToHandler[NewFD] = it->second; + } +} + +DRMLRUCacheFDCache::HandlerType DRMLRUCacheFDCache::FindHandler(int32_t FD) { + HandlerType Handler {}; + for (size_t i = 0; i < LRUSize; ++i) { + auto& it = LRUCache[i]; + if (it.FD == FD) { + if (i == 0) { + // If we are the first in the queue then just return it + return it.Handler; + } + Handler = it.Handler; + break; + } + } + + if (Handler) { + AddToFront(FD, Handler); + return Handler; + } + return LRUCache[LRUSize].Handler; +} + +void DRMLRUCacheFDCache::AddToFront(int32_t FD, HandlerType Handler) { + // Push the element to the front if we found one + // First copy all the other elements back one + // Ensuring the final element isn't written over + memmove(&LRUCache[1], &LRUCache[0], (LRUSize - 1) * sizeof(LRUCache[0])); + // Now set the first element to the one we just found + LRUCache[0] = LRUObject {FD, Handler}; +} + +uint32_t DRMLRUCacheFDCache::AddAndRunMapHandler(FEXCore::Core::CpuStateFrame* Frame, int fd, uint32_t cmd, uint32_t args) { + // Couldn't find in cache, check map + { + auto it = FDToHandler.find(fd); + if (it != FDToHandler.end()) { + // Found, add to the cache + AddToFront(fd, it->second); + return it->second(Frame, fd, cmd, args); + } + } + + // Wasn't found in map, query it + drm_version Host_Version {}; + Host_Version.name = reinterpret_cast(alloca(128)); + Host_Version.name_len = 128; + uint64_t Result = ioctl(fd, DRM_IOCTL_VERSION, &Host_Version); + + // Add it to the map and double check that it was added + // Next time around when the ioctl is used then it will be added to cache + if (Result != -1) { + DRM::AssignDeviceTypeToFD(Frame, fd, Host_Version); + } + + auto it = FDToHandler.find(fd); + + if (it == FDToHandler.end()) { + // We don't understand this DRM ioctl + return -EPERM; + } + Result = it->second(Frame, fd, cmd, args); + SYSCALL_ERRNO(); +} + +std::array Handlers = []() consteval { using namespace DRM; using namespace sockios; using namespace V4l2; - std::array Handlers {}; + std::array Handlers {}; ///< Default fill handlers with BasicHandler. for (auto& Handler : Handlers) { diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/IoctlEmulation.h b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/IoctlEmulation.h index 51e9628d2..ae7ff1134 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/IoctlEmulation.h +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/IoctlEmulation.h @@ -9,53 +9,18 @@ struct CpuStateFrame; } namespace FEX::HLE::x32 { -class LRUCacheFDCache { +class DRMLRUCacheFDCache final { public: using HandlerType = uint32_t (*)(FEXCore::Core::CpuStateFrame* Frame, int fd, uint32_t cmd, uint32_t args); - virtual ~LRUCacheFDCache() = default; - void SetFDHandler(uint32_t FD, HandlerType Handler) { - FDToHandler[FD] = Handler; - } + DRMLRUCacheFDCache(); + void SetFDHandler(uint32_t FD, HandlerType Handler); + void DuplicateFD(int fd, int NewFD); + HandlerType FindHandler(int32_t FD); + uint32_t AddAndRunMapHandler(FEXCore::Core::CpuStateFrame* Frame, int fd, uint32_t cmd, uint32_t args); - void DuplicateFD(int fd, int NewFD) { - auto it = FDToHandler.find(fd); - if (it != FDToHandler.end()) { - FDToHandler[NewFD] = it->second; - } - } - - HandlerType FindHandler(int32_t FD) { - HandlerType Handler {}; - for (size_t i = 0; i < LRUSize; ++i) { - auto& it = LRUCache[i]; - if (it.FD == FD) { - if (i == 0) { - // If we are the first in the queue then just return it - return it.Handler; - } - Handler = it.Handler; - break; - } - } - - if (Handler) { - AddToFront(FD, Handler); - return Handler; - } - return LRUCache[LRUSize].Handler; - } - - virtual uint32_t AddAndRunMapHandler(FEXCore::Core::CpuStateFrame* Frame, int fd, uint32_t cmd, uint32_t args) = 0; protected: constexpr static size_t LRUSize = 3; - void AddToFront(int32_t FD, HandlerType Handler) { - // Push the element to the front if we found one - // First copy all the other elements back one - // Ensuring the final element isn't written over - memmove(&LRUCache[1], &LRUCache[0], (LRUSize - 1) * sizeof(LRUCache[0])); - // Now set the first element to the one we just found - LRUCache[0] = LRUObject {FD, Handler}; - } + void AddToFront(int32_t FD, HandlerType Handler); struct LRUObject { int32_t FD;