From 1d2d5753b94b4f6f67044cb6860a2b8d03b2b4b8 Mon Sep 17 00:00:00 2001 From: J Reece Wilson Date: Tue, 6 Aug 2024 03:22:00 +0100 Subject: [PATCH] [*] Linux: possible regressions in 57c55151733bd3876a9655dce84984163b72be2d. Fixes read while transaction is signaled loops --- Source/IO/FS/Async.Linux.cpp | 2 +- Source/IO/UNIX/IOSubmit.Linux.cpp | 86 ++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/Source/IO/FS/Async.Linux.cpp b/Source/IO/FS/Async.Linux.cpp index 97d8c57d..d1e8bbeb 100644 --- a/Source/IO/FS/Async.Linux.cpp +++ b/Source/IO/FS/Async.Linux.cpp @@ -84,7 +84,7 @@ namespace Aurora::IO::FS auto lock = caller_.lock(); return lock->Complete(); } - + return false; } diff --git a/Source/IO/UNIX/IOSubmit.Linux.cpp b/Source/IO/UNIX/IOSubmit.Linux.cpp index bb7b38f8..10f1eb58 100644 --- a/Source/IO/UNIX/IOSubmit.Linux.cpp +++ b/Source/IO/UNIX/IOSubmit.Linux.cpp @@ -645,7 +645,8 @@ namespace Aurora::IO::UNIX (void)LinuxOverlappedTrySubmitWork(); } - } while (timeout || AuExchange(bAgain, false)); + } + while (timeout || AuExchange(bAgain, false)); return dwApcsSent; } @@ -661,6 +662,8 @@ namespace Aurora::IO::UNIX { bool bRet { true }; timespec targetTime; + int iRedoCount {}; + auto io = GetTls(); if (!io) { @@ -698,9 +701,18 @@ namespace Aurora::IO::UNIX iocb * ptr = &pollSubmit; iocb ** ptrArray = &ptr; - errno = 0; - + bool bEpollTriggered {}; + io_event ioEvents[1024]; + AuTuple toProcess[1024] {}; + int toProcessDone {}; + int temp {}; + bool bAgain {}; int error; + + redo: + toProcessDone = 0; + bEpollTriggered = false; + do { error = io_submit(io->context, 1, ptrArray); @@ -715,18 +727,11 @@ namespace Aurora::IO::UNIX { SysPushErrorIO(); return -1; - } - - bool bEpollTriggered {}; - io_event ioEvents[1024]; - AuTuple toProcess[1024] {}; - int toProcessDone {}; - int temp {}; - bool bAgain {}; + }; do { - if (timeout) + if (timeout && !bAgain) { AuUInt64 uTimeNow = AuTime::SteadyClockNS(); if (uTargetTime <= uTimeNow) @@ -800,16 +805,12 @@ namespace Aurora::IO::UNIX SysPanic("io_getevents() is not implemented on this architecture."); } } - - bAgain = AuExchange(io->bPollHit, false); - - if (bAgain) - { - (void)LinuxOverlappedTrySubmitWork(); - } - } while ((timeout ? !bEpollTriggered : false) || AuExchange(bAgain, false)); + } + while ((timeout ? !bEpollTriggered : false)); exit: + bAgain = false; + io_event finalEpollEvent {}; if (!bEpollTriggered) { @@ -838,6 +839,15 @@ namespace Aurora::IO::UNIX handle->LIOS_SendProcess(bytesTransacted, bError, errNo); } + if ((io->submitPendingArray.size() || (bAgain = AuExchange(io->bPollHit, false)))) + { + LinuxOverlappedTrySubmitWorkInternal(io); + if (bAgain && (iRedoCount++) < 4) + { + goto redo; + } + } + if (bEpollTriggered) { return epoll_wait(epfd, events, maxevents, 0); @@ -855,7 +865,17 @@ namespace Aurora::IO::UNIX bool LinuxOverlappedWaitForOne(AuUInt32 timeout, AuUInt read, AuUInt write, bool &bReadTriggered, bool &bWriteTriggered) { timespec targetTime; + iocb submit {}; + iocb readSubmit {}; + iocb writeSubmit {}; bool bRet { true }; + int iRedoCount {}; + io_event ioEvents[1024]; + AuTuple toProcess[1024] {}; + int toProcessDone {}; + int temp; + bool bTryAgain {}; + auto io = GetTls(); bWriteTriggered = false; @@ -886,9 +906,6 @@ namespace Aurora::IO::UNIX return false; } - iocb submit {}; - iocb readSubmit {}; - iocb writeSubmit {}; AuMemset(&readSubmit, 0, sizeof(readSubmit)); AuMemset(&writeSubmit, 0, sizeof(readSubmit)); AuMemset(&submit, 0, sizeof(submit)); @@ -915,6 +932,8 @@ namespace Aurora::IO::UNIX ptrArray[iocbIdx++] = &writeSubmit; } + redo: + toProcessDone = 0; int error; do { @@ -933,14 +952,9 @@ namespace Aurora::IO::UNIX return -1; } - io_event ioEvents[1024]; - AuTuple toProcess[1024] {}; - int toProcessDone {}; - int temp; - do { - if (timeout) + if (timeout && !bTryAgain) { AuUInt64 uTimeNow = AuTime::SteadyClockNS(); if (uTargetTime <= uTimeNow) @@ -1025,9 +1039,12 @@ namespace Aurora::IO::UNIX } } - } while (timeout ? (!bReadTriggered && !bWriteTriggered) : false); + } + while (timeout ? (!bReadTriggered && !bWriteTriggered) : false); exit: + bTryAgain = false; + for (int i = 0; i < iocbIdx; i++) { io_event finalEpollEvent {}; @@ -1071,6 +1088,15 @@ namespace Aurora::IO::UNIX handle->LIOS_SendProcess(bytesTransacted, bError, errNo); } + if ((io->submitPendingArray.size() || (bTryAgain = AuExchange(io->bPollHit, false)))) + { + LinuxOverlappedTrySubmitWorkInternal(io); + if (bTryAgain && (iRedoCount++) < 4) + { + goto redo; + } + } + return bRet; }