mirror of https://github.com/PCSX2/pcsx2.git
cdvdgigaherz: Use a queue to manage sector requests
Fixes a data race. Also avoid copying from the cache when it's unnecessary to do so.
This commit is contained in:
parent
3919a32dc3
commit
29c2ccb310
|
@ -114,7 +114,6 @@ extern void (*newDiscCB)();
|
||||||
bool cdvdStartThread();
|
bool cdvdStartThread();
|
||||||
void cdvdStopThread();
|
void cdvdStopThread();
|
||||||
s32 cdvdRequestSector(u32 sector, s32 mode);
|
s32 cdvdRequestSector(u32 sector, s32 mode);
|
||||||
s32 cdvdRequestComplete();
|
|
||||||
u8 *cdvdGetSector(u32 sector, s32 mode);
|
u8 *cdvdGetSector(u32 sector, s32 mode);
|
||||||
s32 cdvdDirectReadSector(u32 first, s32 mode, u8 *buffer);
|
s32 cdvdDirectReadSector(u32 first, s32 mode, u8 *buffer);
|
||||||
s32 cdvdGetMediaType();
|
s32 cdvdGetMediaType();
|
||||||
|
|
|
@ -17,8 +17,15 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <queue>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
struct CacheRequest
|
||||||
|
{
|
||||||
|
u32 lsn;
|
||||||
|
s32 mode;
|
||||||
|
};
|
||||||
|
|
||||||
struct SectorInfo
|
struct SectorInfo
|
||||||
{
|
{
|
||||||
u32 lsn;
|
u32 lsn;
|
||||||
|
@ -37,6 +44,7 @@ static std::thread s_thread;
|
||||||
static std::mutex s_notify_lock;
|
static std::mutex s_notify_lock;
|
||||||
static std::condition_variable s_notify_cv;
|
static std::condition_variable s_notify_cv;
|
||||||
static std::mutex s_request_lock;
|
static std::mutex s_request_lock;
|
||||||
|
static std::queue<CacheRequest> s_request_queue;
|
||||||
static std::mutex s_cache_lock;
|
static std::mutex s_cache_lock;
|
||||||
|
|
||||||
static std::atomic<bool> cdvd_is_open;
|
static std::atomic<bool> cdvd_is_open;
|
||||||
|
@ -47,9 +55,6 @@ static std::atomic<bool> cdvd_is_open;
|
||||||
const u32 CacheSize = 1U << CACHE_SIZE;
|
const u32 CacheSize = 1U << CACHE_SIZE;
|
||||||
SectorInfo Cache[CacheSize];
|
SectorInfo Cache[CacheSize];
|
||||||
|
|
||||||
bool threadRequestPending;
|
|
||||||
SectorInfo threadRequestInfo;
|
|
||||||
|
|
||||||
u32 cdvdSectorHash(u32 lsn, s32 mode)
|
u32 cdvdSectorHash(u32 lsn, s32 mode)
|
||||||
{
|
{
|
||||||
u32 t = 0;
|
u32 t = 0;
|
||||||
|
@ -149,6 +154,12 @@ bool cdvdUpdateDiscStatus()
|
||||||
|
|
||||||
disc_has_changed = false;
|
disc_has_changed = false;
|
||||||
cdvdRefreshData();
|
cdvdRefreshData();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> request_guard(s_request_lock);
|
||||||
|
s_request_queue = std::queue<CacheRequest>();
|
||||||
|
}
|
||||||
|
|
||||||
cdvdCallNewDiscCB();
|
cdvdCallNewDiscCB();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,6 +168,8 @@ bool cdvdUpdateDiscStatus()
|
||||||
|
|
||||||
void cdvdThread()
|
void cdvdThread()
|
||||||
{
|
{
|
||||||
|
u8 buffer[2352 * 16];
|
||||||
|
|
||||||
printf(" * CDVD: IO thread started...\n");
|
printf(" * CDVD: IO thread started...\n");
|
||||||
std::unique_lock<std::mutex> guard(s_notify_lock);
|
std::unique_lock<std::mutex> guard(s_notify_lock);
|
||||||
|
|
||||||
|
@ -173,30 +186,29 @@ void cdvdThread()
|
||||||
if (!cdvd_is_open)
|
if (!cdvd_is_open)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
static SectorInfo info;
|
bool handling_request = false;
|
||||||
|
CacheRequest request;
|
||||||
|
|
||||||
bool handlingRequest = false;
|
{
|
||||||
|
std::lock_guard<std::mutex> request_guard(s_request_lock);
|
||||||
if (threadRequestPending) {
|
if (!s_request_queue.empty()) {
|
||||||
info = threadRequestInfo;
|
request = s_request_queue.front();
|
||||||
handlingRequest = true;
|
s_request_queue.pop();
|
||||||
|
handling_request = true;
|
||||||
} else {
|
} else {
|
||||||
info.lsn = prefetch_last_lba;
|
request.lsn = prefetch_last_lba;
|
||||||
info.mode = prefetch_last_mode;
|
request.mode = prefetch_last_mode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (threadRequestPending || prefetch_left) {
|
if (handling_request || prefetch_left) {
|
||||||
if (cdvdReadBlockOfSectors(info.lsn, info.mode, info.data))
|
if (!cdvdCacheCheck(request.lsn, request.mode))
|
||||||
cdvdCacheUpdate(info.lsn, info.mode, info.data);
|
if (cdvdReadBlockOfSectors(request.lsn, request.mode, buffer))
|
||||||
|
cdvdCacheUpdate(request.lsn, request.mode, buffer);
|
||||||
|
|
||||||
if (handlingRequest) {
|
if (handling_request) {
|
||||||
threadRequestInfo = info;
|
prefetch_last_lba = request.lsn;
|
||||||
|
prefetch_last_mode = request.mode;
|
||||||
handlingRequest = false;
|
|
||||||
threadRequestPending = false;
|
|
||||||
|
|
||||||
prefetch_last_lba = info.lsn;
|
|
||||||
prefetch_last_mode = info.mode;
|
|
||||||
|
|
||||||
prefetch_left = prefetch_max_blocks;
|
prefetch_left = prefetch_max_blocks;
|
||||||
} else {
|
} else {
|
||||||
|
@ -237,24 +249,19 @@ s32 cdvdRequestSector(u32 sector, s32 mode)
|
||||||
|
|
||||||
sector &= ~15; //align to 16-sector block
|
sector &= ~15; //align to 16-sector block
|
||||||
|
|
||||||
threadRequestInfo.lsn = sector;
|
if (cdvdCacheCheck(sector, mode))
|
||||||
threadRequestInfo.mode = mode;
|
|
||||||
threadRequestPending = false;
|
|
||||||
if (cdvdCacheFetch(sector, mode, threadRequestInfo.data)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(s_request_lock);
|
||||||
|
s_request_queue.push({sector, mode});
|
||||||
}
|
}
|
||||||
|
|
||||||
threadRequestPending = true;
|
|
||||||
s_notify_cv.notify_one();
|
s_notify_cv.notify_one();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 cdvdRequestComplete()
|
|
||||||
{
|
|
||||||
return !threadRequestPending;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 *cdvdGetSector(u32 sector, s32 mode)
|
u8 *cdvdGetSector(u32 sector, s32 mode)
|
||||||
{
|
{
|
||||||
static u8 buffer[2352 * 16];
|
static u8 buffer[2352 * 16];
|
||||||
|
|
Loading…
Reference in New Issue