From 423018f811ce8c1682735d33a3790031b8c08576 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 5 Mar 2011 06:11:26 +0000 Subject: [PATCH] Replaced Common::CriticalSection with a std::mutex implementation. 64bit Windows builds now use SRWLocks and ConditionVariables(requires Vista/7, x64 builds will no longer work on Windows XP x64). Tell me if you hate that. Removed Common::EventEx. Common::Event now uses a std::condition_variable impl.(using ConditionVariables on Windows x64, Events on x86, or posix condition variables elsewhere). I experience slight speed improvements with these changes. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@7294 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/AudioCommon/Src/AOSoundStream.cpp | 15 +- Source/Core/AudioCommon/Src/AOSoundStream.h | 2 +- Source/Core/AudioCommon/Src/DSoundStream.cpp | 4 - Source/Core/AudioCommon/Src/DSoundStream.h | 2 +- Source/Core/AudioCommon/Src/OpenALStream.cpp | 4 - Source/Core/AudioCommon/Src/OpenALStream.h | 2 +- Source/Core/AudioCommon/Src/XAudio2Stream.cpp | 8 +- Source/Core/AudioCommon/Src/XAudio2Stream.h | 2 +- Source/Core/Common/Common.vcxproj | 2 + Source/Core/Common/Common.vcxproj.filters | 2 + Source/Core/Common/Src/LogManager.cpp | 15 +- Source/Core/Common/Src/LogManager.h | 8 +- Source/Core/Common/Src/StdConditionVariable.h | 152 +++++++ Source/Core/Common/Src/StdMutex.h | 352 +++++++++++++++ Source/Core/Common/Src/Thread.cpp | 403 +++--------------- Source/Core/Common/Src/Thread.h | 160 +++---- Source/Core/Core/Src/Core.cpp | 16 +- Source/Core/Core/Src/CoreTiming.cpp | 24 +- Source/Core/Core/Src/DSP/DSPCore.cpp | 8 +- Source/Core/Core/Src/DSP/DSPCore.h | 2 +- Source/Core/Core/Src/DSP/DSPHWInterface.cpp | 52 ++- Source/Core/Core/Src/GeckoCode.cpp | 35 +- Source/Core/Core/Src/HW/CPU.cpp | 2 - .../Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp | 4 +- .../HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp | 3 +- .../Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h | 2 +- Source/Core/Core/Src/HW/DVDInterface.cpp | 13 +- Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp | 33 +- Source/Core/Core/Src/HW/EXI_DeviceGecko.h | 4 +- Source/Core/Core/Src/HW/GCPad.cpp | 16 +- Source/Core/Core/Src/HW/SI_DeviceGBA.cpp | 9 +- Source/Core/Core/Src/HW/Wiimote.cpp | 6 +- .../Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp | 4 +- .../Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp | 3 +- .../Core/Src/HW/WiimoteReal/WiimoteReal.cpp | 26 +- .../Core/Src/HW/WiimoteReal/WiimoteReal.h | 2 +- Source/Core/Core/Src/NetPlay.cpp | 30 +- Source/Core/Core/Src/NetPlay.h | 17 +- Source/Core/Core/Src/NetPlayClient.cpp | 40 +- Source/Core/Core/Src/NetPlayServer.cpp | 87 ++-- Source/Core/Core/Src/OnFrame.cpp | 10 +- .../DolphinWX/Src/Debugger/CodeWindow.cpp | 2 - Source/Core/DolphinWX/Src/Frame.cpp | 7 - Source/Core/DolphinWX/Src/InputConfigDiag.cpp | 44 +- .../DolphinWX/Src/InputConfigDiagBitmaps.cpp | 6 +- Source/Core/DolphinWX/Src/LogWindow.cpp | 15 +- Source/Core/DolphinWX/Src/LogWindow.h | 2 +- .../ControllerInterface.cpp | 22 +- .../ControllerInterface/ControllerInterface.h | 2 +- Source/Core/InputCommon/Src/InputConfig.h | 2 +- Source/Core/InputCommon/Src/UDPWiimote.cpp | 51 +-- Source/Core/VideoCommon/Src/RenderBase.cpp | 5 +- Source/Core/VideoCommon/Src/RenderBase.h | 2 +- Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 3 +- Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 7 +- .../Src/SWCommandProcessor.cpp | 2 - 56 files changed, 918 insertions(+), 835 deletions(-) create mode 100644 Source/Core/Common/Src/StdConditionVariable.h create mode 100644 Source/Core/Common/Src/StdMutex.h diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.cpp b/Source/Core/AudioCommon/Src/AOSoundStream.cpp index c857856f1a..e864ad1211 100644 --- a/Source/Core/AudioCommon/Src/AOSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/AOSoundStream.cpp @@ -47,9 +47,11 @@ void AOSound::SoundLoop() while (!threadData) { m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2); - soundCriticalSection.Enter(); + + { + std::lock_guard lk(soundCriticalSection); ao_play(device, (char*)realtimeBuffer, numBytesToRender); - soundCriticalSection.Leave(); + } soundSyncEvent.Wait(); } @@ -58,8 +60,6 @@ void AOSound::SoundLoop() bool AOSound::Start() { memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); - - soundSyncEvent.Init(); thread = std::thread(std::mem_fun(&AOSound::SoundLoop), this); return true; @@ -75,7 +75,8 @@ void AOSound::Stop() threadData = 1; soundSyncEvent.Set(); - soundCriticalSection.Enter(); + { + std::lock_guard lk(soundCriticalSection); thread.join(); if (device) @@ -84,9 +85,7 @@ void AOSound::Stop() ao_shutdown(); device = NULL; - soundCriticalSection.Leave(); - - soundSyncEvent.Shutdown(); + } } AOSound::~AOSound() diff --git a/Source/Core/AudioCommon/Src/AOSoundStream.h b/Source/Core/AudioCommon/Src/AOSoundStream.h index 57a883aa83..a631596f02 100644 --- a/Source/Core/AudioCommon/Src/AOSoundStream.h +++ b/Source/Core/AudioCommon/Src/AOSoundStream.h @@ -30,7 +30,7 @@ class AOSound : public SoundStream { #if defined(HAVE_AO) && HAVE_AO std::thread thread; - Common::CriticalSection soundCriticalSection; + std::mutex soundCriticalSection; Common::Event soundSyncEvent; int buf_size; diff --git a/Source/Core/AudioCommon/Src/DSoundStream.cpp b/Source/Core/AudioCommon/Src/DSoundStream.cpp index 206685f707..38fbc2a851 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.cpp +++ b/Source/Core/AudioCommon/Src/DSoundStream.cpp @@ -119,8 +119,6 @@ void DSound::SoundLoop() bool DSound::Start() { - soundSyncEvent.Init(); - if (FAILED(DirectSoundCreate8(0, &ds, 0))) return false; if (hWnd) @@ -180,7 +178,5 @@ void DSound::Stop() dsBuffer->Stop(); dsBuffer->Release(); ds->Release(); - - soundSyncEvent.Shutdown(); } diff --git a/Source/Core/AudioCommon/Src/DSoundStream.h b/Source/Core/AudioCommon/Src/DSoundStream.h index ab3ab1996a..2575a263bb 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.h +++ b/Source/Core/AudioCommon/Src/DSoundStream.h @@ -32,7 +32,7 @@ class DSound : public SoundStream { #ifdef _WIN32 std::thread thread; - Common::EventEx soundSyncEvent; + Common::Event soundSyncEvent; void *hWnd; IDirectSound8* ds; diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp index 5d46763613..91d2b3270c 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.cpp +++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp @@ -32,8 +32,6 @@ bool OpenALStream::Start() ALCdevice *pDevice = NULL; bool bReturn = false; - soundSyncEvent.Init(); - pDeviceList = new ALDeviceList(); if ((pDeviceList) && (pDeviceList->GetNumDevices())) { @@ -92,8 +90,6 @@ void OpenALStream::Stop() alcMakeContextCurrent(NULL); alcDestroyContext(pContext); alcCloseDevice(pDevice); - - soundSyncEvent.Shutdown(); } void OpenALStream::SetVolume(int volume) diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h index 7d33bb854c..2c0d75b510 100644 --- a/Source/Core/AudioCommon/Src/OpenALStream.h +++ b/Source/Core/AudioCommon/Src/OpenALStream.h @@ -63,7 +63,7 @@ public: private: std::thread thread; - Common::EventEx soundSyncEvent; + Common::Event soundSyncEvent; short realtimeBuffer[OAL_MAX_SAMPLES * 2]; ALuint uiBuffers[OAL_NUM_BUFFERS]; diff --git a/Source/Core/AudioCommon/Src/XAudio2Stream.cpp b/Source/Core/AudioCommon/Src/XAudio2Stream.cpp index 090f56d073..ae93b781a8 100644 --- a/Source/Core/AudioCommon/Src/XAudio2Stream.cpp +++ b/Source/Core/AudioCommon/Src/XAudio2Stream.cpp @@ -22,10 +22,10 @@ struct StreamingVoiceContext : public IXAudio2VoiceCallback { IXAudio2SourceVoice* pSourceVoice; CMixer *m_mixer; - Common::EventEx *soundSyncEvent; + Common::Event *soundSyncEvent; short *xaBuffer; - StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::EventEx *pSyncEvent) + StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event *pSyncEvent) { m_mixer = pMixer; @@ -100,7 +100,6 @@ struct StreamingVoiceContext : public IXAudio2VoiceCallback // if( !pSourceVoice || !context) return; - //soundSyncEvent->Init(); //soundSyncEvent->Wait(); //sync //soundSyncEvent->Spin(); //or tight sync @@ -123,8 +122,6 @@ StreamingVoiceContext* pVoiceContext = 0; bool XAudio2::Start() { - //soundSyncEvent.Init(); - // XAudio2 init CoInitializeEx(NULL, COINIT_MULTITHREADED); HRESULT hr; @@ -207,5 +204,4 @@ void XAudio2::Stop() safe_release(pXAudio2); pMasteringVoice = NULL; CoUninitialize(); - //soundSyncEvent.Shutdown(); } diff --git a/Source/Core/AudioCommon/Src/XAudio2Stream.h b/Source/Core/AudioCommon/Src/XAudio2Stream.h index f0c9924c09..cecb587663 100644 --- a/Source/Core/AudioCommon/Src/XAudio2Stream.h +++ b/Source/Core/AudioCommon/Src/XAudio2Stream.h @@ -52,7 +52,7 @@ class XAudio2 : public SoundStream IXAudio2MasteringVoice *pMasteringVoice; IXAudio2SourceVoice *pSourceVoice; - Common::EventEx soundSyncEvent; + Common::Event soundSyncEvent; float m_volume; diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 315583dc70..705daae67d 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -255,6 +255,8 @@ + + diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index 1faddc9355..fecf4819f6 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -121,6 +121,8 @@ Crypto + + diff --git a/Source/Core/Common/Src/LogManager.cpp b/Source/Core/Common/Src/LogManager.cpp index 6332c1c62b..815dd2ec6d 100644 --- a/Source/Core/Common/Src/LogManager.cpp +++ b/Source/Core/Common/Src/LogManager.cpp @@ -36,9 +36,8 @@ void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, LogManager *LogManager::m_logManager = NULL; -LogManager::LogManager() { - logMutex = new Common::CriticalSection(1); - +LogManager::LogManager() +{ // create log files m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log"); m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot"); @@ -105,7 +104,6 @@ LogManager::~LogManager() { delete m_fileLog; delete m_consoleLog; - delete logMutex; } void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, @@ -127,15 +125,14 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, file, line, level_to_char[(int)level], log->getShortName(), temp); - logMutex->Enter(); + std::lock_guard lk(logMutex); log->trigger(level, msg); - logMutex->Leave(); } -void LogManager::removeListener(LogTypes::LOG_TYPE type, LogListener *listener) { - logMutex->Enter(); +void LogManager::removeListener(LogTypes::LOG_TYPE type, LogListener *listener) +{ + std::lock_guard lk(logMutex); m_Log[type]->removeListener(listener); - logMutex->Leave(); } void LogManager::Init() diff --git a/Source/Core/Common/Src/LogManager.h b/Source/Core/Common/Src/LogManager.h index 37a0ca3c45..b948cb20af 100644 --- a/Source/Core/Common/Src/LogManager.h +++ b/Source/Core/Common/Src/LogManager.h @@ -20,6 +20,7 @@ #include "Log.h" #include "StringUtil.h" +#include "Thread.h" #include #include @@ -102,16 +103,11 @@ private: class ConsoleListener; -// Avoid include through Thread.h -namespace Common { - class CriticalSection; -} - class LogManager : NonCopyable { private: LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS]; - Common::CriticalSection *logMutex; + std::mutex logMutex; FileLogListener *m_fileLog; ConsoleListener *m_consoleLog; static LogManager *m_logManager; // Singleton. Ugh. diff --git a/Source/Core/Common/Src/StdConditionVariable.h b/Source/Core/Common/Src/StdConditionVariable.h new file mode 100644 index 0000000000..fddc83bc63 --- /dev/null +++ b/Source/Core/Common/Src/StdConditionVariable.h @@ -0,0 +1,152 @@ + +#ifndef CONDITION_VARIABLE_H_ +#define CONDITION_VARIABLE_H_ + +#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) +#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) + +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +// GCC 4.4 provides +#include +#else + +// partial std::condition_variable implementation for win32/pthread + +#include "StdMutex.h" + +#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) +#define USE_RVALUE_REFERENCES +#endif + +#if defined(_WIN32) && defined(_M_X64) +#define USE_CONDITION_VARIABLES +#elif defined(_WIN32) +#define USE_EVENTS +#endif + +namespace std +{ + +class condition_variable +{ +#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) + typedef CONDITION_VARIABLE native_type; +#elif defined(_WIN32) + typedef HANDLE native_type; +#else + typedef pthread_cond_t native_type; +#endif + +public: + +#ifdef USE_EVENTS + typedef native_type native_handle_type; +#else + typedef native_type* native_handle_type; +#endif + + condition_variable() + { +#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) + InitializeConditionVariable(&m_handle); +#elif defined(_WIN32) + m_handle = CreateEvent(NULL, false, false, NULL); +#else + pthread_cond_init(&m_handle, NULL); +#endif + } + + ~condition_variable() + { +#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES) + CloseHandle(m_handle); +#elif !defined(_WIN32) + pthread_cond_destroy(&m_handle); +#endif + } + + condition_variable(const condition_variable&) /*= delete*/; + condition_variable& operator=(const condition_variable&) /*= delete*/; + + void notify_one() + { +#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) + WakeConditionVariable(&m_handle); +#elif defined(_WIN32) + SetEvent(m_handle); +#else + pthread_cond_signal(&m_handle); +#endif + } + + void notify_all() + { +#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) + WakeAllConditionVariable(&m_handle); +#elif defined(_WIN32) + // TODO: broken + SetEvent(m_handle); +#else + pthread_cond_broadcast(&m_handle); +#endif + } + + void wait(unique_lock& lock) + { +#ifdef _WIN32 + #ifdef USE_SRWLOCKS + SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0); + #elif USE_CONDITION_VARIABLES + SleepConditionVariableCS(m_handle, lock.mutex()->native_handle(), INFINITE); + #else + lock.unlock(); + WaitForSingleObject(m_handle, INFINITE); + lock.lock(); + #endif +#else + pthread_cond_wait(&m_handle, lock.mutex()->native_handle()); +#endif + } + + template + void wait(unique_lock& lock, Predicate pred) + { + while (!pred()) + wait(lock); + } + + //template + //cv_status wait_until(unique_lock& lock, + // const chrono::time_point& abs_time); + + //template + // bool wait_until(unique_lock& lock, + // const chrono::time_point& abs_time, + // Predicate pred); + + //template + //cv_status wait_for(unique_lock& lock, + // const chrono::duration& rel_time); + + //template + // bool wait_for(unique_lock& lock, + // const chrono::duration& rel_time, + // Predicate pred); + + native_handle_type native_handle() + { +#ifdef USE_EVENTS + return m_handle; +#else + return &m_handle; +#endif + } + +private: + native_type m_handle; +}; + +} + +#endif +#endif diff --git a/Source/Core/Common/Src/StdMutex.h b/Source/Core/Common/Src/StdMutex.h new file mode 100644 index 0000000000..580917f2e8 --- /dev/null +++ b/Source/Core/Common/Src/StdMutex.h @@ -0,0 +1,352 @@ + +#ifndef MUTEX_H_ +#define MUTEX_H_ + +#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) +#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) + +#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ +// GCC 4.4 provides +#include +#else + +// partial implementation for win32/pthread + +#include + +#if defined(_WIN32) +// WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +#else +// POSIX +#include + +#endif + +#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) +#define USE_RVALUE_REFERENCES +#endif + +#if defined(_WIN32) && defined(_M_X64) +#define USE_SRWLOCKS +#endif + +namespace std +{ + +class recursive_mutex +{ +#ifdef _WIN32 + typedef CRITICAL_SECTION native_type; +#else + typedef pthread_mutex_t native_type; +#endif + +public: + typedef native_type* native_handle_type; + + recursive_mutex(const recursive_mutex&) /*= delete*/; + recursive_mutex& operator=(const recursive_mutex&) /*= delete*/; + + recursive_mutex() + { +#ifdef _WIN32 + InitializeCriticalSection(&m_handle); +#else + pthread_mutexattr_t attr; + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_handle, &attr); +#endif + } + + ~recursive_mutex() + { +#ifdef _WIN32 + DeleteCriticalSection(&m_handle); +#else + pthread_mutex_destroy(&m_handle); +#endif + } + + void lock() + { +#ifdef _WIN32 + EnterCriticalSection(&m_handle); +#else + pthread_mutex_lock(&m_handle); +#endif + } + + void unlock() + { +#ifdef _WIN32 + LeaveCriticalSection(&m_handle); +#else + pthread_mutex_unlock(&m_handle); +#endif + } + + bool try_lock() + { +#ifdef _WIN32 + return (0 != TryEnterCriticalSection(&m_handle)); +#else + return !pthread_mutex_trylock(&m_handle); +#endif + } + + native_handle_type native_handle() + { + return &m_handle; + } + +private: + native_type m_handle; +}; + +#ifdef USE_SRWLOCKS + +class mutex +{ +#ifdef _WIN32 + typedef SRWLOCK native_type; +#else + typedef pthread_mutex_t native_type; +#endif + +public: + typedef native_type* native_handle_type; + + mutex(const mutex&) /*= delete*/; + mutex& operator=(const mutex&) /*= delete*/; + + mutex() + { +#ifdef _WIN32 + InitializeSRWLock(&m_handle); +#else + pthread_mutex_init(&m_handle, NULL); +#endif + } + + ~mutex() + { +#ifdef _WIN32 +#else + pthread_mutex_destroy(&m_handle); +#endif + } + + void lock() + { +#ifdef _WIN32 + AcquireSRWLockExclusive(&m_handle); +#else + pthread_mutex_lock(&m_handle); +#endif + } + + void unlock() + { +#ifdef _WIN32 + ReleaseSRWLockExclusive(&m_handle); +#else + pthread_mutex_unlock(&m_handle); +#endif + } + + bool try_lock() + { +#ifdef _WIN32 + return (0 != TryAcquireSRWLockExclusive(&m_handle)); +#else + return !pthread_mutex_trylock(&m_handle); +#endif + } + + native_handle_type native_handle() + { + return &m_handle; + } + +private: + native_type m_handle; +}; + +#else +typedef recursive_mutex mutex; // just use CriticalSections + +#endif + +enum defer_lock_t { defer_lock }; +enum try_to_lock_t { try_to_lock }; +enum adopt_lock_t { adopt_lock }; + +template +class lock_guard +{ +public: + typedef Mutex mutex_type; + + explicit lock_guard(mutex_type& m) + : pm(m) + { + m.lock(); + } + + lock_guard(mutex_type& m, adopt_lock_t) + : pm(m) + { + } + + ~lock_guard() + { + pm.unlock(); + } + + lock_guard(lock_guard const&) /*= delete*/; + lock_guard& operator=(lock_guard const&) /*= delete*/; + +private: + mutex_type& pm; +}; + +template +class unique_lock +{ +public: + typedef Mutex mutex_type; + + unique_lock() + : pm(NULL), owns(false) + {} + + /*explicit*/ unique_lock(mutex_type& m) + : pm(&m), owns(true) + { + m.lock(); + } + + unique_lock(mutex_type& m, defer_lock_t) + : pm(&m), owns(false) + {} + + unique_lock(mutex_type& m, try_to_lock_t) + : pm(&m), owns(m.try_lock()) + {} + + unique_lock(mutex_type& m, adopt_lock_t) + : pm(&m), owns(true) + {} + + //template + //unique_lock(mutex_type& m, const chrono::time_point& abs_time); + + //template + //unique_lock(mutex_type& m, const chrono::duration& rel_time); + + ~unique_lock() + { + if (owns_lock()) + mutex()->unlock(); + } + +#ifdef USE_RVALUE_REFERENCES + unique_lock& operator=(const unique_lock&) /*= delete*/; + + unique_lock& operator=(unique_lock&& other) + { +#else + unique_lock& operator=(const unique_lock& u) + { + // ugly const_cast to get around lack of rvalue references + unique_lock& other = const_cast(u); +#endif + swap(other); + return *this; + } + +#ifdef USE_RVALUE_REFERENCES + unique_lock(const unique_lock&) /*= delete*/; + + unique_lock(unique_lock&& other) + : pm(NULL), owns(false) + { +#else + unique_lock(const unique_lock& u) + : pm(NULL), owns(false) + { + // ugly const_cast to get around lack of rvalue references + unique_lock& other = const_cast(u); +#endif + swap(other); + } + + void lock() + { + mutex()->lock(); + owns = true; + } + + bool try_lock() + { + owns = mutex()->try_lock(); + return owns; + } + + //template + //bool try_lock_for(const chrono::duration& rel_time); + //template + //bool try_lock_until(const chrono::time_point& abs_time); + + void unlock() + { + mutex()->unlock(); + owns = false; + } + + void swap(unique_lock& u) + { + std::swap(pm, u.pm); + std::swap(owns, u.owns); + } + + mutex_type* release() + { + return mutex(); + pm = NULL; + owns = false; + } + + bool owns_lock() const + { + return owns; + } + + //explicit operator bool () const + //{ + // return owns_lock(); + //} + + mutex_type* mutex() const + { + return pm; + } + +private: + mutex_type* pm; + bool owns; +}; + +template +void swap(unique_lock& x, unique_lock& y) +{ + x.swap(y); +} + +} + +#endif +#endif diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index fe9586f427..ce91aac651 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -55,219 +55,49 @@ void SetCurrentThreadAffinity(u32 mask) SetThreadAffinityMask(GetCurrentThread(), mask); } - CriticalSection::CriticalSection(int spincount) - { - if (spincount) - { - if (!InitializeCriticalSectionAndSpinCount(§ion, spincount)) - ERROR_LOG(COMMON, "CriticalSection could not be initialized!\n%s", GetLastErrorMsg()); - } - else - { - InitializeCriticalSection(§ion); - } - } +// Supporting functions +void SleepCurrentThread(int ms) +{ + Sleep(ms); +} - CriticalSection::~CriticalSection() - { - DeleteCriticalSection(§ion); - } - - void CriticalSection::Enter() - { - EnterCriticalSection(§ion); - } - - bool CriticalSection::TryEnter() - { - return TryEnterCriticalSection(§ion) ? true : false; - } - - void CriticalSection::Leave() - { - LeaveCriticalSection(§ion); - } - - EventEx::EventEx() - { - InterlockedExchange(&m_Lock, 1); - } - - void EventEx::Init() - { - InterlockedExchange(&m_Lock, 1); - } - - void EventEx::Shutdown() - { - InterlockedExchange(&m_Lock, 0); - } - - void EventEx::Set() - { - InterlockedExchange(&m_Lock, 0); - } - - void EventEx::Spin() - { - while (InterlockedCompareExchange(&m_Lock, 1, 0)) - // This only yields when there is a runnable thread on this core - // If not, spin - SwitchToThread(); - } - - void EventEx::Wait() - { - while (InterlockedCompareExchange(&m_Lock, 1, 0)) - // This directly enters Ring0 and enforces a sleep about 15ms - SleepCurrentThread(1); - } - - bool EventEx::MsgWait() - { - while (InterlockedCompareExchange(&m_Lock, 1, 0)) - { - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) return false; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - // This directly enters Ring0 and enforces a sleep about 15ms - SleepCurrentThread(1); - } - return true; - } - - - // Regular same thread loop based waiting - Event::Event() - { - m_hEvent = 0; - } - - void Event::Init() - { - m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - } - - void Event::Shutdown() - { - CloseHandle(m_hEvent); - m_hEvent = 0; - } - - void Event::Set() - { - SetEvent(m_hEvent); - } - - bool Event::Wait(const u32 timeout) - { - return WaitForSingleObject(m_hEvent, timeout) != WAIT_OBJECT_0; - } - - inline HRESULT MsgWaitForSingleObject(HANDLE handle, DWORD timeout) - { - return MsgWaitForMultipleObjects(1, &handle, FALSE, timeout, 0); - } - - void Event::MsgWait() - { - // Adapted from MSDN example http://msdn.microsoft.com/en-us/library/ms687060.aspx - while (true) - { - DWORD result; - MSG msg; - // Read all of the messages in this next loop, - // removing each message as we read it. - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - // If it is a quit message, exit. - if (msg.message == WM_QUIT) - return; - // Otherwise, dispatch the message. - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - // Wait for any message sent or posted to this queue - // or for one of the passed handles be set to signaled. - result = MsgWaitForSingleObject(m_hEvent, THREAD_WAIT_TIMEOUT); - - // The result tells us the type of event we have. - if (result == (WAIT_OBJECT_0 + 1)) - { - // New messages have arrived. - // Continue to the top of the always while loop to - // dispatch them and resume waiting. - continue; - } - else - { - // result == WAIT_OBJECT_0 - // Our event got signaled - return; - } - } - } +void SwitchCurrentThread() +{ + SwitchToThread(); +} - // Supporting functions - void SleepCurrentThread(int ms) - { - Sleep(ms); - } +// Sets the debugger-visible name of the current thread. +// Uses undocumented (actually, it is now documented) trick. +// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp - void SwitchCurrentThread() - { - SwitchToThread(); - } - - typedef struct tagTHREADNAME_INFO +// This is implemented much nicer in upcoming msvc++, see: +// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx +void SetCurrentThreadName(const char* szThreadName) +{ + static const DWORD MS_VC_EXCEPTION = 0x406D1388; + + #pragma pack(push,8) + struct THREADNAME_INFO { DWORD dwType; // must be 0x1000 LPCSTR szName; // pointer to name (in user addr space) DWORD dwThreadID; // thread ID (-1=caller thread) DWORD dwFlags; // reserved for future use, must be zero - } THREADNAME_INFO; - // Usage: SetThreadName (-1, "MainThread"); - // - // Sets the debugger-visible name of the current thread. - // Uses undocumented (actually, it is now documented) trick. - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp - - // This is implemented much nicer in upcoming msvc++, see: - // http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx - void SetCurrentThreadName(const TCHAR* szThreadName) + } info; + #pragma pack(pop) + + info.dwType = 0x1000; + info.szName = szThreadName; + info.dwThreadID = -1; //dwThreadID; + info.dwFlags = 0; + + __try { - THREADNAME_INFO info; - info.dwType = 0x1000; -#ifdef UNICODE - //TODO: Find the proper way to do this. - char tname[256]; - unsigned int i; - - for (i = 0; i < _tcslen(szThreadName); i++) - { - tname[i] = (char)szThreadName[i]; //poor man's unicode->ansi, TODO: fix - } - - tname[i] = 0; - info.szName = tname; -#else - info.szName = szThreadName; -#endif - - info.dwThreadID = -1; //dwThreadID; - info.dwFlags = 0; - __try - { - RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR*)&info); - } - __except(EXCEPTION_CONTINUE_EXECUTION) - {} + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); } + __except(EXCEPTION_CONTINUE_EXECUTION) + {} +} #else // !WIN32, so must be POSIX threads @@ -293,151 +123,42 @@ void SetCurrentThreadAffinity(u32 mask) SetThreadAffinity(pthread_self(), mask); } - static pthread_key_t threadname_key; - static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT; - - CriticalSection::CriticalSection(int spincount_unused) - { - pthread_mutex_init(&mutex, NULL); - } - - - CriticalSection::~CriticalSection() - { - pthread_mutex_destroy(&mutex); - } - - - void CriticalSection::Enter() - { -#ifdef DEBUG - int ret = pthread_mutex_lock(&mutex); - if (ret) ERROR_LOG(COMMON, "%s: pthread_mutex_lock(%p) failed: %s\n", - __FUNCTION__, &mutex, strerror(ret)); -#else - pthread_mutex_lock(&mutex); -#endif - } - - - bool CriticalSection::TryEnter() - { - return(!pthread_mutex_trylock(&mutex)); - } - - - void CriticalSection::Leave() - { -#ifdef DEBUG - int ret = pthread_mutex_unlock(&mutex); - if (ret) ERROR_LOG(COMMON, "%s: pthread_mutex_unlock(%p) failed: %s\n", - __FUNCTION__, &mutex, strerror(ret)); -#else - pthread_mutex_unlock(&mutex); -#endif - } +static pthread_key_t threadname_key; +static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT; - void SleepCurrentThread(int ms) - { - usleep(1000 * ms); - } +void SleepCurrentThread(int ms) +{ + usleep(1000 * ms); +} - void SwitchCurrentThread() - { - usleep(1000 * 1); - } +void SwitchCurrentThread() +{ + usleep(1000 * 1); +} - static void FreeThreadName(void* threadname) - { +static void FreeThreadName(void* threadname) +{ + free(threadname); +} + +static void ThreadnameKeyAlloc() +{ + pthread_key_create(&threadname_key, FreeThreadName); +} + +void SetCurrentThreadName(const char* szThreadName) +{ + pthread_once(&threadname_key_once, ThreadnameKeyAlloc); + + void* threadname; + if ((threadname = pthread_getspecific(threadname_key)) != NULL) free(threadname); - } - static void ThreadnameKeyAlloc() - { - pthread_key_create(&threadname_key, FreeThreadName); - } + pthread_setspecific(threadname_key, strdup(szThreadName)); - void SetCurrentThreadName(const TCHAR* szThreadName) - { - pthread_once(&threadname_key_once, ThreadnameKeyAlloc); + INFO_LOG(COMMON, "%s(%s)\n", __FUNCTION__, szThreadName); +} - void* threadname; - if ((threadname = pthread_getspecific(threadname_key)) != NULL) - free(threadname); - - pthread_setspecific(threadname_key, strdup(szThreadName)); - - INFO_LOG(COMMON, "%s(%s)\n", __FUNCTION__, szThreadName); - } - - - Event::Event() - { - is_set_ = false; - } - - - void Event::Init() - { - pthread_cond_init(&event_, 0); - pthread_mutex_init(&mutex_, 0); - } - - - void Event::Shutdown() - { - pthread_mutex_destroy(&mutex_); - pthread_cond_destroy(&event_); - } - - - void Event::Set() - { - pthread_mutex_lock(&mutex_); - - if (!is_set_) - { - is_set_ = true; - pthread_cond_signal(&event_); - } - - pthread_mutex_unlock(&mutex_); - } - - - bool Event::Wait(const u32 timeout) - { - bool timedout = false; - struct timespec wait; - pthread_mutex_lock(&mutex_); - - if (timeout != INFINITE) - { - memset(&wait, 0, sizeof(wait)); - struct timeval now; - gettimeofday(&now, NULL); - wait.tv_nsec = (now.tv_usec + (timeout % 1000)) * 1000; - wait.tv_sec = now.tv_sec + (timeout / 1000); - } - - while (!is_set_ && !timedout) - { - if (timeout == INFINITE) - { - pthread_cond_wait(&event_, &mutex_); - } - else - { - timedout = pthread_cond_timedwait(&event_, &mutex_, &wait) == ETIMEDOUT; - } - } - - is_set_ = false; - pthread_mutex_unlock(&mutex_); - - return timedout; - } - #endif } // namespace Common diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index 33ab20fe36..244a8dd2f0 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -19,6 +19,8 @@ #define _THREAD_H_ #include "StdThread.h" +#include "StdMutex.h" +#include "StdConditionVariable.h" // Don't include common.h here as it will break LogManager #include "CommonTypes.h" @@ -38,7 +40,6 @@ #include #endif - namespace Common { @@ -47,105 +48,70 @@ int CurrentThreadId(); void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); void SetCurrentThreadAffinity(u32 mask); - class CriticalSection +class Event +{ +public: + void Set() { -#ifdef _WIN32 - CRITICAL_SECTION section; -#else -#ifdef _POSIX_THREADS - pthread_mutex_t mutex; -#endif -#endif - public: - - CriticalSection(int spincount = 1000); - ~CriticalSection(); - void Enter(); - bool TryEnter(); - void Leave(); - }; - -#ifdef _WIN32 - // Event(WaitForSingleObject) is too expensive - // as it always enters Ring0 regardless of the state of lock - // This EventEx will try to stay in Ring3 as much as possible - // If the lock can be obtained in the first time, Ring0 won't be entered at all - class EventEx - { - public: - EventEx(); - void Init(); - void Shutdown(); - void Set(); - // Infinite wait - void Spin(); - // Infinite wait with sleep - void Wait(); - // Wait with message processing and sleep - bool MsgWait(); - private: - volatile long m_Lock; - }; -#else - // TODO: implement for Linux -#define EventEx Event -#endif - - class Event - { - public: - Event(); - void Init(); - void Shutdown(); - - void Set(); - //returns whether the wait timed out - bool Wait(const u32 timeout = INFINITE); -#ifdef _WIN32 - void MsgWait(); -#else - void MsgWait() {Wait();} -#endif - - - private: -#ifdef _WIN32 - - HANDLE m_hEvent; - /* If we have waited more than five seconds we can be pretty sure that the thread is deadlocked. - So then we can just as well continue and hope for the best. I could try several times that - this works after a five second timeout (with works meaning that the game stopped and I could - start another game without any noticable problems). But several times it failed to, and ended - with a crash. But it's better than an infinite deadlock. */ - static const int THREAD_WAIT_TIMEOUT = 5000; // INFINITE or 5000 for example - -#else - - bool is_set_; -#ifdef _POSIX_THREADS - pthread_cond_t event_; - pthread_mutex_t mutex_; -#endif - -#endif - }; - - void SleepCurrentThread(int ms); - void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms - - // Use this function during a spin-wait to make the current thread - // relax while another thread is working. This may be more efficient - // than using events because event functions use kernel calls. - inline void YieldCPU() - { -#ifdef _WIN32 - Sleep(0); -#elif defined(_M_IX86) || defined(_M_X64) - sleep(0); -#endif + m_condvar.notify_one(); } - void SetCurrentThreadName(const char *name); + void Wait() + { + std::unique_lock lk(m_mutex); + m_condvar.wait(lk); + } + +private: + std::condition_variable m_condvar; + std::mutex m_mutex; +}; + +// TODO: doesn't work on windows with (count > 2) +class Barrier +{ +public: + Barrier(size_t count) + : m_count(count), m_waiting(0) + {} + + // block until "count" threads call Wait() + bool Wait() + { + std::unique_lock lk(m_mutex); + + if (m_count == ++m_waiting) + { + m_waiting = 0; + m_condvar.notify_all(); + return true; + } + else + { + m_condvar.wait(lk); + return false; + } + } + +private: + std::condition_variable m_condvar; + std::mutex m_mutex; + const size_t m_count; + volatile size_t m_waiting; +}; + +void SleepCurrentThread(int ms); +void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms + +// Use this function during a spin-wait to make the current thread +// relax while another thread is working. This may be more efficient +// than using events because event functions use kernel calls. +inline void YieldCPU() +{ + std::this_thread::yield(); +} + +void SetCurrentThreadName(const char *name); } // namespace Common diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 8bd7616857..49493240a4 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -102,8 +102,8 @@ static std::thread cpuThread; SCoreStartupParameter g_CoreStartupParameter; // This event is set when the emuthread starts. -Common::Event emuThreadGoing; -Common::Event cpuRunloopQuit; +Common::Barrier emuThreadGoing(2); +Common::Barrier cpuRunloopQuit(2); std::string GetStateFileName() { return g_stateFileName; } void SetStateFileName(std::string val) { g_stateFileName = val; } @@ -248,14 +248,11 @@ bool Init() // The hardware is initialized. g_bHwInit = true; - emuThreadGoing.Init(); - // Start the emu thread g_EmuThread = std::thread(EmuThread); // Wait until the emu thread is running - emuThreadGoing.MsgWait(); - emuThreadGoing.Shutdown(); + emuThreadGoing.Wait(); Host_SetWaitCursor(false); @@ -359,7 +356,7 @@ void CpuThread() // Enter CPU run loop. When we leave it - we are done. CCPU::Run(); - cpuRunloopQuit.Set(); + cpuRunloopQuit.Wait(); return; } @@ -372,8 +369,6 @@ void EmuThread() const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; - cpuRunloopQuit.Init(); - Common::SetCurrentThreadName("Emuthread - starting"); if (_CoreParameter.bLockThreads) @@ -384,7 +379,7 @@ void EmuThread() Common::SetCurrentThreadAffinity(2); } - emuThreadGoing.Set(); + emuThreadGoing.Wait(); DisplayMessage("CPU: " + cpu_info.Summarize(), 8000); DisplayMessage(_CoreParameter.m_strFilename, 3000); @@ -462,7 +457,6 @@ void EmuThread() VolumeHandler::EjectVolume(); FileMon::Close(); - cpuRunloopQuit.Shutdown(); g_bStopping = false; } diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index 1bed6fbb22..8095b56bde 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -68,7 +68,7 @@ u64 fakeDecStartTicks; u64 fakeTBStartValue; u64 fakeTBStartTicks; -static Common::CriticalSection externalEventSection; +static std::mutex externalEventSection; void (*advanceCallback)(int cyclesExecuted) = NULL; @@ -143,19 +143,18 @@ void Shutdown() delete ev; } - externalEventSection.Enter(); + std::lock_guard lk(externalEventSection); while(eventTsPool) { Event *ev = eventTsPool; eventTsPool = ev->next; delete ev; } - externalEventSection.Leave(); } void DoState(PointerWrap &p) { - externalEventSection.Enter(); + std::lock_guard lk(externalEventSection); p.Do(downcount); p.Do(slicelength); p.Do(globalTimer); @@ -210,7 +209,6 @@ void DoState(PointerWrap &p) break; } } - externalEventSection.Leave(); } u64 GetTicks() @@ -227,7 +225,7 @@ u64 GetIdleTicks() // schedule things to be executed on the main thread. void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata) { - externalEventSection.Enter(); + std::lock_guard lk(externalEventSection); Event *ne = GetNewTsEvent(); ne->time = globalTimer + cyclesIntoFuture; ne->type = event_type; @@ -238,7 +236,6 @@ void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata if(tsLast) tsLast->next = ne; tsLast = ne; - externalEventSection.Leave(); } // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread @@ -247,9 +244,8 @@ void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata) { if(Core::IsCPUThread()) { - externalEventSection.Enter(); + std::lock_guard lk(externalEventSection); event_types[event_type].callback(userdata, 0); - externalEventSection.Leave(); } else ScheduleEvent_Threadsafe(0, event_type, userdata); @@ -352,10 +348,9 @@ void RemoveEvent(int event_type) void RemoveThreadsafeEvent(int event_type) { - externalEventSection.Enter(); + std::lock_guard lk(externalEventSection); if (!tsFirst) { - externalEventSection.Leave(); return; } while(tsFirst) @@ -373,7 +368,6 @@ void RemoveThreadsafeEvent(int event_type) } if (!tsFirst) { - externalEventSection.Leave(); return; } Event *prev = tsFirst; @@ -392,7 +386,6 @@ void RemoveThreadsafeEvent(int event_type) ptr = ptr->next; } } - externalEventSection.Leave(); } void RemoveAllEvents(int event_type) @@ -438,8 +431,7 @@ void ProcessFifoWaitEvents() void MoveEvents() { - - externalEventSection.Enter(); + std::lock_guard lk(externalEventSection); // Move events from async queue into main queue while (tsFirst) { @@ -458,8 +450,6 @@ void MoveEvents() eventTsPool = ev; allocatedTsEvents--; } - externalEventSection.Leave(); - } void Advance() diff --git a/Source/Core/Core/Src/DSP/DSPCore.cpp b/Source/Core/Core/Src/DSP/DSPCore.cpp index 07290c54cb..a5c4fa32f8 100644 --- a/Source/Core/Core/Src/DSP/DSPCore.cpp +++ b/Source/Core/Core/Src/DSP/DSPCore.cpp @@ -41,7 +41,7 @@ DSPCoreState core_state = DSPCORE_STOP; u16 cyclesLeft = 0; DSPEmitter *dspjit = NULL; Common::Event step_event; -Common::CriticalSection ExtIntCriticalSection; +static std::mutex ExtIntCriticalSection; static bool LoadRom(const char *fname, int size_in_words, u16 *rom) { @@ -165,8 +165,6 @@ bool DSPCore_Init(const char *irom_filename, const char *coef_filename, DSPAnalyzer::Analyze(); - step_event.Init(); - core_state = DSPCORE_RUNNING; return true; @@ -183,7 +181,6 @@ void DSPCore_Shutdown() delete dspjit; dspjit = NULL; } - step_event.Shutdown(); DSPCore_FreeMemoryPages(); } @@ -206,9 +203,8 @@ void DSPCore_SetException(u8 level) // Notify that an external interrupt is pending (used by thread mode) void DSPCore_SetExternalInterrupt(bool val) { - ExtIntCriticalSection.Enter(); + std::lock_guard lk(ExtIntCriticalSection); g_dsp.external_interrupt_waiting = val; - ExtIntCriticalSection.Leave(); } // Coming from the CPU diff --git a/Source/Core/Core/Src/DSP/DSPCore.h b/Source/Core/Core/Src/DSP/DSPCore.h index ed3d33e583..a2446cbe55 100644 --- a/Source/Core/Core/Src/DSP/DSPCore.h +++ b/Source/Core/Core/Src/DSP/DSPCore.h @@ -249,7 +249,7 @@ struct SDSP volatile u16 mbox[2][2]; // Mutex protecting the mailbox. - Common::CriticalSection g_CriticalSection; + std::mutex g_CriticalSection; // Accelerator / DMA / other hardware registers. Not GPRs. u16 ifx_regs[256]; diff --git a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp index 91b0b2efe9..f3106df45c 100644 --- a/Source/Core/Core/Src/DSP/DSPHWInterface.cpp +++ b/Source/Core/Core/Src/DSP/DSPHWInterface.cpp @@ -41,7 +41,7 @@ static void gdsp_do_dma(); -Common::CriticalSection g_CriticalSection; +static std::mutex g_CriticalSection; void gdsp_ifx_init() { @@ -56,35 +56,34 @@ void gdsp_ifx_init() g_dsp.mbox[1][1] = 0; } - u32 gdsp_mbox_peek(u8 mbx) { + std::unique_lock lk(g_CriticalSection, std::defer_lock); if (DSPHost_OnThread()) - g_CriticalSection.Enter(); - u32 value = ((g_dsp.mbox[mbx][0] << 16) | g_dsp.mbox[mbx][1]); - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); - return value; + lk.lock(); + + return ((g_dsp.mbox[mbx][0] << 16) | g_dsp.mbox[mbx][1]); } void gdsp_mbox_write_h(u8 mbx, u16 val) { + std::unique_lock lk(g_CriticalSection, std::defer_lock); if (DSPHost_OnThread()) - g_CriticalSection.Enter(); - g_dsp.mbox[mbx][0] = val & 0x7fff; - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); -} + lk.lock(); + g_dsp.mbox[mbx][0] = val & 0x7fff; +} void gdsp_mbox_write_l(u8 mbx, u16 val) { + { + std::unique_lock lk(g_CriticalSection, std::defer_lock); if (DSPHost_OnThread()) - g_CriticalSection.Enter(); + lk.lock(); + g_dsp.mbox[mbx][1] = val; g_dsp.mbox[mbx][0] |= 0x8000; - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); + } #if defined(_DEBUG) || defined(DEBUGFAST) if (mbx == GDSP_MBOX_DSP) @@ -96,29 +95,27 @@ void gdsp_mbox_write_l(u8 mbx, u16 val) #endif } - u16 gdsp_mbox_read_h(u8 mbx) { + std::unique_lock lk(g_CriticalSection, std::defer_lock); if (DSPHost_OnThread()) - g_CriticalSection.Enter(); - u16 val = g_dsp.mbox[mbx][0]; // TODO: mask away the top bit? - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); - return val; + lk.lock(); + + return g_dsp.mbox[mbx][0]; // TODO: mask away the top bit? } u16 gdsp_mbox_read_l(u8 mbx) { + u16 val; + { + std::unique_lock lk(g_CriticalSection, std::defer_lock); if (DSPHost_OnThread()) - g_CriticalSection.Enter(); + lk.lock(); - u16 val = g_dsp.mbox[mbx][1]; + val = g_dsp.mbox[mbx][1]; g_dsp.mbox[mbx][0] &= ~0x8000; - - - if (DSPHost_OnThread()) - g_CriticalSection.Leave(); + } #if defined(_DEBUG) || defined(DEBUGFAST) if (mbx == GDSP_MBOX_DSP) @@ -132,7 +129,6 @@ u16 gdsp_mbox_read_l(u8 mbx) return val; } - void gdsp_ifx_write(u32 addr, u32 val) { switch (addr & 0xff) diff --git a/Source/Core/Core/Src/GeckoCode.cpp b/Source/Core/Core/Src/GeckoCode.cpp index 95a1027afa..6c348eb0ff 100644 --- a/Source/Core/Core/Src/GeckoCode.cpp +++ b/Source/Core/Core/Src/GeckoCode.cpp @@ -55,7 +55,7 @@ u32 GeckoCode::Code::GetAddress() const return gcaddress + (use_po ? pointer_address : (base_address & 0xFE000000)); } -static Common::CriticalSection active_codes_lock; +static std::mutex active_codes_lock; // currently running code static GeckoCode::Code *codes_start = NULL, *current_code = NULL; @@ -78,7 +78,7 @@ bool MathOperation(u32& ret, const u32 left, const u32 right, const u8 type); void SetActiveCodes(const std::vector& gcodes) { - active_codes_lock.Enter(); + std::lock_guard lk(active_codes_lock); active_codes.clear(); // add enabled codes @@ -94,8 +94,6 @@ void SetActiveCodes(const std::vector& gcodes) } inserted_asm_codes.clear(); - - active_codes_lock.Leave(); } bool RunGeckoCode(GeckoCode& gecko_code) @@ -151,24 +149,23 @@ bool RunGeckoCode(GeckoCode& gecko_code) bool RunActiveCodes() { - if (false == SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) - return true; - if (false == active_codes_lock.TryEnter()) - return true; - - std::vector::iterator - gcodes_iter = active_codes.begin(), - gcodes_end = active_codes.end(); - for (; gcodes_iter!=gcodes_end; ++gcodes_iter) + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) { - if (gcodes_iter->enabled) - RunGeckoCode(*gcodes_iter); - // we don't need to stop all codes if one fails, maybe - //if (false == RunGeckoCode(*gcodes_iter)) - //return false; + std::lock_guard lk(active_codes_lock); + + std::vector::iterator + gcodes_iter = active_codes.begin(), + gcodes_end = active_codes.end(); + for (; gcodes_iter!=gcodes_end; ++gcodes_iter) + { + if (gcodes_iter->enabled) + RunGeckoCode(*gcodes_iter); + // we don't need to stop all codes if one fails, maybe + //if (false == RunGeckoCode(*gcodes_iter)) + //return false; + } } - active_codes_lock.Leave(); return true; } diff --git a/Source/Core/Core/Src/HW/CPU.cpp b/Source/Core/Core/Src/HW/CPU.cpp index 1b10bdd766..69b5055c9f 100644 --- a/Source/Core/Core/Src/HW/CPU.cpp +++ b/Source/Core/Core/Src/HW/CPU.cpp @@ -35,7 +35,6 @@ namespace void CCPU::Init(int cpu_core) { - m_StepEvent.Init(); PowerPC::Init(cpu_core); m_SyncEvent = 0; } @@ -43,7 +42,6 @@ void CCPU::Init(int cpu_core) void CCPU::Shutdown() { PowerPC::Shutdown(); - m_StepEvent.Shutdown(); m_SyncEvent = 0; } diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp index 0cd3ec652e..913de7107b 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda.cpp @@ -570,7 +570,7 @@ void CUCode_Zelda::ExecuteList() void CUCode_Zelda::DoState(PointerWrap &p) { // It's bad if we try to save during Mix() - m_csMix.Enter(); + std::lock_guard lk(m_csMix); p.Do(m_CRC); @@ -618,6 +618,4 @@ void CUCode_Zelda::DoState(PointerWrap &p) p.Do(m_UploadSetupInProgress); m_rMailHandler.DoState(p); - - m_csMix.Leave(); } diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp index 11f04d96c7..a3e787cd8c 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_Zelda_Voice.cpp @@ -746,7 +746,7 @@ ContinueWithBlock: // size is in stereo samples. void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) { - m_csMix.Enter(); + std::lock_guard lk(m_csMix); // Safety check if (_Size > 256 * 1024 - 8) _Size = 256 * 1024 - 8; @@ -793,5 +793,4 @@ void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) _Buffer += 2; } - m_csMix.Leave(); } diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h index 8b0772a26a..5b322e861b 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCodes.h @@ -86,7 +86,7 @@ protected: bool NeedsResumeMail(); CMailHandler& m_rMailHandler; - Common::CriticalSection m_csMix; + std::mutex m_csMix; enum EDSP_Codes { diff --git a/Source/Core/Core/Src/HW/DVDInterface.cpp b/Source/Core/Core/Src/HW/DVDInterface.cpp index 098c950470..c9594b13bd 100644 --- a/Source/Core/Core/Src/HW/DVDInterface.cpp +++ b/Source/Core/Core/Src/HW/DVDInterface.cpp @@ -215,7 +215,7 @@ static unsigned char media_buffer[0x40]; // Needed because data and streaming audio access needs to be managed by the "drive" // (both requests can happen at the same time, audio takes precedence) -Common::CriticalSection dvdread_section; +static std::mutex dvdread_section; static int ejectDisc; static int insertDisc; @@ -345,10 +345,8 @@ void ClearCoverInterrupt() bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength) { // We won't need the crit sec when DTK streaming has been rewritten correctly. - dvdread_section.Enter(); - bool retval = VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength); - dvdread_section.Leave(); - return retval; + std::lock_guard lk(dvdread_section); + return VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength); } bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples) @@ -360,9 +358,10 @@ bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples) return false; } _iNumSamples &= ~31; - dvdread_section.Enter(); + { + std::lock_guard lk(dvdread_section); VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples); - dvdread_section.Leave(); + } // // FIX THIS diff --git a/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp b/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp index 5b04e040f4..93b7cd5d09 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp @@ -26,7 +26,7 @@ int GeckoSockServer::client_count; std::thread GeckoSockServer::connectionThread; volatile bool GeckoSockServer::server_running; std::queue GeckoSockServer::waiting_socks; -Common::CriticalSection GeckoSockServer::connection_lock; +std::mutex GeckoSockServer::connection_lock; GeckoSockServer::GeckoSockServer() : client_running(false) @@ -76,9 +76,8 @@ void GeckoSockServer::GeckoConnectionWaiter() { if (server.Accept(new_client) == sf::Socket::Done) { - connection_lock.Enter(); + std::lock_guard lk(connection_lock); waiting_socks.push(new_client); - connection_lock.Leave(); } SLEEP(1); } @@ -89,7 +88,8 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill) { bool sock_filled = false; - connection_lock.Enter(); + std::lock_guard lk(connection_lock); + if (waiting_socks.size()) { sock_to_fill = waiting_socks.front(); @@ -106,7 +106,6 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill) waiting_socks.pop(); sock_filled = true; } - connection_lock.Leave(); return sock_filled; } @@ -123,8 +122,10 @@ void GeckoSockServer::ClientThread() { u8 data; std::size_t got = 0; + + { + std::lock_guard lk(transfer_lock); - transfer_lock.Enter(); if (client.Receive((char*)&data, sizeof(data), got) == sf::Socket::Disconnected) client_running = false; @@ -138,7 +139,8 @@ void GeckoSockServer::ClientThread() client_running = false; send_fifo.pop(); } - transfer_lock.Leave(); + } // unlock transfer + SLEEP(1); } @@ -173,35 +175,40 @@ void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize) // PC -> Gecko // |= 0x08000000 if successful case CMD_RECV: - transfer_lock.Enter(); + { + std::lock_guard lk(transfer_lock); if (!recv_fifo.empty()) { _uData = 0x08000000 | (recv_fifo.front() << 16); recv_fifo.pop(); } - transfer_lock.Leave(); break; + } + // Gecko -> PC // |= 0x04000000 if successful case CMD_SEND: - transfer_lock.Enter(); + { + std::lock_guard lk(transfer_lock); send_fifo.push(_uData >> 20); - transfer_lock.Leave(); _uData = 0x04000000; break; + } // Check if ok for Gecko -> PC, or FIFO full // |= 0x04000000 if FIFO is not full case CMD_CHK_TX: _uData = 0x04000000; break; + // Check if data in FIFO for PC -> Gecko, or FIFO empty // |= 0x04000000 if data in recv FIFO case CMD_CHK_RX: - transfer_lock.Enter(); + { + std::lock_guard lk(transfer_lock); _uData = recv_fifo.empty() ? 0 : 0x04000000; - transfer_lock.Leave(); break; + } default: ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData); diff --git a/Source/Core/Core/Src/HW/EXI_DeviceGecko.h b/Source/Core/Core/Src/HW/EXI_DeviceGecko.h index af4642b83d..9b427e21c8 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceGecko.h +++ b/Source/Core/Core/Src/HW/EXI_DeviceGecko.h @@ -34,7 +34,7 @@ public: sf::SocketTCP client; void ClientThread(); std::thread clientThread; - Common::CriticalSection transfer_lock; + std::mutex transfer_lock; std::queue send_fifo; std::queue recv_fifo; @@ -50,7 +50,7 @@ private: static volatile bool server_running; static std::thread connectionThread; static std::queue waiting_socks; - static Common::CriticalSection connection_lock; + static std::mutex connection_lock; }; class CEXIGecko diff --git a/Source/Core/Core/Src/HW/GCPad.cpp b/Source/Core/Core/Src/HW/GCPad.cpp index 3135caf644..82bf4bc9b4 100644 --- a/Source/Core/Core/Src/HW/GCPad.cpp +++ b/Source/Core/Core/Src/HW/GCPad.cpp @@ -65,8 +65,9 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) // wtf is this? _pPADStatus->button = PAD_USE_ORIGIN; - // try lock - if (false == g_plugin.controls_crit.TryEnter()) + std::unique_lock lk(g_plugin.controls_lock, std::try_to_lock); + + if (!lk.owns_lock()) { // if gui has lock (messing with controls), skip this input cycle // center axes and return @@ -86,9 +87,6 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) // get input ((GCPad*)g_plugin.controllers[_numPAD])->GetInput(_pPADStatus); - - // leave - g_plugin.controls_crit.Leave(); } // __________________________________________________________________________________________________ @@ -99,15 +97,13 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus) // void Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength) { - // enter - if ( g_plugin.controls_crit.TryEnter() ) + std::unique_lock lk(g_plugin.controls_lock, std::try_to_lock); + + if (!lk.owns_lock()) { // TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time // set rumble ((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( 1 == _uType && _uStrength > 2 ); - - // leave - g_plugin.controls_crit.Leave(); } } diff --git a/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp b/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp index 1940be4bdb..57e99f6372 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp +++ b/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp @@ -24,7 +24,7 @@ static std::thread connectionThread; static std::queue waiting_socks; -static Common::CriticalSection cs_gba; +static std::mutex cs_gba; namespace { volatile bool server_running; } // --- GameBoy Advance "Link Cable" --- @@ -47,9 +47,8 @@ void GBAConnectionWaiter() { if (server.Accept(new_client) == sf::Socket::Done) { - cs_gba.Enter(); + std::lock_guard lk(cs_gba); waiting_socks.push(new_client); - cs_gba.Leave(); } SLEEP(1); } @@ -68,14 +67,14 @@ bool GetAvailableSock(sf::SocketTCP& sock_to_fill) { bool sock_filled = false; - cs_gba.Enter(); + std::lock_guard lk(cs_gba); + if (waiting_socks.size()) { sock_to_fill = waiting_socks.front(); waiting_socks.pop(); sock_filled = true; } - cs_gba.Leave(); return sock_filled; } diff --git a/Source/Core/Core/Src/HW/Wiimote.cpp b/Source/Core/Core/Src/HW/Wiimote.cpp index 0712196327..ca005eb8ea 100644 --- a/Source/Core/Core/Src/HW/Wiimote.cpp +++ b/Source/Core/Core/Src/HW/Wiimote.cpp @@ -93,8 +93,8 @@ void Update(int _number) { //PanicAlert( "Wiimote_Update" ); - // TODO: change this to a TryEnter, and make it give empty input on failure - g_plugin.controls_crit.Enter(); + // TODO: change this to a try_to_lock, and make it give empty input on failure + std::lock_guard lk(g_plugin.controls_lock); static int _last_number = 4; if (_number <= _last_number) @@ -108,8 +108,6 @@ void Update(int _number) ((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update(); else WiimoteReal::Update(_number); - - g_plugin.controls_crit.Leave(); } // __________________________________________________________________________________________________ diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index 319da3d5f5..6b6519d7b2 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -248,14 +248,14 @@ void Wiimote::RequestStatus(const wm_request_status* const rs) { using namespace WiimoteReal; - g_refresh_critsec.Enter(); + std::lock_guard lk(g_refresh_lock); + if (g_wiimotes[m_index]) { wm_request_status rpt; rpt.rumble = 0; g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); } - g_refresh_critsec.Leave(); return; } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index 0944ea9639..d7792727f0 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -661,7 +661,7 @@ void Wiimote::Update() { using namespace WiimoteReal; - g_refresh_critsec.Enter(); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[m_index]) { Report rpt = g_wiimotes[m_index]->ProcessReadQueue(); @@ -736,7 +736,6 @@ void Wiimote::Update() delete[] real_data; } } - g_refresh_critsec.Leave(); } if (Frame::IsRecordingInput()) { diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index 15621abce5..0793900900 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -35,7 +35,7 @@ namespace WiimoteReal bool g_real_wiimotes_initialized = false; unsigned int g_wiimotes_found = 0; -Common::CriticalSection g_refresh_critsec; +std::mutex g_refresh_lock; Wiimote *g_wiimotes[MAX_WIIMOTES]; @@ -439,11 +439,11 @@ void Shutdown(void) // This is called from the GUI thread void Refresh() { + std::lock_guard lk(g_refresh_lock); + #ifdef _WIN32 - g_refresh_critsec.Enter(); Shutdown(); Initialize(); - g_refresh_critsec.Leave(); #else // Make sure real wiimotes have been initialized if (!g_real_wiimotes_initialized) @@ -458,8 +458,6 @@ void Refresh() if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) ++wanted_wiimotes; - g_refresh_critsec.Enter(); - // Remove wiimotes that are paired with slots no longer configured for a // real wiimote or that are disconnected for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) @@ -486,50 +484,40 @@ void Refresh() g_wiimotes_found = num_wiimotes; } - - g_refresh_critsec.Leave(); #endif } void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - g_refresh_critsec.Enter(); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size); - - g_refresh_critsec.Leave(); } void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) { - g_refresh_critsec.Enter(); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size); - - g_refresh_critsec.Leave(); } // Read the Wiimote once void Update(int _WiimoteNumber) { - g_refresh_critsec.Enter(); + std::lock_guard lk(g_refresh_lock); if (g_wiimotes[_WiimoteNumber]) g_wiimotes[_WiimoteNumber]->Update(); - - g_refresh_critsec.Leave(); } void StateChange(EMUSTATE_CHANGE newState) { - //g_refresh_critsec.Enter(); // enter + //std::lock_guard lk(g_refresh_lock); // TODO: disable/enable auto reporting, maybe - - //g_refresh_critsec.Leave(); // leave } }; // end of namespace diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index 1ab6edb78d..f3c5b884f8 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -101,7 +101,7 @@ private: Common::FifoQueue m_audio_reports; }; -extern Common::CriticalSection g_refresh_critsec; +extern std::mutex g_refresh_lock; extern Wiimote *g_wiimotes[4]; void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); diff --git a/Source/Core/Core/Src/NetPlay.cpp b/Source/Core/Core/Src/NetPlay.cpp index 650adc34d5..1c19f763ec 100644 --- a/Source/Core/Core/Src/NetPlay.cpp +++ b/Source/Core/Core/Src/NetPlay.cpp @@ -27,7 +27,7 @@ // for wiimote/ OSD messages #include "Core.h" -Common::CriticalSection crit_netplay_ptr; +std::mutex crit_netplay_ptr; static NetPlay* netplay_ptr = NULL; #define RPT_SIZE_HACK (1 << 16) @@ -42,20 +42,20 @@ NetPlay::NetPlay(NetPlayUI* dialog) void NetPlay_Enable(NetPlay* const np) { - CritLocker crit(crit_netplay_ptr); // probably safe without a lock + std::lock_guard lk(crit_netplay_ptr); netplay_ptr = np; } void NetPlay_Disable() { - CritLocker crit(crit_netplay_ptr); + std::lock_guard lk(crit_netplay_ptr); netplay_ptr = NULL; } // called from ---GUI--- thread NetPlay::~NetPlay() { - CritLocker crit(crit_netplay_ptr); + std::lock_guard lk(crit_netplay_ptr); netplay_ptr = NULL; // not perfect @@ -116,7 +116,8 @@ void NetPlay::ClearBuffers() // called from ---CPU--- thread bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues) { - m_crit.players.Enter(); // lock players + { + std::lock_guard lkp(m_crit.players); // in game mapping for this local pad unsigned int in_game_num = m_local_player->pad_map[pad_nb]; @@ -138,7 +139,7 @@ bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, Ne } } - m_crit.players.Leave(); + } // unlock players //Common::Timer bufftimer; //bufftimer.Start(); @@ -181,14 +182,13 @@ void NetPlay::WiimoteInput(int _number, u16 _channelID, const void* _pData, u32 m_wiimote_input[_number].back().assign((char*)_pData, (char*)_pData + _Size); m_wiimote_input[_number].back().channel = _channelID; } - - m_crit.players.Leave(); } // called from ---CPU--- thread void NetPlay::WiimoteUpdate(int _number) { - m_crit.players.Enter(); // lock players + { + std::lock_guard lkp(m_crit.players); // in game mapping for this local wiimote unsigned int in_game_num = m_local_player->pad_map[_number]; // just using gc pad_map for now @@ -203,7 +203,7 @@ void NetPlay::WiimoteUpdate(int _number) m_wiimote_input[_number].clear(); } - m_crit.players.Leave(); + } // unlock players if (0 == m_wiimote_buffer[_number].Size()) { @@ -251,7 +251,7 @@ bool NetPlay::StartGame(const std::string &path) // called from ---GUI--- thread and ---NETPLAY--- thread (client side) bool NetPlay::StopGame() { - CritLocker game_lock(m_crit.game); // lock game state + std::lock_guard lkg(m_crit.game); if (false == m_is_running) { @@ -288,7 +288,7 @@ u8 NetPlay::GetPadNum(u8 numPAD) // Actual Core function which is called on every frame bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus) { - CritLocker crit(crit_netplay_ptr); + std::lock_guard lk(crit_netplay_ptr); if (netplay_ptr) return netplay_ptr->GetNetPads(numPAD, &PadStatus, (NetPad*)PADStatus); @@ -300,7 +300,7 @@ bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u // so all players' games get the same time u32 CEXIIPL::NetPlay_GetGCTime() { - CritLocker crit(crit_netplay_ptr); + std::lock_guard lk(crit_netplay_ptr); if (netplay_ptr) return 1272737767; // watev @@ -312,7 +312,7 @@ u32 CEXIIPL::NetPlay_GetGCTime() // return the local pad num that should rumble given a ingame pad num u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD) { - CritLocker crit(crit_netplay_ptr); + std::lock_guard lk(crit_netplay_ptr); if (netplay_ptr) return netplay_ptr->GetPadNum(numPAD); @@ -348,7 +348,7 @@ int CWII_IPC_HLE_WiiMote::NetPlay_GetWiimoteNum(int _number) //bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int _number, u16 _channelID, const void* _pData, u32& _Size) bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&) { - CritLocker crit(crit_netplay_ptr); + std::lock_guard lk(crit_netplay_ptr); if (netplay_ptr) //{ diff --git a/Source/Core/Core/Src/NetPlay.h b/Source/Core/Core/Src/NetPlay.h index 068efb12a5..e77f972785 100644 --- a/Source/Core/Core/Src/NetPlay.h +++ b/Source/Core/Core/Src/NetPlay.h @@ -75,19 +75,6 @@ enum CON_ERR_VERSION_MISMATCH }; -// something like this should be in Common stuff -class CritLocker -{ -public: - //CritLocker(const CritLocker&); - CritLocker& operator=(const CritLocker&); - CritLocker(Common::CriticalSection& crit) : m_crit(crit) { m_crit.Enter(); } - ~CritLocker() { m_crit.Leave(); } - -private: - Common::CriticalSection& m_crit; -}; - class NetPlayUI { public: @@ -135,9 +122,9 @@ protected: struct { - Common::CriticalSection game; + std::recursive_mutex game; // lock order - Common::CriticalSection players, send; + std::recursive_mutex players, send; } m_crit; class Player diff --git a/Source/Core/Core/Src/NetPlayClient.cpp b/Source/Core/Core/Src/NetPlayClient.cpp index 5c767effd4..ef1edeeb7f 100644 --- a/Source/Core/Core/Src/NetPlayClient.cpp +++ b/Source/Core/Core/Src/NetPlayClient.cpp @@ -93,9 +93,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) packet >> player.name; packet >> player.revision; - m_crit.players.Enter(); // lock players + { + std::lock_guard lkp(m_crit.players); m_players[player.pid] = player; - m_crit.players.Leave(); + } m_dialog->Update(); } @@ -106,9 +107,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) PlayerId pid; packet >> pid; - m_crit.players.Enter(); // lock players + { + std::lock_guard lkp(m_crit.players); m_players.erase(m_players.find(pid)); - m_crit.players.Leave(); + } m_dialog->Update(); } @@ -137,12 +139,13 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) PlayerId pid; packet >> pid; - m_crit.players.Enter(); // lock players + { + std::lock_guard lkp(m_crit.players); Player& player = m_players[pid]; for (unsigned int i=0; i<4; ++i) packet >> player.pad_map[i]; - m_crit.players.Leave(); + } m_dialog->Update(); } @@ -171,10 +174,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) case NP_MSG_CHANGE_GAME : { - // lock here? - m_crit.game.Enter(); // lock game state + { + std::lock_guard lkg(m_crit.game); packet >> m_selected_game; - m_crit.game.Leave(); + } // update gui m_dialog->OnMsgChangeGame(m_selected_game); @@ -183,9 +186,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) case NP_MSG_START_GAME : { - m_crit.game.Enter(); // lock buffer + { + std::lock_guard lkg(m_crit.game); packet >> m_current_game; - m_crit.game.Leave(); + } m_dialog->OnMsgStartGame(); } @@ -200,7 +204,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) case NP_MSG_DISABLE_GAME : { PanicAlertT("Other client disconnected while game is running!! NetPlay is disabled. You manually stop the game."); - CritLocker game_lock(m_crit.game); // lock game state + std::lock_guard lkg(m_crit.game); m_is_running = false; NetPlay_Disable(); } @@ -215,7 +219,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet) spac << (MessageId)NP_MSG_PONG; spac << ping_key; - CritLocker send_lock(m_crit.send); + std::lock_guard lks(m_crit.send); m_socket.Send(spac); } break; @@ -263,7 +267,7 @@ void NetPlayClient::ThreadFunc() // called from ---GUI--- thread void NetPlayClient::GetPlayerList(std::string& list, std::vector& pid_list) { - CritLocker player_lock(m_crit.players); // lock players + std::lock_guard lkp(m_crit.players); std::ostringstream ss; @@ -287,7 +291,7 @@ void NetPlayClient::SendChatMessage(const std::string& msg) spac << (MessageId)NP_MSG_CHAT_MESSAGE; spac << msg; - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lks(m_crit.send); m_socket.Send(spac); } @@ -300,14 +304,14 @@ void NetPlayClient::SendPadState(const PadMapping local_nb, const NetPad& np) spac << local_nb; // local pad num spac << np.nHi << np.nLo; - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lks(m_crit.send); m_socket.Send(spac); } // called from ---GUI--- thread bool NetPlayClient::StartGame(const std::string &path) { - CritLocker game_lock(m_crit.game); // lock game state + std::lock_guard lkg(m_crit.game); if (false == NetPlay::StartGame(path)) return false; @@ -317,7 +321,7 @@ bool NetPlayClient::StartGame(const std::string &path) spac << (MessageId)NP_MSG_START_GAME; spac << m_current_game; - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lks(m_crit.send); m_socket.Send(spac); return true; diff --git a/Source/Core/Core/Src/NetPlayServer.cpp b/Source/Core/Core/Src/NetPlayServer.cpp index 9e5e852ef5..61a61d00ae 100644 --- a/Source/Core/Core/Src/NetPlayServer.cpp +++ b/Source/Core/Core/Src/NetPlayServer.cpp @@ -60,8 +60,7 @@ void NetPlayServer::ThreadFunc() spac << (MessageId)NP_MSG_PING; spac << m_ping_key; - //CritLocker player_lock(m_crit.players); - CritLocker send_lock(m_crit.send); + std::lock_guard lks(m_crit.send); m_ping_timer.Start(); SendToClients(spac); @@ -80,9 +79,11 @@ void NetPlayServer::ThreadFunc() sf::SocketTCP accept_socket; m_socket.Accept(accept_socket); - m_crit.game.Enter(); // lock game state - const unsigned int error = OnConnect(accept_socket); - m_crit.game.Leave(); + unsigned int error; + { + std::lock_guard lkg(m_crit.game); + error = OnConnect(accept_socket); + } if (error) { @@ -108,10 +109,11 @@ void NetPlayServer::ThreadFunc() //case sf::Socket::Disconnected : default : - m_crit.game.Enter(); // lock game state + { + std::lock_guard lkg(m_crit.game); OnDisconnect(ready_socket); - m_crit.game.Leave(); break; + } } } } @@ -200,8 +202,8 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) } - // ENTER - m_crit.send.Enter(); + { + std::lock_guard lks(m_crit.send); // send join message to already connected clients sf::Packet spac; @@ -230,16 +232,16 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) socket.Send(spac); } - // LEAVE - m_crit.send.Leave(); + } // unlock send // add client to the player list - m_crit.players.Enter(); // lock players + { + std::lock_guard lkp(m_crit.players); m_players[socket] = player; - m_crit.send.Enter(); // lock send + std::lock_guard lks(m_crit.send); UpdatePadMapping(); // sync pad mappings with everyone - m_crit.send.Leave(); - m_crit.players.Leave(); + } + // add client to selector/ used for receiving m_selector.Add(socket); @@ -255,14 +257,14 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket) if (m_is_running) { PanicAlertT("Client disconnect while game is running!! NetPlay is disabled. You must manually stop the game."); - CritLocker game_lock(m_crit.game); // lock game state + std::lock_guard lkg(m_crit.game); m_is_running = false; NetPlay_Disable(); sf::Packet spac; spac << (MessageId)NP_MSG_DISABLE_GAME; // this thread doesnt need players lock - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lks(m_crit.send); SendToClients(spac); } @@ -272,11 +274,11 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket) m_selector.Remove(socket); - CritLocker player_lock(m_crit.players); // lock players + std::lock_guard lkp(m_crit.players); m_players.erase(m_players.find(socket)); // alert other players of disconnect - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lks(m_crit.send); SendToClients(spac); m_dialog->Update(); @@ -287,7 +289,7 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket) // called from ---GUI--- thread bool NetPlayServer::GetPadMapping(const int pid, int map[]) { - CritLocker player_lock(m_crit.players); // lock players + std::lock_guard lkp(m_crit.players); std::map::const_iterator i = m_players.begin(), e = m_players.end(); @@ -309,11 +311,11 @@ bool NetPlayServer::GetPadMapping(const int pid, int map[]) // called from ---GUI--- thread bool NetPlayServer::SetPadMapping(const int pid, const int map[]) { - CritLocker game_lock(m_crit.game); // lock game + std::lock_guard lkg(m_crit.game); if (m_is_running) return false; - CritLocker player_lock(m_crit.players); // lock players + std::lock_guard lkp(m_crit.players); std::map::iterator i = m_players.begin(), e = m_players.end(); @@ -340,7 +342,7 @@ bool NetPlayServer::SetPadMapping(const int pid, const int map[]) i->second.pad_map[p] = -1; } - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lks(m_crit.send); UpdatePadMapping(); // sync pad mappings with everyone m_dialog->Update(); @@ -369,7 +371,7 @@ void NetPlayServer::UpdatePadMapping() // called from ---GUI--- thread and ---NETPLAY--- thread u64 NetPlayServer::CalculateMinimumBufferTime() { - CritLocker player_lock(m_crit.players); + std::lock_guard lkp(m_crit.players); std::map::const_iterator i = m_players.begin(), @@ -392,7 +394,7 @@ u64 NetPlayServer::CalculateMinimumBufferTime() // called from ---GUI--- thread and ---NETPLAY--- thread void NetPlayServer::AdjustPadBufferSize(unsigned int size) { - CritLocker game_lock(m_crit.game); // lock game state + std::lock_guard lkg(m_crit.game); m_target_buffer_size = size; @@ -401,8 +403,8 @@ void NetPlayServer::AdjustPadBufferSize(unsigned int size) spac << (MessageId)NP_MSG_PAD_BUFFER; spac << (u32)m_target_buffer_size; - CritLocker player_lock(m_crit.players); // lock players - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lkp(m_crit.players); + std::lock_guard lks(m_crit.send); SendToClients(spac); } @@ -429,9 +431,10 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) spac << player.pid; spac << msg; - m_crit.send.Enter(); // lock send + { + std::lock_guard lks(m_crit.send); SendToClients(spac, player.pid); - m_crit.send.Leave(); + } // add to gui std::ostringstream ss; @@ -471,7 +474,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) spac << map; // in game mapping spac << np.nHi << np.nLo; - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lks(m_crit.send); SendToClients(spac, player.pid); } break; @@ -510,7 +513,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) // called from ---GUI--- thread void NetPlayServer::GetPlayerList(std::string& list, std::vector& pid_list) { - CritLocker player_lock(m_crit.players); // lock players + std::lock_guard lkp(m_crit.players); std::ostringstream ss; @@ -534,15 +537,15 @@ void NetPlayServer::SendChatMessage(const std::string& msg) spac << (PlayerId)0; // server id always 0 spac << msg; - CritLocker player_lock(m_crit.players); // lock players - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lkp(m_crit.players); + std::lock_guard lks(m_crit.send); SendToClients(spac); } // called from ---GUI--- thread bool NetPlayServer::ChangeGame(const std::string &game) { - CritLocker game_lock(m_crit.game); // lock game state + std::lock_guard lkg(m_crit.game); m_selected_game = game; @@ -551,8 +554,8 @@ bool NetPlayServer::ChangeGame(const std::string &game) spac << (MessageId)NP_MSG_CHANGE_GAME; spac << game; - CritLocker player_lock(m_crit.players); // lock players - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lkp(m_crit.players); + std::lock_guard lks(m_crit.send); SendToClients(spac); return true; @@ -567,14 +570,14 @@ void NetPlayServer::SendPadState(const PadMapping local_nb, const NetPad& np) spac << m_local_player->pad_map[local_nb]; // in-game pad num spac << np.nHi << np.nLo; - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lks(m_crit.send); SendToClients(spac); } // called from ---GUI--- thread bool NetPlayServer::StartGame(const std::string &path) { - CritLocker game_lock(m_crit.game); // lock game state + std::lock_guard lkg(m_crit.game); if (false == NetPlay::StartGame(path)) return false; @@ -590,8 +593,8 @@ bool NetPlayServer::StartGame(const std::string &path) spac << (MessageId)NP_MSG_START_GAME; spac << m_current_game; - CritLocker player_lock(m_crit.players); // lock players - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lkp(m_crit.players); + std::lock_guard lks(m_crit.send); SendToClients(spac); return true; @@ -608,8 +611,8 @@ bool NetPlayServer::StopGame() sf::Packet spac; spac << (MessageId)NP_MSG_STOP_GAME; - CritLocker player_lock(m_crit.players); // lock players - CritLocker send_lock(m_crit.send); // lock send + std::lock_guard lkp(m_crit.players); + std::lock_guard lks(m_crit.send); SendToClients(spac); return true; diff --git a/Source/Core/Core/Src/OnFrame.cpp b/Source/Core/Core/Src/OnFrame.cpp index f665a2de5b..c4076e23ad 100644 --- a/Source/Core/Core/Src/OnFrame.cpp +++ b/Source/Core/Core/Src/OnFrame.cpp @@ -36,7 +36,7 @@ #endif #include "State.h" -Common::CriticalSection cs_frameSkip; +std::mutex cs_frameSkip; namespace Frame { @@ -95,7 +95,7 @@ void FrameUpdate() void SetFrameSkipping(unsigned int framesToSkip) { - cs_frameSkip.Enter(); + std::lock_guard lk(cs_frameSkip); g_framesToSkip = framesToSkip; g_frameSkipCounter = 0; @@ -104,8 +104,6 @@ void SetFrameSkipping(unsigned int framesToSkip) // as this won't be changed anymore when frameskip is turned off if (framesToSkip == 0) g_video_backend->Video_SetRendering(true); - - cs_frameSkip.Leave(); } int FrameSkippingFactor() @@ -138,15 +136,13 @@ void FrameSkipping() // Frameskipping will desync movie playback if (!IsPlayingInput() && !IsRecordingInput()) { - cs_frameSkip.Enter(); + std::lock_guard lk(cs_frameSkip); g_frameSkipCounter++; if (g_frameSkipCounter > g_framesToSkip || Core::report_slow(g_frameSkipCounter) == false) g_frameSkipCounter = 0; g_video_backend->Video_SetRendering(!g_frameSkipCounter); - - cs_frameSkip.Leave(); } } diff --git a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp index 62b7e42944..db4c478bc9 100644 --- a/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp +++ b/Source/Core/DolphinWX/Src/Debugger/CodeWindow.cpp @@ -121,8 +121,6 @@ CCodeWindow::CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter sizerLeft->Fit(this); sizerBig->Fit(this); - - sync_event.Init(); } wxMenuBar *CCodeWindow::GetMenuBar() diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index d2c0657f2a..ebfcc5e196 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -354,8 +354,6 @@ CFrame::CFrame(wxFrame* parent, bFloatWindow[i] = false; #ifdef __WXGTK__ - panic_event.Init(); - keystate_event.Init(); bKeyStateResult = false; #endif @@ -492,11 +490,6 @@ CFrame::~CFrame() ClosePages(); -#ifdef __WXGTK__ - panic_event.Shutdown(); - keystate_event.Shutdown(); -#endif - delete m_Mgr; } diff --git a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp index 1db082e1b8..9871025f6e 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiag.cpp @@ -278,9 +278,8 @@ void GamepadPage::ClearAll(wxCommandEvent&) // no point in using the real ControllerInterface i guess ControllerInterface face; - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); controller->UpdateReferences(face); - m_plugin.controls_crit.Leave(); // leave UpdateGUI(); } @@ -289,9 +288,8 @@ void GamepadPage::LoadDefaults(wxCommandEvent&) { controller->LoadDefaults(g_controller_interface); - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); controller->UpdateReferences(g_controller_interface); - m_plugin.controls_crit.Leave(); // leave UpdateGUI(); } @@ -300,9 +298,8 @@ void ControlDialog::SetControl(wxCommandEvent&) { control_reference->expression = STR_FROM_WXSTR(textctrl->GetValue()); - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); - m_plugin.controls_crit.Leave(); // leave UpdateGUI(); } @@ -318,9 +315,8 @@ void GamepadPage::SetDevice(wxCommandEvent&) controller->UpdateDefaultDevice(); // update references - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); controller->UpdateReferences(g_controller_interface); - m_plugin.controls_crit.Leave(); // leave } void ControlDialog::SetDevice(wxCommandEvent&) @@ -338,9 +334,8 @@ void ControlDialog::ClearControl(wxCommandEvent&) { control_reference->expression.clear(); - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); - m_plugin.controls_crit.Leave(); // leave UpdateGUI(); } @@ -363,9 +358,8 @@ void ControlDialog::SetSelectedControl(wxCommandEvent&) control_reference->expression = STR_FROM_WXSTR(expr); - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); - m_plugin.controls_crit.Leave(); // leave UpdateGUI(); } @@ -395,25 +389,22 @@ void ControlDialog::AppendControl(wxCommandEvent& event) control_reference->expression = STR_FROM_WXSTR(expr); - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); - m_plugin.controls_crit.Leave(); // leave UpdateGUI(); } void GamepadPage::AdjustSetting(wxCommandEvent& event) { - m_plugin.controls_crit.Enter(); // enter / prolly fine not being here + std::lock_guard lk(m_plugin.controls_lock); ((PadSetting*)((wxControl*)event.GetEventObject())->GetClientData())->UpdateValue(); - m_plugin.controls_crit.Leave(); // leave } void GamepadPage::AdjustControlOption(wxCommandEvent&) { - m_plugin.controls_crit.Enter(); // enter / prolly fine not being here + std::lock_guard lk(m_plugin.controls_lock); m_control_dialog->control_reference->range = (ControlState)(m_control_dialog->range_slider->GetValue()) / SLIDER_TICK_COUNT; - m_plugin.controls_crit.Leave(); // leave } void GamepadPage::ConfigControl(wxCommandEvent& event) @@ -432,9 +423,8 @@ void GamepadPage::ClearControl(wxCommandEvent& event) btn->control_reference->expression.clear(); btn->control_reference->range = 1.0f; - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); controller->UpdateReferences(g_controller_interface); - m_plugin.controls_crit.Leave(); // leave // update changes UpdateGUI(); @@ -453,9 +443,8 @@ void ControlDialog::DetectControl(wxCommandEvent& event) // apparently, this makes the "waiting" text work on Linux wxTheApp->Yield(); - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); ControllerInterface::Device::Control* const ctrl = control_reference->Detect(DETECT_WAIT_TIME, dev); - m_plugin.controls_crit.Leave(); // leave // if we got input, select it in the list if (ctrl) @@ -478,7 +467,7 @@ void GamepadPage::DetectControl(wxCommandEvent& event) // apparently, this makes the "waiting" text work on Linux wxTheApp->Yield(); - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); ControllerInterface::Device::Control* const ctrl = btn->control_reference->Detect(DETECT_WAIT_TIME, dev); // if we got input, update expression and reference @@ -488,8 +477,6 @@ void GamepadPage::DetectControl(wxCommandEvent& event) g_controller_interface.UpdateReference(btn->control_reference, controller->default_device); } - m_plugin.controls_crit.Leave(); // leave - btn->SetLabel(WXSTR_FROM_STR(btn->control_reference->expression)); } } @@ -597,10 +584,9 @@ void GamepadPage::LoadProfile(wxCommandEvent&) IniFile inifile; inifile.Load(fname); - m_plugin.controls_crit.Enter(); + std::lock_guard lk(m_plugin.controls_lock); controller->LoadConfig(inifile.GetOrCreateSection("Profile")); controller->UpdateReferences(g_controller_interface); - m_plugin.controls_crit.Leave(); UpdateGUI(); } @@ -662,7 +648,7 @@ void InputConfigDialog::UpdateDeviceComboBox() void GamepadPage::RefreshDevices(wxCommandEvent&) { - m_plugin.controls_crit.Enter(); // enter + std::lock_guard lk(m_plugin.controls_lock); // refresh devices g_controller_interface.Shutdown(); @@ -673,8 +659,6 @@ void GamepadPage::RefreshDevices(wxCommandEvent&) // update device cbox m_config_dialog->UpdateDeviceComboBox(); - - m_plugin.controls_crit.Leave(); // leave } ControlGroupBox::~ControlGroupBox() diff --git a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp index 18718948ac..6f7c83d3c2 100644 --- a/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp +++ b/Source/Core/DolphinWX/Src/InputConfigDiagBitmaps.cpp @@ -22,8 +22,10 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD); g_controller_interface.UpdateInput(); + // don't want game thread updating input when we are using it here - if (false == g_controller_interface.update_lock.TryEnter()) + std::unique_lock lk(g_controller_interface.update_lock, std::try_to_lock); + if (!lk.owns_lock()) return; GamepadPage* const current_page = (GamepadPage*)m_pad_notebook->GetPage(m_pad_notebook->GetSelection()); @@ -344,6 +346,4 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event)) (*g)->static_bitmap->SetBitmap(bitmap); } } - - g_controller_interface.update_lock.Leave(); } diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp index 768ad8c1ea..ad1d9c87a2 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.cpp +++ b/Source/Core/DolphinWX/Src/LogWindow.cpp @@ -42,7 +42,6 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos, , x(0), y(0), winpos(0) , Parent(parent) , m_LogAccess(true) , m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL) - , m_LogSection(1) , m_SJISConv(wxT("")) { #ifdef _WIN32 @@ -212,11 +211,12 @@ void CLogWindow::OnClear(wxCommandEvent& WXUNUSED (event)) { m_Log->Clear(); - m_LogSection.Enter(); + { + std::lock_guard lk(m_LogSection); int msgQueueSize = (int)msgQueue.size(); for (int i = 0; i < msgQueueSize; i++) msgQueue.pop(); - m_LogSection.Leave(); + } m_LogManager->getConsoleListener()->ClearScreen(); } @@ -308,7 +308,8 @@ void CLogWindow::UpdateLog() m_LogTimer->Stop(); - m_LogSection.Enter(); + { + std::lock_guard lk(m_LogSection); int msgQueueSize = (int)msgQueue.size(); for (int i = 0; i < msgQueueSize; i++) { @@ -348,16 +349,16 @@ void CLogWindow::UpdateLog() } msgQueue.pop(); } - m_LogSection.Leave(); + } // unlock log m_LogTimer->Start(UPDATETIME); } void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text) { - m_LogSection.Enter(); + std::lock_guard lk(m_LogSection); + if (msgQueue.size() >= 100) msgQueue.pop(); msgQueue.push(std::pair((u8)level, wxString(text, m_SJISConv))); - m_LogSection.Leave(); } diff --git a/Source/Core/DolphinWX/Src/LogWindow.h b/Source/Core/DolphinWX/Src/LogWindow.h index 551ac4d8c6..e98cf753c8 100644 --- a/Source/Core/DolphinWX/Src/LogWindow.h +++ b/Source/Core/DolphinWX/Src/LogWindow.h @@ -72,7 +72,7 @@ private: wxChoice *m_FontChoice; wxCheckBox *m_WrapLine; - Common::CriticalSection m_LogSection; + std::mutex m_LogSection; wxCSConv m_SJISConv; diff --git a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp index d1efdf1d93..16c633db78 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.cpp @@ -118,10 +118,12 @@ void ControllerInterface::SetHwnd( void* const hwnd ) // bool ControllerInterface::UpdateInput(const bool force) { + std::unique_lock lk(update_lock, std::defer_lock); + if (force) - update_lock.Enter(); - else if (false == update_lock.TryEnter()) - return false; + lk.lock(); + else if (!lk.try_lock()) + return false; size_t ok_count = 0; @@ -137,7 +139,6 @@ bool ControllerInterface::UpdateInput(const bool force) //(*d)->ClearInputState(); } - update_lock.Leave(); return (m_devices.size() == ok_count); } @@ -148,10 +149,12 @@ bool ControllerInterface::UpdateInput(const bool force) // bool ControllerInterface::UpdateOutput(const bool force) { + std::unique_lock lk(update_lock, std::defer_lock); + if (force) - update_lock.Enter(); - else if (false == update_lock.TryEnter()) - return false; + lk.lock(); + else if (!lk.try_lock()) + return false; size_t ok_count = 0; @@ -161,7 +164,6 @@ bool ControllerInterface::UpdateOutput(const bool force) for (;d != e; ++d) (*d)->UpdateOutput(); - update_lock.Leave(); return (m_devices.size() == ok_count); } @@ -470,8 +472,8 @@ void ControllerInterface::UpdateReference(ControllerInterface::ControlReference* else if ('`' == c) { // different device - if (false == /*XXX*/(bool)std::getline(ss, dev_str, '`')) - break; + if (std::getline(ss, dev_str, '`').eof()) + break; // no terminating '`' character } else ctrl_str += c; diff --git a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h index d0bff0a271..661bc832d2 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h +++ b/Source/Core/InputCommon/Src/ControllerInterface/ControllerInterface.h @@ -222,7 +222,7 @@ public: const std::vector& Devices() const { return m_devices; } Device* FindDevice(const DeviceQualifier& devq) const; - Common::CriticalSection update_lock; + std::mutex update_lock; private: bool m_is_init; diff --git a/Source/Core/InputCommon/Src/InputConfig.h b/Source/Core/InputCommon/Src/InputConfig.h index f405b7bfa1..190558a68a 100644 --- a/Source/Core/InputCommon/Src/InputConfig.h +++ b/Source/Core/InputCommon/Src/InputConfig.h @@ -47,7 +47,7 @@ public: std::vector< ControllerEmu* > controllers; - Common::CriticalSection controls_crit; // critical section for changing any control references + std::mutex controls_lock; // for changing any control references const char * const ini_name; const char * const gui_name; diff --git a/Source/Core/InputCommon/Src/UDPWiimote.cpp b/Source/Core/InputCommon/Src/UDPWiimote.cpp index 9396da741f..f14f9ed7e2 100644 --- a/Source/Core/InputCommon/Src/UDPWiimote.cpp +++ b/Source/Core/InputCommon/Src/UDPWiimote.cpp @@ -52,9 +52,9 @@ struct UDPWiimote::_d { std::thread thread; std::list sockfds; - Common::CriticalSection termLock,mutex,nameMutex; + std::mutex termLock, mutex, nameMutex; volatile bool exit; - sock_t bipv4_fd,bipv6_fd; + sock_t bipv4_fd, bipv6_fd; }; int UDPWiimote::noinst = 0; @@ -132,15 +132,17 @@ UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) : d->exit=false; initBroadcastIPv4(); initBroadcastIPv6(); - d->termLock.Enter(); + + std::lock_guard lk(d->termLock); d->thread = std::thread(std::mem_fun(&UDPWiimote::mainThread), this); - d->termLock.Leave(); + return; } void UDPWiimote::mainThread() { - d->termLock.Enter(); + std::unique_lock lk(d->termLock); + Common::Timer time; fd_set fds; struct timeval timeout; @@ -174,11 +176,11 @@ void UDPWiimote::mainThread() timeout.tv_usec=(tleft%1000)*1000; } - d->termLock.Leave(); //VERY hacky. don't like it + lk.unlock(); //VERY hacky. don't like it if (d->exit) return; int rt=select(maxfd,&fds,NULL,NULL,&timeout); if (d->exit) return; - d->termLock.Enter(); + lk.lock(); if (d->exit) return; if (rt) @@ -200,27 +202,26 @@ void UDPWiimote::mainThread() } else { - d->mutex.Enter(); + std::lock_guard lkm(d->mutex); if (pharsePacket(bf,size)==0) { //NOTICE_LOG(WIIMOTE,"UDPWII New pack"); } else { //NOTICE_LOG(WIIMOTE,"UDPWII Wrong pack format... ignoring"); } - d->mutex.Leave(); } } } } while (!(d->exit)); - d->termLock.Leave(); } UDPWiimote::~UDPWiimote() { d->exit = true; + { + std::lock_guard lk(d->termLock); d->thread.join(); - d->termLock.Enter(); - d->termLock.Leave(); + } for (std::list::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) close(*i); close(d->bipv4_fd); @@ -289,7 +290,6 @@ int UDPWiimote::pharsePacket(u8 * bf, size_t size) return 0; } - void UDPWiimote::initBroadcastIPv4() { d->bipv4_fd=socket(AF_INET, SOCK_DGRAM, 0); @@ -342,71 +342,64 @@ void UDPWiimote::broadcastPresence() *((u16*)(&(bf[1])))=htons(bcastMagic); //unique per-wiimote 16-bit ID bf[3]=(u8)index; //wiimote index *((u16*)(&(bf[4])))=htons(int_port); //port - d->nameMutex.Enter(); + { + std::lock_guard lk(d->nameMutex); slen=displayName.size(); if (slen>=256) slen=255; bf[6]=(u8)slen; //display name size (max 255) memcpy(&(bf[7]),displayName.c_str(),slen); //display name - d->nameMutex.Leave(); + } broadcastIPv4(bf,7+slen); broadcastIPv6(bf,7+slen); } void UDPWiimote::getAccel(float &_x, float &_y, float &_z) { - d->mutex.Enter(); + std::lock_guard lk(d->mutex); _x=(float)x; _y=(float)y; _z=(float)z; - d->mutex.Leave(); } u32 UDPWiimote::getButtons() { u32 msk; - d->mutex.Enter(); + std::lock_guard lk(d->mutex); msk=mask; - d->mutex.Leave(); return msk; } void UDPWiimote::getIR(float &_x, float &_y) { - d->mutex.Enter(); + std::lock_guard lk(d->mutex); _x=(float)pointerX; _y=(float)pointerY; - d->mutex.Leave(); } void UDPWiimote::getNunchuck(float &_x, float &_y, u8 &_mask) { - d->mutex.Enter(); + std::lock_guard lk(d->mutex); _x=(float)nunX; _y=(float)nunY; _mask=nunMask; - d->mutex.Leave(); } void UDPWiimote::getNunchuckAccel(float &_x, float &_y, float &_z) { - d->mutex.Enter(); + std::lock_guard lk(d->mutex); _x=(float)naX; _y=(float)naY; _z=(float)naZ; - d->mutex.Leave(); } - const char * UDPWiimote::getPort() { return port.c_str(); } - void UDPWiimote::changeName(const char * name) { - d->nameMutex.Enter(); + std::lock_guard lk(d->nameMutex); displayName=name; - d->nameMutex.Leave(); } diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index 853c2d574d..82a4ec8a72 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -46,7 +46,7 @@ int OSDChoice, OSDTime; Renderer *g_renderer = NULL; bool s_bLastFrameDumped = false; -Common::CriticalSection Renderer::s_criticalScreenshot; +std::mutex Renderer::s_criticalScreenshot; std::string Renderer::s_sScreenshotName; volatile bool Renderer::s_bScreenshot; @@ -182,10 +182,9 @@ bool Renderer::CalculateTargetSize(int multiplier) void Renderer::SetScreenshot(const char *filename) { - s_criticalScreenshot.Enter(); + std::lock_guard lk(s_criticalScreenshot); s_sScreenshotName = filename; s_bScreenshot = true; - s_criticalScreenshot.Leave(); } // Create On-Screen-Messages diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 6085581475..338e2fda2c 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -142,7 +142,7 @@ public: protected: - static Common::CriticalSection s_criticalScreenshot; + static std::mutex s_criticalScreenshot; static std::string s_sScreenshotName; static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 45d79564c1..51f4154373 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -1094,10 +1094,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons // Save screenshot if (s_bScreenshot) { - s_criticalScreenshot.Enter(); + std::lock_guard lk(s_criticalScreenshot); SaveScreenshot(s_sScreenshotName, dst_rect); s_bScreenshot = false; - s_criticalScreenshot.Leave(); } if (g_ActiveConfig.bDumpFrames) { diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index ccee1ef777..c0a95f1f8f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -1150,19 +1150,18 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons // Save screenshot if (s_bScreenshot) { - s_criticalScreenshot.Enter(); + std::lock_guard lk(s_criticalScreenshot); SaveScreenshot(s_sScreenshotName, dst_rect); // Reset settings s_sScreenshotName.clear(); s_bScreenshot = false; - s_criticalScreenshot.Leave(); } // Frame dumps are handled a little differently in Windows #if defined _WIN32 || defined HAVE_LIBAV if (g_ActiveConfig.bDumpFrames) { - s_criticalScreenshot.Enter(); + std::lock_guard lk(s_criticalScreenshot); if (!data || w != dst_rect.GetWidth() || h != dst_rect.GetHeight()) { @@ -1205,8 +1204,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons } else NOTICE_LOG(VIDEO, "Error reading framebuffer"); - - s_criticalScreenshot.Leave(); } else { diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp index fd1e111f4d..d76ebdd5f0 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWCommandProcessor.cpp @@ -70,8 +70,6 @@ volatile bool interruptWaiting; CPReg cpreg; // shared between gfx and emulator thread -Common::CriticalSection criticalSection; - void DoState(PointerWrap &p) { p.Do(cpreg);