From 75f6325ee25c0ef28fbf3fb77bc71c3f72f8e26f Mon Sep 17 00:00:00 2001 From: J Reece Wilson Date: Mon, 5 Aug 2024 04:32:52 +0100 Subject: [PATCH] [*] Linux: fix spinning in an io_submit=EAGAIN loop --- Source/IO/FS/Async.Linux.cpp | 4 +++ Source/IO/UNIX/IOSubmit.Linux.cpp | 55 ++++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Source/IO/FS/Async.Linux.cpp b/Source/IO/FS/Async.Linux.cpp index 3c8c13d7..97d8c57d 100644 --- a/Source/IO/FS/Async.Linux.cpp +++ b/Source/IO/FS/Async.Linux.cpp @@ -609,6 +609,10 @@ namespace Aurora::IO::FS } else { + if (!this->pCompletionGroup_ && !this->loopSource_) + { + this->loopSource_ = AuMakeShared(AuSharedFromThis()); + } return AuStaticCast(AuStaticCast(this->loopSource_)); } } diff --git a/Source/IO/UNIX/IOSubmit.Linux.cpp b/Source/IO/UNIX/IOSubmit.Linux.cpp index 25a4a218..55c3b4b6 100644 --- a/Source/IO/UNIX/IOSubmit.Linux.cpp +++ b/Source/IO/UNIX/IOSubmit.Linux.cpp @@ -263,6 +263,14 @@ namespace Aurora::IO::UNIX // GLUE ////////////////////////////////////////////////////////////////// + static void HandleEAGAIN() + { + // DO NOT + LinuxOverlappedYield(); + // CHANGE! + sched_yield(); + } + static bool LinuxOverlappedTrySubmitWorkInternal(TLSIO *io) { int index {}; @@ -270,7 +278,16 @@ namespace Aurora::IO::UNIX while (index != startingLength) { - int ret = io_submit(io->context, io->submitPendingArray.size() - index, io->submitPendingArray.data() + index); + int ret; + do + { + ret = io_submit(io->context, io->submitPendingArray.size() - index, io->submitPendingArray.data() + index); + if (ret == -EAGAIN) + { + HandleEAGAIN(); + } + } + while (ret == -EAGAIN); if (ret <= 0) { @@ -377,6 +394,7 @@ namespace Aurora::IO::UNIX context->abortContext = io->context; iocb &submit = context->GetIOCB(); + AuMemset(&submit, 0, sizeof(submit)); submit.aio_data = context->GetData(); submit.aio_lio_opcode = op; submit.aio_reqprio = 0; @@ -694,6 +712,7 @@ namespace Aurora::IO::UNIX // evil nested epoll garbage // but i'm sure the kevent way would be more inefficient iocb pollSubmit {}; + AuMemset(&pollSubmit, 0, sizeof(pollSubmit)); pollSubmit.aio_fildes = epfd; pollSubmit.aio_lio_opcode = IOCB_CMD_POLL; pollSubmit.aio_buf = POLLIN; @@ -701,9 +720,21 @@ namespace Aurora::IO::UNIX iocb * ptr = &pollSubmit; iocb ** ptrArray = &ptr; - if (io_submit(io->context, 1, ptrArray) <= 0) + errno = 0; + + int error; + do + { + error = io_submit(io->context, 1, ptrArray); + if (error == -EAGAIN) + { + HandleEAGAIN(); + } + } + while (error == -EAGAIN); + + if (error <= 0) { - errno = EFAULT; SysPushErrorIO(); return -1; } @@ -797,7 +828,7 @@ namespace Aurora::IO::UNIX io_event finalEpollEvent {}; if (!bEpollTriggered) { - if (io_cancel(io->context, ptr, &finalEpollEvent) != 0) + if (io_cancel(io->context, &pollSubmit, &finalEpollEvent) != 0) { if (errno != EINPROGRESS) { @@ -864,6 +895,9 @@ namespace Aurora::IO::UNIX iocb submit {}; iocb readSubmit {}; iocb writeSubmit {}; + AuMemset(&readSubmit, 0, sizeof(readSubmit)); + AuMemset(&writeSubmit, 0, sizeof(readSubmit)); + AuMemset(&submit, 0, sizeof(submit)); submit.aio_lio_opcode = IOCB_CMD_POLL; iocb * ptrArray[2]; @@ -887,7 +921,18 @@ namespace Aurora::IO::UNIX ptrArray[iocbIdx++] = &writeSubmit; } - if (io_submit(io->context, iocbIdx, ptrArray) <= 0) + int error; + do + { + error = io_submit(io->context, iocbIdx, ptrArray); + if (error == -EAGAIN) + { + HandleEAGAIN(); + } + } + while (error == -EAGAIN); + + if (error <= 0) { errno = EFAULT; SysPushErrorIO();