From 2250bd58a29c9541ad3a5e91509832e1ab4e0c6e Mon Sep 17 00:00:00 2001 From: LC Date: Sat, 11 Jul 2026 13:23:16 -0400 Subject: [PATCH] x32/FD: Deduplicate guest and host fd set management Same behavior, but less copy pastey --- .../LinuxEmulation/LinuxSyscalls/x32/FD.cpp | 218 ++++-------------- 1 file changed, 44 insertions(+), 174 deletions(-) diff --git a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/FD.cpp b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/FD.cpp index b5122ef46..bd7dc2f23 100644 --- a/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/FD.cpp +++ b/Source/Tools/LinuxEmulation/LinuxSyscalls/x32/FD.cpp @@ -163,6 +163,32 @@ auto fcntl32Handler = [](FEXCore::Core::CpuStateFrame* Frame, int fd, int cmd, u return fcntlHandler(Frame, fd, cmd, arg); }; +// Helper for select implementations +static void SetHostFDSet(uint32_t nfds, uint32_t NumWords, const fd_set32* Guest, fd_set* Host) { + FaultSafeUserMemAccess::VerifyIsReadable(Guest, sizeof(fd_set32) * NumWords); + + for (uint32_t i = 0; i < NumWords; ++i) { + const uint32_t FD = Guest[i]; + const uint32_t Rem = nfds - (i * 32); + for (uint32_t j = 0; j < 32 && j < Rem; ++j) { + if ((FD >> j) & 1) { + FD_SET(i * 32 + j, Host); + } + } + } +} +static void SetGuestFDSet(uint32_t nfds, uint32_t NumWords, const fd_set& Host, fd_set32* Guest) { + FaultSafeUserMemAccess::VerifyIsWritable(Guest, sizeof(fd_set32) * NumWords); + + for (uint32_t i = 0; i < nfds; ++i) { + if (FD_ISSET(i, &Host)) { + Guest[i / 32] |= 1 << (i & 31); + } else { + Guest[i / 32] &= ~(1 << (i & 31)); + } + } +} + auto selectHandler = [](FEXCore::Core::CpuStateFrame* Frame, int nfds, fd_set32* readfds, fd_set32* writefds, fd_set32* exceptfds, struct timeval32* timeout) -> uint64_t { struct timeval tp64 {}; @@ -182,77 +208,25 @@ auto selectHandler = [](FEXCore::Core::CpuStateFrame* Frame, int nfds, fd_set32* const uint32_t NumWords = FEXCore::AlignUp(nfds, 32) / 32; if (readfds) { - FaultSafeUserMemAccess::VerifyIsReadable(readfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = readfds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_readfds); - } - } - } + SetHostFDSet(nfds, NumWords, readfds, &Host_readfds); } - if (writefds) { - FaultSafeUserMemAccess::VerifyIsReadable(writefds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = writefds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_writefds); - } - } - } + SetHostFDSet(nfds, NumWords, writefds, &Host_writefds); } - if (exceptfds) { - FaultSafeUserMemAccess::VerifyIsReadable(exceptfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = exceptfds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_exceptfds); - } - } - } + SetHostFDSet(nfds, NumWords, exceptfds, &Host_exceptfds); } uint64_t Result = ::select(nfds, readfds ? &Host_readfds : nullptr, writefds ? &Host_writefds : nullptr, exceptfds ? &Host_exceptfds : nullptr, timeout ? &tp64 : nullptr); if (readfds) { - FaultSafeUserMemAccess::VerifyIsWritable(readfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_readfds)) { - readfds[i / 32] |= 1 << (i & 31); - } else { - readfds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_readfds, readfds); } - if (writefds) { - FaultSafeUserMemAccess::VerifyIsWritable(writefds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_writefds)) { - writefds[i / 32] |= 1 << (i & 31); - } else { - writefds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_writefds, writefds); } - if (exceptfds) { - FaultSafeUserMemAccess::VerifyIsWritable(exceptfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_exceptfds)) { - exceptfds[i / 32] |= 1 << (i & 31); - } else { - exceptfds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_exceptfds, exceptfds); } if (timeout) { @@ -652,42 +626,13 @@ void RegisterFD(FEX::HLE::SyscallHandler* Handler) { const uint32_t NumWords = FEXCore::AlignUp(nfds, 32) / 32; if (readfds) { - FaultSafeUserMemAccess::VerifyIsReadable(readfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = readfds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_readfds); - } - } - } + SetHostFDSet(nfds, NumWords, readfds, &Host_readfds); } - if (writefds) { - FaultSafeUserMemAccess::VerifyIsReadable(writefds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = writefds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_writefds); - } - } - } + SetHostFDSet(nfds, NumWords, writefds, &Host_writefds); } - if (exceptfds) { - FaultSafeUserMemAccess::VerifyIsReadable(exceptfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = exceptfds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_exceptfds); - } - } - } + SetHostFDSet(nfds, NumWords, exceptfds, &Host_exceptfds); } FaultSafeUserMemAccess::VerifyIsReadableOrNull(sigmaskpack, sizeof(*sigmaskpack)); @@ -706,36 +651,13 @@ void RegisterFD(FEX::HLE::SyscallHandler* Handler) { exceptfds ? &Host_exceptfds : nullptr, timeout ? &tp64 : nullptr, &HostSet); if (readfds) { - FaultSafeUserMemAccess::VerifyIsWritable(readfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_readfds)) { - readfds[i / 32] |= 1 << (i & 31); - } else { - readfds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_readfds, readfds); } - if (writefds) { - FaultSafeUserMemAccess::VerifyIsWritable(writefds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_writefds)) { - writefds[i / 32] |= 1 << (i & 31); - } else { - writefds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_writefds, writefds); } - if (exceptfds) { - FaultSafeUserMemAccess::VerifyIsWritable(exceptfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_exceptfds)) { - exceptfds[i / 32] |= 1 << (i & 31); - } else { - exceptfds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_exceptfds, exceptfds); } if (timeout) { @@ -820,42 +742,13 @@ void RegisterFD(FEX::HLE::SyscallHandler* Handler) { const uint32_t NumWords = FEXCore::AlignUp(nfds, 32) / 32; if (readfds) { - FaultSafeUserMemAccess::VerifyIsReadable(readfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = readfds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_readfds); - } - } - } + SetHostFDSet(nfds, NumWords, readfds, &Host_readfds); } - if (writefds) { - FaultSafeUserMemAccess::VerifyIsReadable(writefds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = writefds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_writefds); - } - } - } + SetHostFDSet(nfds, NumWords, writefds, &Host_writefds); } - if (exceptfds) { - FaultSafeUserMemAccess::VerifyIsReadable(exceptfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < NumWords; ++i) { - uint32_t FD = exceptfds[i]; - int32_t Rem = nfds - (i * 32); - for (int j = 0; j < 32 && j < Rem; ++j) { - if ((FD >> j) & 1) { - FD_SET(i * 32 + j, &Host_exceptfds); - } - } - } + SetHostFDSet(nfds, NumWords, exceptfds, &Host_exceptfds); } FaultSafeUserMemAccess::VerifyIsReadableOrNull(sigmaskpack, sizeof(*sigmaskpack)); @@ -874,36 +767,13 @@ void RegisterFD(FEX::HLE::SyscallHandler* Handler) { exceptfds ? &Host_exceptfds : nullptr, timeout, &HostSet); if (readfds) { - FaultSafeUserMemAccess::VerifyIsWritable(readfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_readfds)) { - readfds[i / 32] |= 1 << (i & 31); - } else { - readfds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_readfds, readfds); } - if (writefds) { - FaultSafeUserMemAccess::VerifyIsWritable(writefds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_writefds)) { - writefds[i / 32] |= 1 << (i & 31); - } else { - writefds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_writefds, writefds); } - if (exceptfds) { - FaultSafeUserMemAccess::VerifyIsWritable(exceptfds, sizeof(fd_set32) * NumWords); - for (int i = 0; i < nfds; ++i) { - if (FD_ISSET(i, &Host_exceptfds)) { - exceptfds[i / 32] |= 1 << (i & 31); - } else { - exceptfds[i / 32] &= ~(1 << (i & 31)); - } - } + SetGuestFDSet(nfds, NumWords, Host_exceptfds, exceptfds); } SYSCALL_ERRNO();