[*] 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:
parent
22c4d25759
commit
30b0c2e0ba
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user