CDROM: Fix async readahead causing lockups in some games

This commit is contained in:
Connor McLaughlin 2021-07-14 01:25:49 +10:00
parent ab9109f3b1
commit c2c204c845
2 changed files with 28 additions and 8 deletions

View file

@ -101,9 +101,28 @@ void CDROMAsyncReader::QueueReadSector(CDImage::LBA lba)
bool CDROMAsyncReader::ReadSectorUncached(CDImage::LBA lba, CDImage::SubChannelQ* subq, SectorBuffer* data)
{
if (IsUsingThread())
CancelReadahead();
if (!IsUsingThread())
return InternalReadSectorUncached(lba, subq, data);
std::unique_lock lock(m_mutex);
// wait until the read thread is idle
m_notify_read_complete_cv.wait(lock, [this]() { return !m_is_reading.load(); });
// read while the lock is held so it has to wait
const CDImage::LBA prev_lba = m_media->GetPositionOnDisc();
const bool result = InternalReadSectorUncached(lba, subq, data);
if (!m_media->Seek(prev_lba))
{
Log_ErrorPrintf("Failed to re-seek to cached position %u", prev_lba);
m_can_readahead.store(false);
}
return result;
}
bool CDROMAsyncReader::InternalReadSectorUncached(CDImage::LBA lba, CDImage::SubChannelQ* subq, SectorBuffer* data)
{
if (m_media->GetPositionOnDisc() != lba && !m_media->Seek(lba))
{
Log_WarningPrintf("Seek to LBA %u failed", lba);

View file

@ -52,6 +52,7 @@ private:
void EmptyBuffers();
bool ReadSectorIntoBuffer(std::unique_lock<std::mutex>& lock);
void ReadSectorNonThreaded(CDImage::LBA lba);
bool InternalReadSectorUncached(CDImage::LBA lba, CDImage::SubChannelQ* subq, SectorBuffer* data);
void CancelReadahead();
void WorkerThreadEntryPoint();
@ -67,12 +68,12 @@ private:
std::atomic_bool m_next_position_set{false};
std::atomic_bool m_shutdown_flag{true};
std::atomic_bool m_is_reading{ false };
std::atomic_bool m_can_readahead{ false };
std::atomic_bool m_seek_error{ false };
std::atomic_bool m_is_reading{false};
std::atomic_bool m_can_readahead{false};
std::atomic_bool m_seek_error{false};
std::vector<BufferSlot> m_buffers;
std::atomic<u32> m_buffer_front{ 0 };
std::atomic<u32> m_buffer_back{ 0 };
std::atomic<u32> m_buffer_count{ 0 };
std::atomic<u32> m_buffer_front{0};
std::atomic<u32> m_buffer_back{0};
std::atomic<u32> m_buffer_count{0};
};