mirror of https://github.com/PCSX2/pcsx2.git
ThreadedFileReader: Fix possible race with synchronous reads
This commit is contained in:
parent
576bcc6979
commit
008beb4896
|
@ -70,22 +70,35 @@ void ThreadedFileReader::Loop()
|
||||||
if (m_quit)
|
if (m_quit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u64 requestOffset = m_requestOffset;
|
void* ptr;
|
||||||
u32 requestSize = m_requestSize;
|
u64 requestOffset;
|
||||||
void* ptr = m_requestPtr.load(std::memory_order_relaxed);
|
u32 requestSize;
|
||||||
|
|
||||||
m_running = true;
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
m_running = true;
|
||||||
|
|
||||||
if (ptr)
|
for (;;)
|
||||||
{
|
{
|
||||||
ok = Decompress(ptr, requestOffset, requestSize);
|
ptr = m_requestPtr.load(std::memory_order_acquire);
|
||||||
}
|
requestOffset = m_requestOffset;
|
||||||
|
requestSize = m_requestSize;
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
m_requestPtr.store(nullptr, std::memory_order_release);
|
if (ptr)
|
||||||
m_condition.notify_one();
|
ok = Decompress(ptr, requestOffset, requestSize);
|
||||||
|
|
||||||
|
// There's a potential for a race here when doing synchronous reads. Basically, another request can come in,
|
||||||
|
// after we release the lock, but before we store null to indicate we're finished. So, we do a compare-exchange
|
||||||
|
// instead, to detect when this happens, and if so, reload all the inputs and try again.
|
||||||
|
if (!m_requestPtr.compare_exchange_strong(ptr, nullptr, std::memory_order_release))
|
||||||
|
{
|
||||||
|
lock.lock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_condition.notify_one();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
|
@ -326,7 +339,7 @@ int ThreadedFileReader::FinishRead(void)
|
||||||
if (m_requestPtr.load(std::memory_order_acquire) == nullptr)
|
if (m_requestPtr.load(std::memory_order_acquire) == nullptr)
|
||||||
return m_amtRead;
|
return m_amtRead;
|
||||||
std::unique_lock<std::mutex> lock(m_mtx);
|
std::unique_lock<std::mutex> lock(m_mtx);
|
||||||
while (m_requestPtr)
|
while (m_requestPtr.load(std::memory_order_acquire))
|
||||||
m_condition.wait(lock);
|
m_condition.wait(lock);
|
||||||
return m_amtRead;
|
return m_amtRead;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue