This commit is contained in:
Ryan Houdek committed 2026-01-26 12:39:00 -08:00
1 parent 82b1763431
commit e3cb700cf7
3 files changed
+95 -92

No files matched your search

@@ -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<x32::LRUCacheFDCache> DRMLRUCache {};
fextl::unique_ptr<x32::DRMLRUCacheFDCache> DRMLRUCache {};
};
class ThreadManager final {
@@ -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<char*>(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<LRUCacheFDCacheImpl>();
Thread->DRMLRUCache = fextl::make_unique<DRMLRUCacheFDCache>();
}
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<LRUCacheFDCacheImpl>();
Thread->DRMLRUCache = fextl::make_unique<DRMLRUCacheFDCache>();
}
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<LRUCacheFDCacheImpl>();
Thread->DRMLRUCache = fextl::make_unique<DRMLRUCacheFDCache>();
}
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<LRUCacheFDCacheImpl>();
Thread->DRMLRUCache = fextl::make_unique<DRMLRUCacheFDCache>();
}
const std::string_view Name(Version.name, Version.name_len);
@@ -912,11 +870,91 @@ namespace DRM {
}
} // namespace DRM
std::array<LRUCacheFDCache::HandlerType, 1U << _IOC_TYPEBITS> 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<char*>(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<DRMLRUCacheFDCache::HandlerType, 1U << _IOC_TYPEBITS> Handlers = []() consteval {
using namespace DRM;
using namespace sockios;
using namespace V4l2;
std::array<LRUCacheFDCache::HandlerType, 1U << _IOC_TYPEBITS> Handlers {};
std::array<DRMLRUCacheFDCache::HandlerType, 1U << _IOC_TYPEBITS> Handlers {};
///< Default fill handlers with BasicHandler.
for (auto& Handler : Handlers) {
@@ -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;