[*] Linux: fix spinning in an io_submit=EAGAIN loop

This commit is contained in:
Reece Wilson 2024-08-05 04:32:52 +01:00
parent 5947e6a2c3
commit 75f6325ee2
2 changed files with 54 additions and 5 deletions

View File

@ -609,6 +609,10 @@ namespace Aurora::IO::FS
} }
else else
{ {
if (!this->pCompletionGroup_ && !this->loopSource_)
{
this->loopSource_ = AuMakeShared<LinuxAsyncFileTransactionLoopSource>(AuSharedFromThis());
}
return AuStaticCast<Loop::ILoopSource>(AuStaticCast<Loop::ILSEvent>(this->loopSource_)); return AuStaticCast<Loop::ILoopSource>(AuStaticCast<Loop::ILSEvent>(this->loopSource_));
} }
} }

View File

@ -263,6 +263,14 @@ namespace Aurora::IO::UNIX
// GLUE // GLUE
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
static void HandleEAGAIN()
{
// DO NOT
LinuxOverlappedYield();
// CHANGE!
sched_yield();
}
static bool LinuxOverlappedTrySubmitWorkInternal(TLSIO *io) static bool LinuxOverlappedTrySubmitWorkInternal(TLSIO *io)
{ {
int index {}; int index {};
@ -270,7 +278,16 @@ namespace Aurora::IO::UNIX
while (index != startingLength) 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) if (ret <= 0)
{ {
@ -377,6 +394,7 @@ namespace Aurora::IO::UNIX
context->abortContext = io->context; context->abortContext = io->context;
iocb &submit = context->GetIOCB(); iocb &submit = context->GetIOCB();
AuMemset(&submit, 0, sizeof(submit));
submit.aio_data = context->GetData(); submit.aio_data = context->GetData();
submit.aio_lio_opcode = op; submit.aio_lio_opcode = op;
submit.aio_reqprio = 0; submit.aio_reqprio = 0;
@ -694,6 +712,7 @@ namespace Aurora::IO::UNIX
// evil nested epoll garbage // evil nested epoll garbage
// but i'm sure the kevent way would be more inefficient // but i'm sure the kevent way would be more inefficient
iocb pollSubmit {}; iocb pollSubmit {};
AuMemset(&pollSubmit, 0, sizeof(pollSubmit));
pollSubmit.aio_fildes = epfd; pollSubmit.aio_fildes = epfd;
pollSubmit.aio_lio_opcode = IOCB_CMD_POLL; pollSubmit.aio_lio_opcode = IOCB_CMD_POLL;
pollSubmit.aio_buf = POLLIN; pollSubmit.aio_buf = POLLIN;
@ -701,9 +720,21 @@ namespace Aurora::IO::UNIX
iocb * ptr = &pollSubmit; iocb * ptr = &pollSubmit;
iocb ** ptrArray = &ptr; 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(); SysPushErrorIO();
return -1; return -1;
} }
@ -797,7 +828,7 @@ namespace Aurora::IO::UNIX
io_event finalEpollEvent {}; io_event finalEpollEvent {};
if (!bEpollTriggered) if (!bEpollTriggered)
{ {
if (io_cancel(io->context, ptr, &finalEpollEvent) != 0) if (io_cancel(io->context, &pollSubmit, &finalEpollEvent) != 0)
{ {
if (errno != EINPROGRESS) if (errno != EINPROGRESS)
{ {
@ -864,6 +895,9 @@ namespace Aurora::IO::UNIX
iocb submit {}; iocb submit {};
iocb readSubmit {}; iocb readSubmit {};
iocb writeSubmit {}; iocb writeSubmit {};
AuMemset(&readSubmit, 0, sizeof(readSubmit));
AuMemset(&writeSubmit, 0, sizeof(readSubmit));
AuMemset(&submit, 0, sizeof(submit));
submit.aio_lio_opcode = IOCB_CMD_POLL; submit.aio_lio_opcode = IOCB_CMD_POLL;
iocb * ptrArray[2]; iocb * ptrArray[2];
@ -887,7 +921,18 @@ namespace Aurora::IO::UNIX
ptrArray[iocbIdx++] = &writeSubmit; 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; errno = EFAULT;
SysPushErrorIO(); SysPushErrorIO();