[*] Preemptive GetOverlappedResult fast-paths under WaitMultiple2 that rely on the alertable yield under next read/write cannot be trusted if the read count is zero.

Direct IO-specific quirk?
Windows 7 specific quirk?
Direct IO under Win7 specific quirk?
idk, but this fixes it
This commit is contained in:
Reece Wilson 2023-04-26 07:24:17 +01:00
parent 22c4d25759
commit 30b0c2e0ba
4 changed files with 32 additions and 13 deletions

View File

@ -279,6 +279,14 @@ namespace Aurora::IO::FS
this->overlap.hEvent = this->event = CreateEventW(nullptr, true, false, nullptr); this->overlap.hEvent = this->event = CreateEventW(nullptr, true, false, nullptr);
return this->overlap.hEvent != INVALID_HANDLE_VALUE; return this->overlap.hEvent != INVALID_HANDLE_VALUE;
} }
void NtAsyncFileTransaction::ResetAIO()
{
auto hEvent = this->overlap.hEvent;
AuResetMember(this->overlap);
this->overlap.hEvent = hEvent;
}
static bool TranslateNtStatus(NtAsyncFileTransaction *that, BOOL val) static bool TranslateNtStatus(NtAsyncFileTransaction *that, BOOL val)
{ {
auto er = GetLastError(); auto er = GetLastError();
@ -347,12 +355,9 @@ namespace Aurora::IO::FS
bool NtAsyncFileTransaction::IDontWannaUsePorts() bool NtAsyncFileTransaction::IDontWannaUsePorts()
{ {
// TODO: maybe we could use a semaphore counter of read attempts
// to allow APC callbacks to drag behind
if (AuExchange(this->pPin, AuSharedFromThis())) if (AuExchange(this->pPin, AuSharedFromThis()))
{ {
while (SleepEx(100, true) == WAIT_IO_COMPLETION) while (SleepEx(0, true) == WAIT_IO_COMPLETION)
{ {
} }
@ -407,6 +412,7 @@ namespace Aurora::IO::FS
this->dwLastAbstractOffset = offset; this->dwLastAbstractOffset = offset;
this->dwLastBytes = 0; this->dwLastBytes = 0;
this->ResetAIO();
this->overlap.Offset = AuBitsToLower(offset); this->overlap.Offset = AuBitsToLower(offset);
this->overlap.OffsetHigh = AuBitsToHigher(offset); this->overlap.OffsetHigh = AuBitsToHigher(offset);
@ -453,7 +459,8 @@ namespace Aurora::IO::FS
this->dwLastBytes = 0; this->dwLastBytes = 0;
this->dwLastAbstractStat = memoryView->length; this->dwLastAbstractStat = memoryView->length;
this->dwLastAbstractOffset = offset; this->dwLastAbstractOffset = offset;
this->ResetAIO();
this->overlap.Offset = AuBitsToLower(offset); this->overlap.Offset = AuBitsToLower(offset);
this->overlap.OffsetHigh = AuBitsToHigher(offset); this->overlap.OffsetHigh = AuBitsToHigher(offset);
auto ret = ::WriteFileEx(this->pHandle_->writeHandle, memoryView->ptr, memoryView->length, &this->overlap, FileOperationCompletion); auto ret = ::WriteFileEx(this->pHandle_->writeHandle, memoryView->ptr, memoryView->length, &this->overlap, FileOperationCompletion);
@ -533,10 +540,10 @@ namespace Aurora::IO::FS
if (::GetOverlappedResult(this->pHandle_->handle, if (::GetOverlappedResult(this->pHandle_->handle,
&this->overlap, &this->overlap,
&read, &read,
false)) false) && read)
{ {
DispatchCb(read); DispatchCb(read);
return read; return true;
} }
} }
else else

View File

@ -51,6 +51,7 @@ namespace Aurora::IO::FS
~NtAsyncFileTransaction(); ~NtAsyncFileTransaction();
bool Init(const AuSPtr<FileHandle> &handle); bool Init(const AuSPtr<FileHandle> &handle);
void ResetAIO();
bool StartRead(AuUInt64 offset, const AuSPtr<AuMemoryViewWrite> &memoryView) override; bool StartRead(AuUInt64 offset, const AuSPtr<AuMemoryViewWrite> &memoryView) override;
bool StartWrite(AuUInt64 offset, const AuSPtr<AuMemoryViewRead> &memoryView) override; bool StartWrite(AuUInt64 offset, const AuSPtr<AuMemoryViewRead> &memoryView) override;

View File

@ -300,10 +300,15 @@ namespace Aurora::IO::Net
return true; return true;
} }
if (::GetOverlappedResult((HANDLE)this->GetSocket(), &this->overlap, &read, false)) if (!this->pMemoryHold)
{
return false;
}
if (::GetOverlappedResult((HANDLE)this->GetSocket(), &this->overlap, &read, false) && read)
{ {
DispatchCb(read); DispatchCb(read);
return read; return true;
} }
} }
else else
@ -397,7 +402,7 @@ namespace Aurora::IO::Net
{ {
if (AuExchange(this->pPin, AuSharedFromThis())) if (AuExchange(this->pPin, AuSharedFromThis()))
{ {
while (SleepEx(100, true) == WAIT_IO_COMPLETION) while (SleepEx(0, true) == WAIT_IO_COMPLETION)
{ {
} }

View File

@ -52,14 +52,18 @@ namespace Aurora::IO
{ {
return {}; return {};
} }
AuDebug::AddMemoryCrunch();
retTransasctions.reserve(transactions.size()); AuTryReserve(retTransasctions, transactions.size());
for (const auto &file : transactions) for (const auto &file : transactions)
{ {
AuTryInsert(handles, AuStaticPointerCast<FS::NtAsyncFileTransaction>(file)->GetHandle()); SysAssert(AuTryInsert(handles, AuStaticPointerCast<FS::NtAsyncFileTransaction>(file)->GetHandle()));
} }
AuDebug::DecMemoryCrunch();
auto ret = WaitForMultipleObjectsEx(handles.size(), handles.data(), false, timeoutMs ? timeoutMs : INFINITE, TRUE); auto ret = WaitForMultipleObjectsEx(handles.size(), handles.data(), false, timeoutMs ? timeoutMs : INFINITE, TRUE);
if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED)
@ -71,7 +75,9 @@ namespace Aurora::IO
{ {
if (AuStaticPointerCast<FS::NtAsyncFileTransaction>(file)->Complete()) if (AuStaticPointerCast<FS::NtAsyncFileTransaction>(file)->Complete())
{ {
AuTryInsert(retTransasctions, file); AuDebug::AddMemoryCrunch();
SysAssert(AuTryInsert(retTransasctions, file));
AuDebug::DecMemoryCrunch();
} }
} }