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) bool CDROMAsyncReader::ReadSectorUncached(CDImage::LBA lba, CDImage::SubChannelQ* subq, SectorBuffer* data)
{ {
if (IsUsingThread()) if (!IsUsingThread())
CancelReadahead(); 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)) if (m_media->GetPositionOnDisc() != lba && !m_media->Seek(lba))
{ {
Log_WarningPrintf("Seek to LBA %u failed", lba); Log_WarningPrintf("Seek to LBA %u failed", lba);

View file

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