cdvdgigaherz: Use condition variables for event waiting

Also use atomics for thread exit variables.
This commit is contained in:
Jonathan Li 2016-10-25 01:32:51 +01:00
parent f678ff8cfd
commit f8f79788e4
3 changed files with 32 additions and 43 deletions

View File

@ -15,6 +15,8 @@
#include "CDVD.h"
#include <cstdio>
#include <atomic>
#include <condition_variable>
#include "svnrev.h"
Settings g_settings;
@ -22,8 +24,9 @@ static std::string s_config_file{"inis/cdvdGigaherz.ini"};
void (*newDiscCB)();
static std::mutex s_keepalive_lock;
static std::condition_variable s_keepalive_cv;
HANDLE hThread_keepAlive = nullptr;
HANDLE hNotify_keepAlive = nullptr;
DWORD pidThreadKeepAlive = 0;
#define STRFY(x) #x
@ -116,8 +119,7 @@ void WriteSettings()
///////////////////////////////////////////////////////////////////////////////
// CDVD processing functions //
bool cdvd_is_open = false;
bool cdvdKeepAlive_is_open = false;
std::atomic<bool> s_keepalive_is_open;
bool disc_has_changed = false;
bool weAreInNewDiskCB = false;
@ -133,14 +135,10 @@ extern s32 prefetch_last_mode;
DWORD CALLBACK keepAliveThread(PVOID param)
{
printf(" * CDVD: KeepAlive thread started...\n");
std::unique_lock<std::mutex> guard(s_keepalive_lock);
while (cdvdKeepAlive_is_open) {
// Sleep 30 seconds with thread abort check
if (WaitForSingleObject(hNotify_keepAlive, 30000) != WAIT_TIMEOUT)
break;
if (!cdvdKeepAlive_is_open) {
break;
}
while (!s_keepalive_cv.wait_for(guard, std::chrono::seconds(30),
[]() { return !s_keepalive_is_open; })) {
//printf(" * keepAliveThread: polling drive.\n");
//if (prefetch_last_mode == CDVD_MODE_2048)
@ -156,14 +154,10 @@ DWORD CALLBACK keepAliveThread(PVOID param)
s32 StartKeepAliveThread()
{
hNotify_keepAlive = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hNotify_keepAlive == nullptr)
return -1;
cdvdKeepAlive_is_open = true;
s_keepalive_is_open = true;
hThread_keepAlive = CreateThread(NULL, 0, keepAliveThread, NULL, 0, &pidThreadKeepAlive);
if (hThread_keepAlive == nullptr) {
cdvdKeepAlive_is_open = false;
s_keepalive_is_open = false;
return -1;
}
@ -174,13 +168,15 @@ s32 StartKeepAliveThread()
void StopKeepAliveThread()
{
cdvdKeepAlive_is_open = false;
PulseEvent(hNotify_keepAlive);
{
std::lock_guard<std::mutex> guard(s_keepalive_lock);
s_keepalive_is_open = false;
}
s_keepalive_cv.notify_one();
if (WaitForSingleObject(hThread_keepAlive, 5000) == WAIT_TIMEOUT) {
TerminateThread(hThread_keepAlive, 0);
}
CloseHandle(hThread_keepAlive);
CloseHandle(hNotify_keepAlive);
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -93,8 +93,6 @@ std::wstring GetValidDrive();
extern Settings g_settings;
extern bool cdvd_is_open;
extern bool cdvdKeepAlive_is_open;
extern bool disc_has_changed;
extern bool weAreInNewDiskCB;

View File

@ -14,6 +14,8 @@
*/
#include "CDVD.h"
#include <atomic>
#include <condition_variable>
const s32 prefetch_max_blocks = 16;
s32 prefetch_mode = 0;
@ -21,12 +23,16 @@ s32 prefetch_last_lba = 0;
s32 prefetch_last_mode = 0;
s32 prefetch_left = 0;
HANDLE hNotify = nullptr;
HANDLE hThread = nullptr;
HANDLE hRequestComplete = nullptr;
static std::mutex s_notify_lock;
static std::condition_variable s_notify_cv;
static std::mutex s_request_lock;
static std::condition_variable s_request_cv;
static std::mutex s_cache_lock;
static std::atomic<bool> cdvd_is_open;
DWORD pidThread = 0;
typedef struct
@ -128,6 +134,7 @@ bool cdvdUpdateDiscStatus()
DWORD CALLBACK cdvdThread(PVOID param)
{
printf(" * CDVD: IO thread started...\n");
std::unique_lock<std::mutex> guard(s_notify_lock);
while (cdvd_is_open) {
if (cdvdUpdateDiscStatus()) {
@ -136,10 +143,7 @@ DWORD CALLBACK cdvdThread(PVOID param)
continue;
}
if (prefetch_left)
WaitForSingleObject(hNotify, 1);
else
WaitForSingleObject(hNotify, 250);
s_notify_cv.wait_for(guard, std::chrono::milliseconds(prefetch_left ? 1 : 250));
// check again to make sure we're not done here...
if (!cdvd_is_open)
@ -181,7 +185,7 @@ DWORD CALLBACK cdvdThread(PVOID param)
handlingRequest = false;
threadRequestPending = false;
PulseEvent(hRequestComplete);
s_request_cv.notify_one();
prefetch_last_lba = info.lsn;
prefetch_last_mode = info.mode;
@ -199,14 +203,6 @@ DWORD CALLBACK cdvdThread(PVOID param)
s32 cdvdStartThread()
{
hNotify = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hNotify == nullptr)
return -1;
hRequestComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hRequestComplete == nullptr)
return -1;
cdvd_is_open = true;
hThread = CreateThread(NULL, 0, cdvdThread, NULL, 0, &pidThread);
@ -223,13 +219,11 @@ s32 cdvdStartThread()
void cdvdStopThread()
{
cdvd_is_open = false;
PulseEvent(hNotify);
s_notify_cv.notify_one();
if (WaitForSingleObject(hThread, 4000) == WAIT_TIMEOUT) {
TerminateThread(hThread, 0);
}
CloseHandle(hThread);
CloseHandle(hNotify);
CloseHandle(hRequestComplete);
}
s32 cdvdRequestSector(u32 sector, s32 mode)
@ -247,8 +241,7 @@ s32 cdvdRequestSector(u32 sector, s32 mode)
}
threadRequestPending = true;
ResetEvent(hRequestComplete);
PulseEvent(hNotify);
s_notify_cv.notify_one();
return 0;
}
@ -260,8 +253,10 @@ s32 cdvdRequestComplete()
s8 *cdvdGetSector(s32 sector, s32 mode)
{
while (threadRequestPending) {
WaitForSingleObject(hRequestComplete, 10);
{
std::unique_lock<std::mutex> guard(s_request_lock);
while (threadRequestPending)
s_request_cv.wait_for(guard, std::chrono::milliseconds(10));
}
s32 offset;