From f8f79788e4a06de30c9c88313730a42f1a15f795 Mon Sep 17 00:00:00 2001 From: Jonathan Li Date: Tue, 25 Oct 2016 01:32:51 +0100 Subject: [PATCH] cdvdgigaherz: Use condition variables for event waiting Also use atomics for thread exit variables. --- plugins/cdvdGigaherz/src/CDVD.cpp | 34 ++++++++++----------- plugins/cdvdGigaherz/src/CDVD.h | 2 -- plugins/cdvdGigaherz/src/ReadThread.cpp | 39 +++++++++++-------------- 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/plugins/cdvdGigaherz/src/CDVD.cpp b/plugins/cdvdGigaherz/src/CDVD.cpp index fc9732f54c..499389093d 100644 --- a/plugins/cdvdGigaherz/src/CDVD.cpp +++ b/plugins/cdvdGigaherz/src/CDVD.cpp @@ -15,6 +15,8 @@ #include "CDVD.h" #include +#include +#include #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 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 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 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); } /////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/cdvdGigaherz/src/CDVD.h b/plugins/cdvdGigaherz/src/CDVD.h index 783341b3bf..2c362c4796 100644 --- a/plugins/cdvdGigaherz/src/CDVD.h +++ b/plugins/cdvdGigaherz/src/CDVD.h @@ -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; diff --git a/plugins/cdvdGigaherz/src/ReadThread.cpp b/plugins/cdvdGigaherz/src/ReadThread.cpp index 28f160a7c4..faf3010138 100644 --- a/plugins/cdvdGigaherz/src/ReadThread.cpp +++ b/plugins/cdvdGigaherz/src/ReadThread.cpp @@ -14,6 +14,8 @@ */ #include "CDVD.h" +#include +#include 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 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 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 guard(s_request_lock); + while (threadRequestPending) + s_request_cv.wait_for(guard, std::chrono::milliseconds(10)); } s32 offset;