[*] Linux: fix spinning in an io_submit=EAGAIN loop
This commit is contained in:
parent
5947e6a2c3
commit
75f6325ee2
@ -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_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user