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
This commit is contained in:
Jordan Woyak 2011-03-05 06:11:26 +00:00
parent a037ff2358
commit 423018f811
56 changed files with 918 additions and 835 deletions

View File

@ -47,9 +47,11 @@ void AOSound::SoundLoop()
while (!threadData) while (!threadData)
{ {
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2); m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
soundCriticalSection.Enter();
{
std::lock_guard<std::mutex> lk(soundCriticalSection);
ao_play(device, (char*)realtimeBuffer, numBytesToRender); ao_play(device, (char*)realtimeBuffer, numBytesToRender);
soundCriticalSection.Leave(); }
soundSyncEvent.Wait(); soundSyncEvent.Wait();
} }
@ -59,8 +61,6 @@ bool AOSound::Start()
{ {
memset(realtimeBuffer, 0, sizeof(realtimeBuffer)); memset(realtimeBuffer, 0, sizeof(realtimeBuffer));
soundSyncEvent.Init();
thread = std::thread(std::mem_fun(&AOSound::SoundLoop), this); thread = std::thread(std::mem_fun(&AOSound::SoundLoop), this);
return true; return true;
} }
@ -75,7 +75,8 @@ void AOSound::Stop()
threadData = 1; threadData = 1;
soundSyncEvent.Set(); soundSyncEvent.Set();
soundCriticalSection.Enter(); {
std::lock_guard<std::mutex> lk(soundCriticalSection);
thread.join(); thread.join();
if (device) if (device)
@ -84,9 +85,7 @@ void AOSound::Stop()
ao_shutdown(); ao_shutdown();
device = NULL; device = NULL;
soundCriticalSection.Leave(); }
soundSyncEvent.Shutdown();
} }
AOSound::~AOSound() AOSound::~AOSound()

View File

@ -30,7 +30,7 @@ class AOSound : public SoundStream
{ {
#if defined(HAVE_AO) && HAVE_AO #if defined(HAVE_AO) && HAVE_AO
std::thread thread; std::thread thread;
Common::CriticalSection soundCriticalSection; std::mutex soundCriticalSection;
Common::Event soundSyncEvent; Common::Event soundSyncEvent;
int buf_size; int buf_size;

View File

@ -119,8 +119,6 @@ void DSound::SoundLoop()
bool DSound::Start() bool DSound::Start()
{ {
soundSyncEvent.Init();
if (FAILED(DirectSoundCreate8(0, &ds, 0))) if (FAILED(DirectSoundCreate8(0, &ds, 0)))
return false; return false;
if (hWnd) if (hWnd)
@ -180,7 +178,5 @@ void DSound::Stop()
dsBuffer->Stop(); dsBuffer->Stop();
dsBuffer->Release(); dsBuffer->Release();
ds->Release(); ds->Release();
soundSyncEvent.Shutdown();
} }

View File

@ -32,7 +32,7 @@ class DSound : public SoundStream
{ {
#ifdef _WIN32 #ifdef _WIN32
std::thread thread; std::thread thread;
Common::EventEx soundSyncEvent; Common::Event soundSyncEvent;
void *hWnd; void *hWnd;
IDirectSound8* ds; IDirectSound8* ds;

View File

@ -32,8 +32,6 @@ bool OpenALStream::Start()
ALCdevice *pDevice = NULL; ALCdevice *pDevice = NULL;
bool bReturn = false; bool bReturn = false;
soundSyncEvent.Init();
pDeviceList = new ALDeviceList(); pDeviceList = new ALDeviceList();
if ((pDeviceList) && (pDeviceList->GetNumDevices())) if ((pDeviceList) && (pDeviceList->GetNumDevices()))
{ {
@ -92,8 +90,6 @@ void OpenALStream::Stop()
alcMakeContextCurrent(NULL); alcMakeContextCurrent(NULL);
alcDestroyContext(pContext); alcDestroyContext(pContext);
alcCloseDevice(pDevice); alcCloseDevice(pDevice);
soundSyncEvent.Shutdown();
} }
void OpenALStream::SetVolume(int volume) void OpenALStream::SetVolume(int volume)

View File

@ -63,7 +63,7 @@ public:
private: private:
std::thread thread; std::thread thread;
Common::EventEx soundSyncEvent; Common::Event soundSyncEvent;
short realtimeBuffer[OAL_MAX_SAMPLES * 2]; short realtimeBuffer[OAL_MAX_SAMPLES * 2];
ALuint uiBuffers[OAL_NUM_BUFFERS]; ALuint uiBuffers[OAL_NUM_BUFFERS];

View File

@ -22,10 +22,10 @@ struct StreamingVoiceContext : public IXAudio2VoiceCallback
{ {
IXAudio2SourceVoice* pSourceVoice; IXAudio2SourceVoice* pSourceVoice;
CMixer *m_mixer; CMixer *m_mixer;
Common::EventEx *soundSyncEvent; Common::Event *soundSyncEvent;
short *xaBuffer; short *xaBuffer;
StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::EventEx *pSyncEvent) StreamingVoiceContext(IXAudio2 *pXAudio2, CMixer *pMixer, Common::Event *pSyncEvent)
{ {
m_mixer = pMixer; m_mixer = pMixer;
@ -100,7 +100,6 @@ struct StreamingVoiceContext : public IXAudio2VoiceCallback
// //
if( !pSourceVoice || !context) return; if( !pSourceVoice || !context) return;
//soundSyncEvent->Init();
//soundSyncEvent->Wait(); //sync //soundSyncEvent->Wait(); //sync
//soundSyncEvent->Spin(); //or tight sync //soundSyncEvent->Spin(); //or tight sync
@ -123,8 +122,6 @@ StreamingVoiceContext* pVoiceContext = 0;
bool XAudio2::Start() bool XAudio2::Start()
{ {
//soundSyncEvent.Init();
// XAudio2 init // XAudio2 init
CoInitializeEx(NULL, COINIT_MULTITHREADED); CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr; HRESULT hr;
@ -207,5 +204,4 @@ void XAudio2::Stop()
safe_release(pXAudio2); safe_release(pXAudio2);
pMasteringVoice = NULL; pMasteringVoice = NULL;
CoUninitialize(); CoUninitialize();
//soundSyncEvent.Shutdown();
} }

View File

@ -52,7 +52,7 @@ class XAudio2 : public SoundStream
IXAudio2MasteringVoice *pMasteringVoice; IXAudio2MasteringVoice *pMasteringVoice;
IXAudio2SourceVoice *pSourceVoice; IXAudio2SourceVoice *pSourceVoice;
Common::EventEx soundSyncEvent; Common::Event soundSyncEvent;
float m_volume; float m_volume;

View File

@ -255,6 +255,8 @@
<ClInclude Include="Src\SDCardUtil.h" /> <ClInclude Include="Src\SDCardUtil.h" />
<ClInclude Include="Src\Setup.h" /> <ClInclude Include="Src\Setup.h" />
<ClInclude Include="Src\stdafx.h" /> <ClInclude Include="Src\stdafx.h" />
<ClInclude Include="Src\StdConditionVariable.h" />
<ClInclude Include="Src\StdMutex.h" />
<ClInclude Include="Src\StdThread.h" /> <ClInclude Include="Src\StdThread.h" />
<ClInclude Include="Src\StringUtil.h" /> <ClInclude Include="Src\StringUtil.h" />
<ClInclude Include="Src\svnrev.h" /> <ClInclude Include="Src\svnrev.h" />

View File

@ -121,6 +121,8 @@
<ClInclude Include="Src\Crypto\tools.h"> <ClInclude Include="Src\Crypto\tools.h">
<Filter>Crypto</Filter> <Filter>Crypto</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Src\StdMutex.h" />
<ClInclude Include="Src\StdConditionVariable.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="CMakeLists.txt" /> <None Include="CMakeLists.txt" />

View File

@ -36,9 +36,8 @@ void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
LogManager *LogManager::m_logManager = NULL; LogManager *LogManager::m_logManager = NULL;
LogManager::LogManager() { LogManager::LogManager()
logMutex = new Common::CriticalSection(1); {
// create log files // create log files
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log"); m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot"); m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
@ -105,7 +104,6 @@ LogManager::~LogManager() {
delete m_fileLog; delete m_fileLog;
delete m_consoleLog; delete m_consoleLog;
delete logMutex;
} }
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, 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], file, line, level_to_char[(int)level],
log->getShortName(), temp); log->getShortName(), temp);
logMutex->Enter(); std::lock_guard<std::mutex> lk(logMutex);
log->trigger(level, msg); log->trigger(level, msg);
logMutex->Leave();
} }
void LogManager::removeListener(LogTypes::LOG_TYPE type, LogListener *listener) { void LogManager::removeListener(LogTypes::LOG_TYPE type, LogListener *listener)
logMutex->Enter(); {
std::lock_guard<std::mutex> lk(logMutex);
m_Log[type]->removeListener(listener); m_Log[type]->removeListener(listener);
logMutex->Leave();
} }
void LogManager::Init() void LogManager::Init()

View File

@ -20,6 +20,7 @@
#include "Log.h" #include "Log.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "Thread.h"
#include <vector> #include <vector>
#include <string.h> #include <string.h>
@ -102,16 +103,11 @@ private:
class ConsoleListener; class ConsoleListener;
// Avoid <windows.h> include through Thread.h
namespace Common {
class CriticalSection;
}
class LogManager : NonCopyable class LogManager : NonCopyable
{ {
private: private:
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS]; LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
Common::CriticalSection *logMutex; std::mutex logMutex;
FileLogListener *m_fileLog; FileLogListener *m_fileLog;
ConsoleListener *m_consoleLog; ConsoleListener *m_consoleLog;
static LogManager *m_logManager; // Singleton. Ugh. static LogManager *m_logManager; // Singleton. Ugh.

View File

@ -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 <condition_variable>
#include <condition_variable>
#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<mutex>& 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 <class Predicate>
void wait(unique_lock<mutex>& lock, Predicate pred)
{
while (!pred())
wait(lock);
}
//template <class Clock, class Duration>
//cv_status wait_until(unique_lock<mutex>& lock,
// const chrono::time_point<Clock, Duration>& abs_time);
//template <class Clock, class Duration, class Predicate>
// bool wait_until(unique_lock<mutex>& lock,
// const chrono::time_point<Clock, Duration>& abs_time,
// Predicate pred);
//template <class Rep, class Period>
//cv_status wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& rel_time);
//template <class Rep, class Period, class Predicate>
// bool wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& 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

View File

@ -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 <mutex>
#include <mutex>
#else
// partial <mutex> implementation for win32/pthread
#include <algorithm>
#if defined(_WIN32)
// WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#else
// POSIX
#include <pthread.h>
#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 Mutex>
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 Mutex>
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 <class Clock, class Duration>
//unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
//template <class Rep, class Period>
//unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& 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<unique_lock&>(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<unique_lock&>(u);
#endif
swap(other);
}
void lock()
{
mutex()->lock();
owns = true;
}
bool try_lock()
{
owns = mutex()->try_lock();
return owns;
}
//template <class Rep, class Period>
//bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
//template <class Clock, class Duration>
//bool try_lock_until(const chrono::time_point<Clock, Duration>& 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 <class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
{
x.swap(y);
}
}
#endif
#endif

View File

@ -55,219 +55,49 @@ void SetCurrentThreadAffinity(u32 mask)
SetThreadAffinityMask(GetCurrentThread(), mask); SetThreadAffinityMask(GetCurrentThread(), mask);
} }
CriticalSection::CriticalSection(int spincount) // Supporting functions
{ void SleepCurrentThread(int ms)
if (spincount) {
{
if (!InitializeCriticalSectionAndSpinCount(&section, spincount))
ERROR_LOG(COMMON, "CriticalSection could not be initialized!\n%s", GetLastErrorMsg());
}
else
{
InitializeCriticalSection(&section);
}
}
CriticalSection::~CriticalSection()
{
DeleteCriticalSection(&section);
}
void CriticalSection::Enter()
{
EnterCriticalSection(&section);
}
bool CriticalSection::TryEnter()
{
return TryEnterCriticalSection(&section) ? true : false;
}
void CriticalSection::Leave()
{
LeaveCriticalSection(&section);
}
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;
}
}
}
// Supporting functions
void SleepCurrentThread(int ms)
{
Sleep(ms); Sleep(ms);
} }
void SwitchCurrentThread() void SwitchCurrentThread()
{ {
SwitchToThread(); SwitchToThread();
} }
typedef struct tagTHREADNAME_INFO // 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 char* szThreadName)
{
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8)
struct THREADNAME_INFO
{ {
DWORD dwType; // must be 0x1000 DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name (in user addr space) LPCSTR szName; // pointer to name (in user addr space)
DWORD dwThreadID; // thread ID (-1=caller thread) DWORD dwThreadID; // thread ID (-1=caller thread)
DWORD dwFlags; // reserved for future use, must be zero DWORD dwFlags; // reserved for future use, must be zero
} THREADNAME_INFO; } info;
// Usage: SetThreadName (-1, "MainThread"); #pragma pack(pop)
//
// 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)
{
THREADNAME_INFO info;
info.dwType = 0x1000; 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; info.szName = szThreadName;
#endif
info.dwThreadID = -1; //dwThreadID; info.dwThreadID = -1; //dwThreadID;
info.dwFlags = 0; info.dwFlags = 0;
__try __try
{ {
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR*)&info); RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
} }
__except(EXCEPTION_CONTINUE_EXECUTION) __except(EXCEPTION_CONTINUE_EXECUTION)
{} {}
} }
#else // !WIN32, so must be POSIX threads #else // !WIN32, so must be POSIX threads
@ -293,72 +123,31 @@ void SetCurrentThreadAffinity(u32 mask)
SetThreadAffinity(pthread_self(), mask); SetThreadAffinity(pthread_self(), mask);
} }
static pthread_key_t threadname_key; static pthread_key_t threadname_key;
static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT; static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT;
CriticalSection::CriticalSection(int spincount_unused) void SleepCurrentThread(int ms)
{ {
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
}
void SleepCurrentThread(int ms)
{
usleep(1000 * ms); usleep(1000 * ms);
} }
void SwitchCurrentThread() void SwitchCurrentThread()
{ {
usleep(1000 * 1); usleep(1000 * 1);
} }
static void FreeThreadName(void* threadname) static void FreeThreadName(void* threadname)
{ {
free(threadname); free(threadname);
} }
static void ThreadnameKeyAlloc() static void ThreadnameKeyAlloc()
{ {
pthread_key_create(&threadname_key, FreeThreadName); pthread_key_create(&threadname_key, FreeThreadName);
} }
void SetCurrentThreadName(const TCHAR* szThreadName) void SetCurrentThreadName(const char* szThreadName)
{ {
pthread_once(&threadname_key_once, ThreadnameKeyAlloc); pthread_once(&threadname_key_once, ThreadnameKeyAlloc);
void* threadname; void* threadname;
@ -368,75 +157,7 @@ void SetCurrentThreadAffinity(u32 mask)
pthread_setspecific(threadname_key, strdup(szThreadName)); pthread_setspecific(threadname_key, strdup(szThreadName));
INFO_LOG(COMMON, "%s(%s)\n", __FUNCTION__, 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 #endif

View File

@ -19,6 +19,8 @@
#define _THREAD_H_ #define _THREAD_H_
#include "StdThread.h" #include "StdThread.h"
#include "StdMutex.h"
#include "StdConditionVariable.h"
// Don't include common.h here as it will break LogManager // Don't include common.h here as it will break LogManager
#include "CommonTypes.h" #include "CommonTypes.h"
@ -38,7 +40,6 @@
#include <sys/time.h> #include <sys/time.h>
#endif #endif
namespace Common namespace Common
{ {
@ -47,105 +48,70 @@ int CurrentThreadId();
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
void SetCurrentThreadAffinity(u32 mask); void SetCurrentThreadAffinity(u32 mask);
class CriticalSection class Event
{
public:
void Set()
{ {
#ifdef _WIN32 m_condvar.notify_one();
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
} }
void SetCurrentThreadName(const char *name); void Wait()
{
std::unique_lock<std::mutex> 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<std::mutex> 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 } // namespace Common

View File

@ -102,8 +102,8 @@ static std::thread cpuThread;
SCoreStartupParameter g_CoreStartupParameter; SCoreStartupParameter g_CoreStartupParameter;
// This event is set when the emuthread starts. // This event is set when the emuthread starts.
Common::Event emuThreadGoing; Common::Barrier emuThreadGoing(2);
Common::Event cpuRunloopQuit; Common::Barrier cpuRunloopQuit(2);
std::string GetStateFileName() { return g_stateFileName; } std::string GetStateFileName() { return g_stateFileName; }
void SetStateFileName(std::string val) { g_stateFileName = val; } void SetStateFileName(std::string val) { g_stateFileName = val; }
@ -248,14 +248,11 @@ bool Init()
// The hardware is initialized. // The hardware is initialized.
g_bHwInit = true; g_bHwInit = true;
emuThreadGoing.Init();
// Start the emu thread // Start the emu thread
g_EmuThread = std::thread(EmuThread); g_EmuThread = std::thread(EmuThread);
// Wait until the emu thread is running // Wait until the emu thread is running
emuThreadGoing.MsgWait(); emuThreadGoing.Wait();
emuThreadGoing.Shutdown();
Host_SetWaitCursor(false); Host_SetWaitCursor(false);
@ -359,7 +356,7 @@ void CpuThread()
// Enter CPU run loop. When we leave it - we are done. // Enter CPU run loop. When we leave it - we are done.
CCPU::Run(); CCPU::Run();
cpuRunloopQuit.Set(); cpuRunloopQuit.Wait();
return; return;
} }
@ -372,8 +369,6 @@ void EmuThread()
const SCoreStartupParameter& _CoreParameter = const SCoreStartupParameter& _CoreParameter =
SConfig::GetInstance().m_LocalCoreStartupParameter; SConfig::GetInstance().m_LocalCoreStartupParameter;
cpuRunloopQuit.Init();
Common::SetCurrentThreadName("Emuthread - starting"); Common::SetCurrentThreadName("Emuthread - starting");
if (_CoreParameter.bLockThreads) if (_CoreParameter.bLockThreads)
@ -384,7 +379,7 @@ void EmuThread()
Common::SetCurrentThreadAffinity(2); Common::SetCurrentThreadAffinity(2);
} }
emuThreadGoing.Set(); emuThreadGoing.Wait();
DisplayMessage("CPU: " + cpu_info.Summarize(), 8000); DisplayMessage("CPU: " + cpu_info.Summarize(), 8000);
DisplayMessage(_CoreParameter.m_strFilename, 3000); DisplayMessage(_CoreParameter.m_strFilename, 3000);
@ -462,7 +457,6 @@ void EmuThread()
VolumeHandler::EjectVolume(); VolumeHandler::EjectVolume();
FileMon::Close(); FileMon::Close();
cpuRunloopQuit.Shutdown();
g_bStopping = false; g_bStopping = false;
} }

View File

@ -68,7 +68,7 @@ u64 fakeDecStartTicks;
u64 fakeTBStartValue; u64 fakeTBStartValue;
u64 fakeTBStartTicks; u64 fakeTBStartTicks;
static Common::CriticalSection externalEventSection; static std::mutex externalEventSection;
void (*advanceCallback)(int cyclesExecuted) = NULL; void (*advanceCallback)(int cyclesExecuted) = NULL;
@ -143,19 +143,18 @@ void Shutdown()
delete ev; delete ev;
} }
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
while(eventTsPool) while(eventTsPool)
{ {
Event *ev = eventTsPool; Event *ev = eventTsPool;
eventTsPool = ev->next; eventTsPool = ev->next;
delete ev; delete ev;
} }
externalEventSection.Leave();
} }
void DoState(PointerWrap &p) void DoState(PointerWrap &p)
{ {
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
p.Do(downcount); p.Do(downcount);
p.Do(slicelength); p.Do(slicelength);
p.Do(globalTimer); p.Do(globalTimer);
@ -210,7 +209,6 @@ void DoState(PointerWrap &p)
break; break;
} }
} }
externalEventSection.Leave();
} }
u64 GetTicks() u64 GetTicks()
@ -227,7 +225,7 @@ u64 GetIdleTicks()
// schedule things to be executed on the main thread. // schedule things to be executed on the main thread.
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata) void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata)
{ {
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
Event *ne = GetNewTsEvent(); Event *ne = GetNewTsEvent();
ne->time = globalTimer + cyclesIntoFuture; ne->time = globalTimer + cyclesIntoFuture;
ne->type = event_type; ne->type = event_type;
@ -238,7 +236,6 @@ void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata
if(tsLast) if(tsLast)
tsLast->next = ne; tsLast->next = ne;
tsLast = ne; tsLast = ne;
externalEventSection.Leave();
} }
// Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread // 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()) if(Core::IsCPUThread())
{ {
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
event_types[event_type].callback(userdata, 0); event_types[event_type].callback(userdata, 0);
externalEventSection.Leave();
} }
else else
ScheduleEvent_Threadsafe(0, event_type, userdata); ScheduleEvent_Threadsafe(0, event_type, userdata);
@ -352,10 +348,9 @@ void RemoveEvent(int event_type)
void RemoveThreadsafeEvent(int event_type) void RemoveThreadsafeEvent(int event_type)
{ {
externalEventSection.Enter(); std::lock_guard<std::mutex> lk(externalEventSection);
if (!tsFirst) if (!tsFirst)
{ {
externalEventSection.Leave();
return; return;
} }
while(tsFirst) while(tsFirst)
@ -373,7 +368,6 @@ void RemoveThreadsafeEvent(int event_type)
} }
if (!tsFirst) if (!tsFirst)
{ {
externalEventSection.Leave();
return; return;
} }
Event *prev = tsFirst; Event *prev = tsFirst;
@ -392,7 +386,6 @@ void RemoveThreadsafeEvent(int event_type)
ptr = ptr->next; ptr = ptr->next;
} }
} }
externalEventSection.Leave();
} }
void RemoveAllEvents(int event_type) void RemoveAllEvents(int event_type)
@ -438,8 +431,7 @@ void ProcessFifoWaitEvents()
void MoveEvents() void MoveEvents()
{ {
std::lock_guard<std::mutex> lk(externalEventSection);
externalEventSection.Enter();
// Move events from async queue into main queue // Move events from async queue into main queue
while (tsFirst) while (tsFirst)
{ {
@ -458,8 +450,6 @@ void MoveEvents()
eventTsPool = ev; eventTsPool = ev;
allocatedTsEvents--; allocatedTsEvents--;
} }
externalEventSection.Leave();
} }
void Advance() void Advance()

View File

@ -41,7 +41,7 @@ DSPCoreState core_state = DSPCORE_STOP;
u16 cyclesLeft = 0; u16 cyclesLeft = 0;
DSPEmitter *dspjit = NULL; DSPEmitter *dspjit = NULL;
Common::Event step_event; Common::Event step_event;
Common::CriticalSection ExtIntCriticalSection; static std::mutex ExtIntCriticalSection;
static bool LoadRom(const char *fname, int size_in_words, u16 *rom) 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(); DSPAnalyzer::Analyze();
step_event.Init();
core_state = DSPCORE_RUNNING; core_state = DSPCORE_RUNNING;
return true; return true;
@ -183,7 +181,6 @@ void DSPCore_Shutdown()
delete dspjit; delete dspjit;
dspjit = NULL; dspjit = NULL;
} }
step_event.Shutdown();
DSPCore_FreeMemoryPages(); DSPCore_FreeMemoryPages();
} }
@ -206,9 +203,8 @@ void DSPCore_SetException(u8 level)
// Notify that an external interrupt is pending (used by thread mode) // Notify that an external interrupt is pending (used by thread mode)
void DSPCore_SetExternalInterrupt(bool val) void DSPCore_SetExternalInterrupt(bool val)
{ {
ExtIntCriticalSection.Enter(); std::lock_guard<std::mutex> lk(ExtIntCriticalSection);
g_dsp.external_interrupt_waiting = val; g_dsp.external_interrupt_waiting = val;
ExtIntCriticalSection.Leave();
} }
// Coming from the CPU // Coming from the CPU

View File

@ -249,7 +249,7 @@ struct SDSP
volatile u16 mbox[2][2]; volatile u16 mbox[2][2];
// Mutex protecting the mailbox. // Mutex protecting the mailbox.
Common::CriticalSection g_CriticalSection; std::mutex g_CriticalSection;
// Accelerator / DMA / other hardware registers. Not GPRs. // Accelerator / DMA / other hardware registers. Not GPRs.
u16 ifx_regs[256]; u16 ifx_regs[256];

View File

@ -41,7 +41,7 @@
static void gdsp_do_dma(); static void gdsp_do_dma();
Common::CriticalSection g_CriticalSection; static std::mutex g_CriticalSection;
void gdsp_ifx_init() void gdsp_ifx_init()
{ {
@ -56,35 +56,34 @@ void gdsp_ifx_init()
g_dsp.mbox[1][1] = 0; g_dsp.mbox[1][1] = 0;
} }
u32 gdsp_mbox_peek(u8 mbx) u32 gdsp_mbox_peek(u8 mbx)
{ {
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
u32 value = ((g_dsp.mbox[mbx][0] << 16) | g_dsp.mbox[mbx][1]);
if (DSPHost_OnThread()) return ((g_dsp.mbox[mbx][0] << 16) | g_dsp.mbox[mbx][1]);
g_CriticalSection.Leave();
return value;
} }
void gdsp_mbox_write_h(u8 mbx, u16 val) void gdsp_mbox_write_h(u8 mbx, u16 val)
{ {
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
g_dsp.mbox[mbx][0] = val & 0x7fff;
if (DSPHost_OnThread())
g_CriticalSection.Leave();
}
g_dsp.mbox[mbx][0] = val & 0x7fff;
}
void gdsp_mbox_write_l(u8 mbx, u16 val) void gdsp_mbox_write_l(u8 mbx, u16 val)
{ {
{
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
g_dsp.mbox[mbx][1] = val; g_dsp.mbox[mbx][1] = val;
g_dsp.mbox[mbx][0] |= 0x8000; g_dsp.mbox[mbx][0] |= 0x8000;
if (DSPHost_OnThread()) }
g_CriticalSection.Leave();
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (mbx == GDSP_MBOX_DSP) if (mbx == GDSP_MBOX_DSP)
@ -96,29 +95,27 @@ void gdsp_mbox_write_l(u8 mbx, u16 val)
#endif #endif
} }
u16 gdsp_mbox_read_h(u8 mbx) u16 gdsp_mbox_read_h(u8 mbx)
{ {
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) if (DSPHost_OnThread())
g_CriticalSection.Enter(); lk.lock();
u16 val = g_dsp.mbox[mbx][0]; // TODO: mask away the top bit?
if (DSPHost_OnThread()) return g_dsp.mbox[mbx][0]; // TODO: mask away the top bit?
g_CriticalSection.Leave();
return val;
} }
u16 gdsp_mbox_read_l(u8 mbx) u16 gdsp_mbox_read_l(u8 mbx)
{ {
u16 val;
{
std::unique_lock<std::mutex> lk(g_CriticalSection, std::defer_lock);
if (DSPHost_OnThread()) 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; g_dsp.mbox[mbx][0] &= ~0x8000;
}
if (DSPHost_OnThread())
g_CriticalSection.Leave();
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (mbx == GDSP_MBOX_DSP) if (mbx == GDSP_MBOX_DSP)
@ -132,7 +129,6 @@ u16 gdsp_mbox_read_l(u8 mbx)
return val; return val;
} }
void gdsp_ifx_write(u32 addr, u32 val) void gdsp_ifx_write(u32 addr, u32 val)
{ {
switch (addr & 0xff) switch (addr & 0xff)

View File

@ -55,7 +55,7 @@ u32 GeckoCode::Code::GetAddress() const
return gcaddress + (use_po ? pointer_address : (base_address & 0xFE000000)); return gcaddress + (use_po ? pointer_address : (base_address & 0xFE000000));
} }
static Common::CriticalSection active_codes_lock; static std::mutex active_codes_lock;
// currently running code // currently running code
static GeckoCode::Code *codes_start = NULL, *current_code = NULL; 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<GeckoCode>& gcodes) void SetActiveCodes(const std::vector<GeckoCode>& gcodes)
{ {
active_codes_lock.Enter(); std::lock_guard<std::mutex> lk(active_codes_lock);
active_codes.clear(); active_codes.clear();
// add enabled codes // add enabled codes
@ -94,8 +94,6 @@ void SetActiveCodes(const std::vector<GeckoCode>& gcodes)
} }
inserted_asm_codes.clear(); inserted_asm_codes.clear();
active_codes_lock.Leave();
} }
bool RunGeckoCode(GeckoCode& gecko_code) bool RunGeckoCode(GeckoCode& gecko_code)
@ -151,10 +149,9 @@ bool RunGeckoCode(GeckoCode& gecko_code)
bool RunActiveCodes() bool RunActiveCodes()
{ {
if (false == SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats)
return true; {
if (false == active_codes_lock.TryEnter()) std::lock_guard<std::mutex> lk(active_codes_lock);
return true;
std::vector<GeckoCode>::iterator std::vector<GeckoCode>::iterator
gcodes_iter = active_codes.begin(), gcodes_iter = active_codes.begin(),
@ -167,8 +164,8 @@ bool RunActiveCodes()
//if (false == RunGeckoCode(*gcodes_iter)) //if (false == RunGeckoCode(*gcodes_iter))
//return false; //return false;
} }
}
active_codes_lock.Leave();
return true; return true;
} }

View File

@ -35,7 +35,6 @@ namespace
void CCPU::Init(int cpu_core) void CCPU::Init(int cpu_core)
{ {
m_StepEvent.Init();
PowerPC::Init(cpu_core); PowerPC::Init(cpu_core);
m_SyncEvent = 0; m_SyncEvent = 0;
} }
@ -43,7 +42,6 @@ void CCPU::Init(int cpu_core)
void CCPU::Shutdown() void CCPU::Shutdown()
{ {
PowerPC::Shutdown(); PowerPC::Shutdown();
m_StepEvent.Shutdown();
m_SyncEvent = 0; m_SyncEvent = 0;
} }

View File

@ -570,7 +570,7 @@ void CUCode_Zelda::ExecuteList()
void CUCode_Zelda::DoState(PointerWrap &p) void CUCode_Zelda::DoState(PointerWrap &p)
{ {
// It's bad if we try to save during Mix() // It's bad if we try to save during Mix()
m_csMix.Enter(); std::lock_guard<std::mutex> lk(m_csMix);
p.Do(m_CRC); p.Do(m_CRC);
@ -618,6 +618,4 @@ void CUCode_Zelda::DoState(PointerWrap &p)
p.Do(m_UploadSetupInProgress); p.Do(m_UploadSetupInProgress);
m_rMailHandler.DoState(p); m_rMailHandler.DoState(p);
m_csMix.Leave();
} }

View File

@ -746,7 +746,7 @@ ContinueWithBlock:
// size is in stereo samples. // size is in stereo samples.
void CUCode_Zelda::MixAdd(short *_Buffer, int _Size) void CUCode_Zelda::MixAdd(short *_Buffer, int _Size)
{ {
m_csMix.Enter(); std::lock_guard<std::mutex> lk(m_csMix);
// Safety check // Safety check
if (_Size > 256 * 1024 - 8) if (_Size > 256 * 1024 - 8)
_Size = 256 * 1024 - 8; _Size = 256 * 1024 - 8;
@ -793,5 +793,4 @@ void CUCode_Zelda::MixAdd(short *_Buffer, int _Size)
_Buffer += 2; _Buffer += 2;
} }
m_csMix.Leave();
} }

View File

@ -86,7 +86,7 @@ protected:
bool NeedsResumeMail(); bool NeedsResumeMail();
CMailHandler& m_rMailHandler; CMailHandler& m_rMailHandler;
Common::CriticalSection m_csMix; std::mutex m_csMix;
enum EDSP_Codes enum EDSP_Codes
{ {

View File

@ -215,7 +215,7 @@ static unsigned char media_buffer[0x40];
// Needed because data and streaming audio access needs to be managed by the "drive" // 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) // (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 ejectDisc;
static int insertDisc; static int insertDisc;
@ -345,10 +345,8 @@ void ClearCoverInterrupt()
bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength) bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength)
{ {
// We won't need the crit sec when DTK streaming has been rewritten correctly. // We won't need the crit sec when DTK streaming has been rewritten correctly.
dvdread_section.Enter(); std::lock_guard<std::mutex> lk(dvdread_section);
bool retval = VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength); return VolumeHandler::ReadToPtr(Memory::GetPointer(_iRamAddress), _iDVDOffset, _iLength);
dvdread_section.Leave();
return retval;
} }
bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples) bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
@ -360,9 +358,10 @@ bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples)
return false; return false;
} }
_iNumSamples &= ~31; _iNumSamples &= ~31;
dvdread_section.Enter(); {
std::lock_guard<std::mutex> lk(dvdread_section);
VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples); VolumeHandler::ReadToPtr(_pDestBuffer, AudioPos, _iNumSamples);
dvdread_section.Leave(); }
// //
// FIX THIS // FIX THIS

View File

@ -26,7 +26,7 @@ int GeckoSockServer::client_count;
std::thread GeckoSockServer::connectionThread; std::thread GeckoSockServer::connectionThread;
volatile bool GeckoSockServer::server_running; volatile bool GeckoSockServer::server_running;
std::queue<sf::SocketTCP> GeckoSockServer::waiting_socks; std::queue<sf::SocketTCP> GeckoSockServer::waiting_socks;
Common::CriticalSection GeckoSockServer::connection_lock; std::mutex GeckoSockServer::connection_lock;
GeckoSockServer::GeckoSockServer() GeckoSockServer::GeckoSockServer()
: client_running(false) : client_running(false)
@ -76,9 +76,8 @@ void GeckoSockServer::GeckoConnectionWaiter()
{ {
if (server.Accept(new_client) == sf::Socket::Done) if (server.Accept(new_client) == sf::Socket::Done)
{ {
connection_lock.Enter(); std::lock_guard<std::mutex> lk(connection_lock);
waiting_socks.push(new_client); waiting_socks.push(new_client);
connection_lock.Leave();
} }
SLEEP(1); SLEEP(1);
} }
@ -89,7 +88,8 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
{ {
bool sock_filled = false; bool sock_filled = false;
connection_lock.Enter(); std::lock_guard<std::mutex> lk(connection_lock);
if (waiting_socks.size()) if (waiting_socks.size())
{ {
sock_to_fill = waiting_socks.front(); sock_to_fill = waiting_socks.front();
@ -106,7 +106,6 @@ bool GeckoSockServer::GetAvailableSock(sf::SocketTCP &sock_to_fill)
waiting_socks.pop(); waiting_socks.pop();
sock_filled = true; sock_filled = true;
} }
connection_lock.Leave();
return sock_filled; return sock_filled;
} }
@ -124,7 +123,9 @@ void GeckoSockServer::ClientThread()
u8 data; u8 data;
std::size_t got = 0; std::size_t got = 0;
transfer_lock.Enter(); {
std::lock_guard<std::mutex> lk(transfer_lock);
if (client.Receive((char*)&data, sizeof(data), got) if (client.Receive((char*)&data, sizeof(data), got)
== sf::Socket::Disconnected) == sf::Socket::Disconnected)
client_running = false; client_running = false;
@ -138,7 +139,8 @@ void GeckoSockServer::ClientThread()
client_running = false; client_running = false;
send_fifo.pop(); send_fifo.pop();
} }
transfer_lock.Leave(); } // unlock transfer
SLEEP(1); SLEEP(1);
} }
@ -173,35 +175,40 @@ void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize)
// PC -> Gecko // PC -> Gecko
// |= 0x08000000 if successful // |= 0x08000000 if successful
case CMD_RECV: case CMD_RECV:
transfer_lock.Enter(); {
std::lock_guard<std::mutex> lk(transfer_lock);
if (!recv_fifo.empty()) if (!recv_fifo.empty())
{ {
_uData = 0x08000000 | (recv_fifo.front() << 16); _uData = 0x08000000 | (recv_fifo.front() << 16);
recv_fifo.pop(); recv_fifo.pop();
} }
transfer_lock.Leave();
break; break;
}
// Gecko -> PC // Gecko -> PC
// |= 0x04000000 if successful // |= 0x04000000 if successful
case CMD_SEND: case CMD_SEND:
transfer_lock.Enter(); {
std::lock_guard<std::mutex> lk(transfer_lock);
send_fifo.push(_uData >> 20); send_fifo.push(_uData >> 20);
transfer_lock.Leave();
_uData = 0x04000000; _uData = 0x04000000;
break; break;
}
// Check if ok for Gecko -> PC, or FIFO full // Check if ok for Gecko -> PC, or FIFO full
// |= 0x04000000 if FIFO is not full // |= 0x04000000 if FIFO is not full
case CMD_CHK_TX: case CMD_CHK_TX:
_uData = 0x04000000; _uData = 0x04000000;
break; break;
// Check if data in FIFO for PC -> Gecko, or FIFO empty // Check if data in FIFO for PC -> Gecko, or FIFO empty
// |= 0x04000000 if data in recv FIFO // |= 0x04000000 if data in recv FIFO
case CMD_CHK_RX: case CMD_CHK_RX:
transfer_lock.Enter(); {
std::lock_guard<std::mutex> lk(transfer_lock);
_uData = recv_fifo.empty() ? 0 : 0x04000000; _uData = recv_fifo.empty() ? 0 : 0x04000000;
transfer_lock.Leave();
break; break;
}
default: default:
ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData); ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData);

View File

@ -34,7 +34,7 @@ public:
sf::SocketTCP client; sf::SocketTCP client;
void ClientThread(); void ClientThread();
std::thread clientThread; std::thread clientThread;
Common::CriticalSection transfer_lock; std::mutex transfer_lock;
std::queue<u8> send_fifo; std::queue<u8> send_fifo;
std::queue<u8> recv_fifo; std::queue<u8> recv_fifo;
@ -50,7 +50,7 @@ private:
static volatile bool server_running; static volatile bool server_running;
static std::thread connectionThread; static std::thread connectionThread;
static std::queue<sf::SocketTCP> waiting_socks; static std::queue<sf::SocketTCP> waiting_socks;
static Common::CriticalSection connection_lock; static std::mutex connection_lock;
}; };
class CEXIGecko class CEXIGecko

View File

@ -65,8 +65,9 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// wtf is this? // wtf is this?
_pPADStatus->button = PAD_USE_ORIGIN; _pPADStatus->button = PAD_USE_ORIGIN;
// try lock std::unique_lock<std::mutex> lk(g_plugin.controls_lock, std::try_to_lock);
if (false == g_plugin.controls_crit.TryEnter())
if (!lk.owns_lock())
{ {
// if gui has lock (messing with controls), skip this input cycle // if gui has lock (messing with controls), skip this input cycle
// center axes and return // center axes and return
@ -86,9 +87,6 @@ void GetStatus(u8 _numPAD, SPADStatus* _pPADStatus)
// get input // get input
((GCPad*)g_plugin.controllers[_numPAD])->GetInput(_pPADStatus); ((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) void Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
{ {
// enter std::unique_lock<std::mutex> lk(g_plugin.controls_lock, std::try_to_lock);
if ( g_plugin.controls_crit.TryEnter() )
if (!lk.owns_lock())
{ {
// TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time // TODO: this has potential to not stop rumble if user is messing with GUI at the perfect time
// set rumble // set rumble
((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( 1 == _uType && _uStrength > 2 ); ((GCPad*)g_plugin.controllers[ _numPAD ])->SetOutput( 1 == _uType && _uStrength > 2 );
// leave
g_plugin.controls_crit.Leave();
} }
} }

View File

@ -24,7 +24,7 @@
static std::thread connectionThread; static std::thread connectionThread;
static std::queue<sf::SocketTCP> waiting_socks; static std::queue<sf::SocketTCP> waiting_socks;
static Common::CriticalSection cs_gba; static std::mutex cs_gba;
namespace { volatile bool server_running; } namespace { volatile bool server_running; }
// --- GameBoy Advance "Link Cable" --- // --- GameBoy Advance "Link Cable" ---
@ -47,9 +47,8 @@ void GBAConnectionWaiter()
{ {
if (server.Accept(new_client) == sf::Socket::Done) if (server.Accept(new_client) == sf::Socket::Done)
{ {
cs_gba.Enter(); std::lock_guard<std::mutex> lk(cs_gba);
waiting_socks.push(new_client); waiting_socks.push(new_client);
cs_gba.Leave();
} }
SLEEP(1); SLEEP(1);
} }
@ -68,14 +67,14 @@ bool GetAvailableSock(sf::SocketTCP& sock_to_fill)
{ {
bool sock_filled = false; bool sock_filled = false;
cs_gba.Enter(); std::lock_guard<std::mutex> lk(cs_gba);
if (waiting_socks.size()) if (waiting_socks.size())
{ {
sock_to_fill = waiting_socks.front(); sock_to_fill = waiting_socks.front();
waiting_socks.pop(); waiting_socks.pop();
sock_filled = true; sock_filled = true;
} }
cs_gba.Leave();
return sock_filled; return sock_filled;
} }

View File

@ -93,8 +93,8 @@ void Update(int _number)
{ {
//PanicAlert( "Wiimote_Update" ); //PanicAlert( "Wiimote_Update" );
// TODO: change this to a TryEnter, and make it give empty input on failure // TODO: change this to a try_to_lock, and make it give empty input on failure
g_plugin.controls_crit.Enter(); std::lock_guard<std::mutex> lk(g_plugin.controls_lock);
static int _last_number = 4; static int _last_number = 4;
if (_number <= _last_number) if (_number <= _last_number)
@ -108,8 +108,6 @@ void Update(int _number)
((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update(); ((WiimoteEmu::Wiimote*)g_plugin.controllers[_number])->Update();
else else
WiimoteReal::Update(_number); WiimoteReal::Update(_number);
g_plugin.controls_crit.Leave();
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________

View File

@ -248,14 +248,14 @@ void Wiimote::RequestStatus(const wm_request_status* const rs)
{ {
using namespace WiimoteReal; using namespace WiimoteReal;
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[m_index]) if (g_wiimotes[m_index])
{ {
wm_request_status rpt; wm_request_status rpt;
rpt.rumble = 0; rpt.rumble = 0;
g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt)); g_wiimotes[m_index]->SendPacket(WM_REQUEST_STATUS, &rpt, sizeof(rpt));
} }
g_refresh_critsec.Leave();
return; return;
} }

View File

@ -661,7 +661,7 @@ void Wiimote::Update()
{ {
using namespace WiimoteReal; using namespace WiimoteReal;
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[m_index]) if (g_wiimotes[m_index])
{ {
Report rpt = g_wiimotes[m_index]->ProcessReadQueue(); Report rpt = g_wiimotes[m_index]->ProcessReadQueue();
@ -736,7 +736,6 @@ void Wiimote::Update()
delete[] real_data; delete[] real_data;
} }
} }
g_refresh_critsec.Leave();
} }
if (Frame::IsRecordingInput()) if (Frame::IsRecordingInput())
{ {

View File

@ -35,7 +35,7 @@ namespace WiimoteReal
bool g_real_wiimotes_initialized = false; bool g_real_wiimotes_initialized = false;
unsigned int g_wiimotes_found = 0; unsigned int g_wiimotes_found = 0;
Common::CriticalSection g_refresh_critsec; std::mutex g_refresh_lock;
Wiimote *g_wiimotes[MAX_WIIMOTES]; Wiimote *g_wiimotes[MAX_WIIMOTES];
@ -439,11 +439,11 @@ void Shutdown(void)
// This is called from the GUI thread // This is called from the GUI thread
void Refresh() void Refresh()
{ {
std::lock_guard<std::mutex> lk(g_refresh_lock);
#ifdef _WIN32 #ifdef _WIN32
g_refresh_critsec.Enter();
Shutdown(); Shutdown();
Initialize(); Initialize();
g_refresh_critsec.Leave();
#else #else
// Make sure real wiimotes have been initialized // Make sure real wiimotes have been initialized
if (!g_real_wiimotes_initialized) if (!g_real_wiimotes_initialized)
@ -458,8 +458,6 @@ void Refresh()
if (WIIMOTE_SRC_REAL & g_wiimote_sources[i]) if (WIIMOTE_SRC_REAL & g_wiimote_sources[i])
++wanted_wiimotes; ++wanted_wiimotes;
g_refresh_critsec.Enter();
// Remove wiimotes that are paired with slots no longer configured for a // Remove wiimotes that are paired with slots no longer configured for a
// real wiimote or that are disconnected // real wiimote or that are disconnected
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i) for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
@ -486,50 +484,40 @@ void Refresh()
g_wiimotes_found = num_wiimotes; g_wiimotes_found = num_wiimotes;
} }
g_refresh_critsec.Leave();
#endif #endif
} }
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{ {
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber]) if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size); g_wiimotes[_WiimoteNumber]->InterruptChannel(_channelID, _pData, _Size);
g_refresh_critsec.Leave();
} }
void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size) void ControlChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size)
{ {
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber]) if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size); g_wiimotes[_WiimoteNumber]->ControlChannel(_channelID, _pData, _Size);
g_refresh_critsec.Leave();
} }
// Read the Wiimote once // Read the Wiimote once
void Update(int _WiimoteNumber) void Update(int _WiimoteNumber)
{ {
g_refresh_critsec.Enter(); std::lock_guard<std::mutex> lk(g_refresh_lock);
if (g_wiimotes[_WiimoteNumber]) if (g_wiimotes[_WiimoteNumber])
g_wiimotes[_WiimoteNumber]->Update(); g_wiimotes[_WiimoteNumber]->Update();
g_refresh_critsec.Leave();
} }
void StateChange(EMUSTATE_CHANGE newState) void StateChange(EMUSTATE_CHANGE newState)
{ {
//g_refresh_critsec.Enter(); // enter //std::lock_guard<std::mutex> lk(g_refresh_lock);
// TODO: disable/enable auto reporting, maybe // TODO: disable/enable auto reporting, maybe
//g_refresh_critsec.Leave(); // leave
} }
}; // end of namespace }; // end of namespace

View File

@ -101,7 +101,7 @@ private:
Common::FifoQueue<Report> m_audio_reports; Common::FifoQueue<Report> m_audio_reports;
}; };
extern Common::CriticalSection g_refresh_critsec; extern std::mutex g_refresh_lock;
extern Wiimote *g_wiimotes[4]; extern Wiimote *g_wiimotes[4];
void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size); void InterruptChannel(int _WiimoteNumber, u16 _channelID, const void* _pData, u32 _Size);

View File

@ -27,7 +27,7 @@
// for wiimote/ OSD messages // for wiimote/ OSD messages
#include "Core.h" #include "Core.h"
Common::CriticalSection crit_netplay_ptr; std::mutex crit_netplay_ptr;
static NetPlay* netplay_ptr = NULL; static NetPlay* netplay_ptr = NULL;
#define RPT_SIZE_HACK (1 << 16) #define RPT_SIZE_HACK (1 << 16)
@ -42,20 +42,20 @@ NetPlay::NetPlay(NetPlayUI* dialog)
void NetPlay_Enable(NetPlay* const np) void NetPlay_Enable(NetPlay* const np)
{ {
CritLocker crit(crit_netplay_ptr); // probably safe without a lock std::lock_guard<std::mutex> lk(crit_netplay_ptr);
netplay_ptr = np; netplay_ptr = np;
} }
void NetPlay_Disable() void NetPlay_Disable()
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
netplay_ptr = NULL; netplay_ptr = NULL;
} }
// called from ---GUI--- thread // called from ---GUI--- thread
NetPlay::~NetPlay() NetPlay::~NetPlay()
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
netplay_ptr = NULL; netplay_ptr = NULL;
// not perfect // not perfect
@ -116,7 +116,8 @@ void NetPlay::ClearBuffers()
// called from ---CPU--- thread // called from ---CPU--- thread
bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues) bool NetPlay::GetNetPads(const u8 pad_nb, const SPADStatus* const pad_status, NetPad* const netvalues)
{ {
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
// in game mapping for this local pad // in game mapping for this local pad
unsigned int in_game_num = m_local_player->pad_map[pad_nb]; 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; //Common::Timer bufftimer;
//bufftimer.Start(); //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().assign((char*)_pData, (char*)_pData + _Size);
m_wiimote_input[_number].back().channel = _channelID; m_wiimote_input[_number].back().channel = _channelID;
} }
m_crit.players.Leave();
} }
// called from ---CPU--- thread // called from ---CPU--- thread
void NetPlay::WiimoteUpdate(int _number) void NetPlay::WiimoteUpdate(int _number)
{ {
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
// in game mapping for this local wiimote // 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 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_wiimote_input[_number].clear();
} }
m_crit.players.Leave(); } // unlock players
if (0 == m_wiimote_buffer[_number].Size()) 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) // called from ---GUI--- thread and ---NETPLAY--- thread (client side)
bool NetPlay::StopGame() bool NetPlay::StopGame()
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (false == m_is_running) if (false == m_is_running)
{ {
@ -288,7 +288,7 @@ u8 NetPlay::GetPadNum(u8 numPAD)
// Actual Core function which is called on every frame // Actual Core function which is called on every frame
bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus) bool CSIDevice_GCController::NetPlay_GetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr) if (netplay_ptr)
return netplay_ptr->GetNetPads(numPAD, &PadStatus, (NetPad*)PADStatus); 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 // so all players' games get the same time
u32 CEXIIPL::NetPlay_GetGCTime() u32 CEXIIPL::NetPlay_GetGCTime()
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr) if (netplay_ptr)
return 1272737767; // watev return 1272737767; // watev
@ -312,7 +312,7 @@ u32 CEXIIPL::NetPlay_GetGCTime()
// return the local pad num that should rumble given a ingame pad num // return the local pad num that should rumble given a ingame pad num
u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD) u8 CSIDevice_GCController::NetPlay_GetPadNum(u8 numPAD)
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr) if (netplay_ptr)
return netplay_ptr->GetPadNum(numPAD); 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 _number, u16 _channelID, const void* _pData, u32& _Size)
bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&) bool CWII_IPC_HLE_WiiMote::NetPlay_WiimoteInput(int, u16, const void*, u32&)
{ {
CritLocker crit(crit_netplay_ptr); std::lock_guard<std::mutex> lk(crit_netplay_ptr);
if (netplay_ptr) if (netplay_ptr)
//{ //{

View File

@ -75,19 +75,6 @@ enum
CON_ERR_VERSION_MISMATCH 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 class NetPlayUI
{ {
public: public:
@ -135,9 +122,9 @@ protected:
struct struct
{ {
Common::CriticalSection game; std::recursive_mutex game;
// lock order // lock order
Common::CriticalSection players, send; std::recursive_mutex players, send;
} m_crit; } m_crit;
class Player class Player

View File

@ -93,9 +93,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> player.name; packet >> player.name;
packet >> player.revision; packet >> player.revision;
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
m_players[player.pid] = player; m_players[player.pid] = player;
m_crit.players.Leave(); }
m_dialog->Update(); m_dialog->Update();
} }
@ -106,9 +107,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
PlayerId pid; PlayerId pid;
packet >> pid; packet >> pid;
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
m_players.erase(m_players.find(pid)); m_players.erase(m_players.find(pid));
m_crit.players.Leave(); }
m_dialog->Update(); m_dialog->Update();
} }
@ -137,12 +139,13 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
PlayerId pid; PlayerId pid;
packet >> pid; packet >> pid;
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
Player& player = m_players[pid]; Player& player = m_players[pid];
for (unsigned int i=0; i<4; ++i) for (unsigned int i=0; i<4; ++i)
packet >> player.pad_map[i]; packet >> player.pad_map[i];
m_crit.players.Leave(); }
m_dialog->Update(); m_dialog->Update();
} }
@ -171,10 +174,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_CHANGE_GAME : case NP_MSG_CHANGE_GAME :
{ {
// lock here? {
m_crit.game.Enter(); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
packet >> m_selected_game; packet >> m_selected_game;
m_crit.game.Leave(); }
// update gui // update gui
m_dialog->OnMsgChangeGame(m_selected_game); m_dialog->OnMsgChangeGame(m_selected_game);
@ -183,9 +186,10 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_START_GAME : case NP_MSG_START_GAME :
{ {
m_crit.game.Enter(); // lock buffer {
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
packet >> m_current_game; packet >> m_current_game;
m_crit.game.Leave(); }
m_dialog->OnMsgStartGame(); m_dialog->OnMsgStartGame();
} }
@ -200,7 +204,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
case NP_MSG_DISABLE_GAME : case NP_MSG_DISABLE_GAME :
{ {
PanicAlertT("Other client disconnected while game is running!! NetPlay is disabled. You manually stop the 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<std::recursive_mutex> lkg(m_crit.game);
m_is_running = false; m_is_running = false;
NetPlay_Disable(); NetPlay_Disable();
} }
@ -215,7 +219,7 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
spac << (MessageId)NP_MSG_PONG; spac << (MessageId)NP_MSG_PONG;
spac << ping_key; spac << ping_key;
CritLocker send_lock(m_crit.send); std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac); m_socket.Send(spac);
} }
break; break;
@ -263,7 +267,7 @@ void NetPlayClient::ThreadFunc()
// called from ---GUI--- thread // called from ---GUI--- thread
void NetPlayClient::GetPlayerList(std::string& list, std::vector<int>& pid_list) void NetPlayClient::GetPlayerList(std::string& list, std::vector<int>& pid_list)
{ {
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::ostringstream ss; std::ostringstream ss;
@ -287,7 +291,7 @@ void NetPlayClient::SendChatMessage(const std::string& msg)
spac << (MessageId)NP_MSG_CHAT_MESSAGE; spac << (MessageId)NP_MSG_CHAT_MESSAGE;
spac << msg; spac << msg;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac); 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 << local_nb; // local pad num
spac << np.nHi << np.nLo; spac << np.nHi << np.nLo;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac); m_socket.Send(spac);
} }
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayClient::StartGame(const std::string &path) bool NetPlayClient::StartGame(const std::string &path)
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (false == NetPlay::StartGame(path)) if (false == NetPlay::StartGame(path))
return false; return false;
@ -317,7 +321,7 @@ bool NetPlayClient::StartGame(const std::string &path)
spac << (MessageId)NP_MSG_START_GAME; spac << (MessageId)NP_MSG_START_GAME;
spac << m_current_game; spac << m_current_game;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac); m_socket.Send(spac);
return true; return true;

View File

@ -60,8 +60,7 @@ void NetPlayServer::ThreadFunc()
spac << (MessageId)NP_MSG_PING; spac << (MessageId)NP_MSG_PING;
spac << m_ping_key; spac << m_ping_key;
//CritLocker player_lock(m_crit.players); std::lock_guard<std::recursive_mutex> lks(m_crit.send);
CritLocker send_lock(m_crit.send);
m_ping_timer.Start(); m_ping_timer.Start();
SendToClients(spac); SendToClients(spac);
@ -80,9 +79,11 @@ void NetPlayServer::ThreadFunc()
sf::SocketTCP accept_socket; sf::SocketTCP accept_socket;
m_socket.Accept(accept_socket); m_socket.Accept(accept_socket);
m_crit.game.Enter(); // lock game state unsigned int error;
const unsigned int error = OnConnect(accept_socket); {
m_crit.game.Leave(); std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
error = OnConnect(accept_socket);
}
if (error) if (error)
{ {
@ -108,14 +109,15 @@ void NetPlayServer::ThreadFunc()
//case sf::Socket::Disconnected : //case sf::Socket::Disconnected :
default : default :
m_crit.game.Enter(); // lock game state {
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
OnDisconnect(ready_socket); OnDisconnect(ready_socket);
m_crit.game.Leave();
break; break;
} }
} }
} }
} }
}
// close listening socket and client sockets // close listening socket and client sockets
{ {
@ -200,8 +202,8 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
} }
// ENTER {
m_crit.send.Enter(); std::lock_guard<std::recursive_mutex> lks(m_crit.send);
// send join message to already connected clients // send join message to already connected clients
sf::Packet spac; sf::Packet spac;
@ -230,16 +232,16 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket)
socket.Send(spac); socket.Send(spac);
} }
// LEAVE } // unlock send
m_crit.send.Leave();
// add client to the player list // add client to the player list
m_crit.players.Enter(); // lock players {
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
m_players[socket] = player; m_players[socket] = player;
m_crit.send.Enter(); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
UpdatePadMapping(); // sync pad mappings with everyone UpdatePadMapping(); // sync pad mappings with everyone
m_crit.send.Leave(); }
m_crit.players.Leave();
// add client to selector/ used for receiving // add client to selector/ used for receiving
m_selector.Add(socket); m_selector.Add(socket);
@ -255,14 +257,14 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
if (m_is_running) if (m_is_running)
{ {
PanicAlertT("Client disconnect while game is running!! NetPlay is disabled. You must manually stop the game."); 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<std::recursive_mutex> lkg(m_crit.game);
m_is_running = false; m_is_running = false;
NetPlay_Disable(); NetPlay_Disable();
sf::Packet spac; sf::Packet spac;
spac << (MessageId)NP_MSG_DISABLE_GAME; spac << (MessageId)NP_MSG_DISABLE_GAME;
// this thread doesnt need players lock // this thread doesnt need players lock
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
} }
@ -272,11 +274,11 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
m_selector.Remove(socket); m_selector.Remove(socket);
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
m_players.erase(m_players.find(socket)); m_players.erase(m_players.find(socket));
// alert other players of disconnect // alert other players of disconnect
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
m_dialog->Update(); m_dialog->Update();
@ -287,7 +289,7 @@ unsigned int NetPlayServer::OnDisconnect(sf::SocketTCP& socket)
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayServer::GetPadMapping(const int pid, int map[]) bool NetPlayServer::GetPadMapping(const int pid, int map[])
{ {
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::const_iterator std::map<sf::SocketTCP, Client>::const_iterator
i = m_players.begin(), i = m_players.begin(),
e = m_players.end(); e = m_players.end();
@ -309,11 +311,11 @@ bool NetPlayServer::GetPadMapping(const int pid, int map[])
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayServer::SetPadMapping(const int pid, const int map[]) bool NetPlayServer::SetPadMapping(const int pid, const int map[])
{ {
CritLocker game_lock(m_crit.game); // lock game std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (m_is_running) if (m_is_running)
return false; return false;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::iterator std::map<sf::SocketTCP, Client>::iterator
i = m_players.begin(), i = m_players.begin(),
e = m_players.end(); e = m_players.end();
@ -340,7 +342,7 @@ bool NetPlayServer::SetPadMapping(const int pid, const int map[])
i->second.pad_map[p] = -1; i->second.pad_map[p] = -1;
} }
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
UpdatePadMapping(); // sync pad mappings with everyone UpdatePadMapping(); // sync pad mappings with everyone
m_dialog->Update(); m_dialog->Update();
@ -369,7 +371,7 @@ void NetPlayServer::UpdatePadMapping()
// called from ---GUI--- thread and ---NETPLAY--- thread // called from ---GUI--- thread and ---NETPLAY--- thread
u64 NetPlayServer::CalculateMinimumBufferTime() u64 NetPlayServer::CalculateMinimumBufferTime()
{ {
CritLocker player_lock(m_crit.players); std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::map<sf::SocketTCP, Client>::const_iterator std::map<sf::SocketTCP, Client>::const_iterator
i = m_players.begin(), i = m_players.begin(),
@ -392,7 +394,7 @@ u64 NetPlayServer::CalculateMinimumBufferTime()
// called from ---GUI--- thread and ---NETPLAY--- thread // called from ---GUI--- thread and ---NETPLAY--- thread
void NetPlayServer::AdjustPadBufferSize(unsigned int size) void NetPlayServer::AdjustPadBufferSize(unsigned int size)
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
m_target_buffer_size = size; m_target_buffer_size = size;
@ -401,8 +403,8 @@ void NetPlayServer::AdjustPadBufferSize(unsigned int size)
spac << (MessageId)NP_MSG_PAD_BUFFER; spac << (MessageId)NP_MSG_PAD_BUFFER;
spac << (u32)m_target_buffer_size; spac << (u32)m_target_buffer_size;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
} }
@ -429,9 +431,10 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
spac << player.pid; spac << player.pid;
spac << msg; spac << msg;
m_crit.send.Enter(); // lock send {
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac, player.pid); SendToClients(spac, player.pid);
m_crit.send.Leave(); }
// add to gui // add to gui
std::ostringstream ss; std::ostringstream ss;
@ -471,7 +474,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
spac << map; // in game mapping spac << map; // in game mapping
spac << np.nHi << np.nLo; spac << np.nHi << np.nLo;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac, player.pid); SendToClients(spac, player.pid);
} }
break; break;
@ -510,7 +513,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket)
// called from ---GUI--- thread // called from ---GUI--- thread
void NetPlayServer::GetPlayerList(std::string& list, std::vector<int>& pid_list) void NetPlayServer::GetPlayerList(std::string& list, std::vector<int>& pid_list)
{ {
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::ostringstream ss; std::ostringstream ss;
@ -534,15 +537,15 @@ void NetPlayServer::SendChatMessage(const std::string& msg)
spac << (PlayerId)0; // server id always 0 spac << (PlayerId)0; // server id always 0
spac << msg; spac << msg;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
} }
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayServer::ChangeGame(const std::string &game) bool NetPlayServer::ChangeGame(const std::string &game)
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
m_selected_game = game; m_selected_game = game;
@ -551,8 +554,8 @@ bool NetPlayServer::ChangeGame(const std::string &game)
spac << (MessageId)NP_MSG_CHANGE_GAME; spac << (MessageId)NP_MSG_CHANGE_GAME;
spac << game; spac << game;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
return true; 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 << m_local_player->pad_map[local_nb]; // in-game pad num
spac << np.nHi << np.nLo; spac << np.nHi << np.nLo;
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
} }
// called from ---GUI--- thread // called from ---GUI--- thread
bool NetPlayServer::StartGame(const std::string &path) bool NetPlayServer::StartGame(const std::string &path)
{ {
CritLocker game_lock(m_crit.game); // lock game state std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
if (false == NetPlay::StartGame(path)) if (false == NetPlay::StartGame(path))
return false; return false;
@ -590,8 +593,8 @@ bool NetPlayServer::StartGame(const std::string &path)
spac << (MessageId)NP_MSG_START_GAME; spac << (MessageId)NP_MSG_START_GAME;
spac << m_current_game; spac << m_current_game;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
return true; return true;
@ -608,8 +611,8 @@ bool NetPlayServer::StopGame()
sf::Packet spac; sf::Packet spac;
spac << (MessageId)NP_MSG_STOP_GAME; spac << (MessageId)NP_MSG_STOP_GAME;
CritLocker player_lock(m_crit.players); // lock players std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
CritLocker send_lock(m_crit.send); // lock send std::lock_guard<std::recursive_mutex> lks(m_crit.send);
SendToClients(spac); SendToClients(spac);
return true; return true;

View File

@ -36,7 +36,7 @@
#endif #endif
#include "State.h" #include "State.h"
Common::CriticalSection cs_frameSkip; std::mutex cs_frameSkip;
namespace Frame { namespace Frame {
@ -95,7 +95,7 @@ void FrameUpdate()
void SetFrameSkipping(unsigned int framesToSkip) void SetFrameSkipping(unsigned int framesToSkip)
{ {
cs_frameSkip.Enter(); std::lock_guard<std::mutex> lk(cs_frameSkip);
g_framesToSkip = framesToSkip; g_framesToSkip = framesToSkip;
g_frameSkipCounter = 0; g_frameSkipCounter = 0;
@ -104,8 +104,6 @@ void SetFrameSkipping(unsigned int framesToSkip)
// as this won't be changed anymore when frameskip is turned off // as this won't be changed anymore when frameskip is turned off
if (framesToSkip == 0) if (framesToSkip == 0)
g_video_backend->Video_SetRendering(true); g_video_backend->Video_SetRendering(true);
cs_frameSkip.Leave();
} }
int FrameSkippingFactor() int FrameSkippingFactor()
@ -138,15 +136,13 @@ void FrameSkipping()
// Frameskipping will desync movie playback // Frameskipping will desync movie playback
if (!IsPlayingInput() && !IsRecordingInput()) if (!IsPlayingInput() && !IsRecordingInput())
{ {
cs_frameSkip.Enter(); std::lock_guard<std::mutex> lk(cs_frameSkip);
g_frameSkipCounter++; g_frameSkipCounter++;
if (g_frameSkipCounter > g_framesToSkip || Core::report_slow(g_frameSkipCounter) == false) if (g_frameSkipCounter > g_framesToSkip || Core::report_slow(g_frameSkipCounter) == false)
g_frameSkipCounter = 0; g_frameSkipCounter = 0;
g_video_backend->Video_SetRendering(!g_frameSkipCounter); g_video_backend->Video_SetRendering(!g_frameSkipCounter);
cs_frameSkip.Leave();
} }
} }

View File

@ -121,8 +121,6 @@ CCodeWindow::CCodeWindow(const SCoreStartupParameter& _LocalCoreStartupParameter
sizerLeft->Fit(this); sizerLeft->Fit(this);
sizerBig->Fit(this); sizerBig->Fit(this);
sync_event.Init();
} }
wxMenuBar *CCodeWindow::GetMenuBar() wxMenuBar *CCodeWindow::GetMenuBar()

View File

@ -354,8 +354,6 @@ CFrame::CFrame(wxFrame* parent,
bFloatWindow[i] = false; bFloatWindow[i] = false;
#ifdef __WXGTK__ #ifdef __WXGTK__
panic_event.Init();
keystate_event.Init();
bKeyStateResult = false; bKeyStateResult = false;
#endif #endif
@ -492,11 +490,6 @@ CFrame::~CFrame()
ClosePages(); ClosePages();
#ifdef __WXGTK__
panic_event.Shutdown();
keystate_event.Shutdown();
#endif
delete m_Mgr; delete m_Mgr;
} }

View File

@ -278,9 +278,8 @@ void GamepadPage::ClearAll(wxCommandEvent&)
// no point in using the real ControllerInterface i guess // no point in using the real ControllerInterface i guess
ControllerInterface face; ControllerInterface face;
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(face); controller->UpdateReferences(face);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -289,9 +288,8 @@ void GamepadPage::LoadDefaults(wxCommandEvent&)
{ {
controller->LoadDefaults(g_controller_interface); controller->LoadDefaults(g_controller_interface);
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(g_controller_interface); controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -300,9 +298,8 @@ void ControlDialog::SetControl(wxCommandEvent&)
{ {
control_reference->expression = STR_FROM_WXSTR(textctrl->GetValue()); control_reference->expression = STR_FROM_WXSTR(textctrl->GetValue());
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -318,9 +315,8 @@ void GamepadPage::SetDevice(wxCommandEvent&)
controller->UpdateDefaultDevice(); controller->UpdateDefaultDevice();
// update references // update references
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(g_controller_interface); controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave(); // leave
} }
void ControlDialog::SetDevice(wxCommandEvent&) void ControlDialog::SetDevice(wxCommandEvent&)
@ -338,9 +334,8 @@ void ControlDialog::ClearControl(wxCommandEvent&)
{ {
control_reference->expression.clear(); control_reference->expression.clear();
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -363,9 +358,8 @@ void ControlDialog::SetSelectedControl(wxCommandEvent&)
control_reference->expression = STR_FROM_WXSTR(expr); control_reference->expression = STR_FROM_WXSTR(expr);
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
@ -395,25 +389,22 @@ void ControlDialog::AppendControl(wxCommandEvent& event)
control_reference->expression = STR_FROM_WXSTR(expr); control_reference->expression = STR_FROM_WXSTR(expr);
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device); g_controller_interface.UpdateReference(control_reference, m_parent->controller->default_device);
m_plugin.controls_crit.Leave(); // leave
UpdateGUI(); UpdateGUI();
} }
void GamepadPage::AdjustSetting(wxCommandEvent& event) void GamepadPage::AdjustSetting(wxCommandEvent& event)
{ {
m_plugin.controls_crit.Enter(); // enter / prolly fine not being here std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
((PadSetting*)((wxControl*)event.GetEventObject())->GetClientData())->UpdateValue(); ((PadSetting*)((wxControl*)event.GetEventObject())->GetClientData())->UpdateValue();
m_plugin.controls_crit.Leave(); // leave
} }
void GamepadPage::AdjustControlOption(wxCommandEvent&) void GamepadPage::AdjustControlOption(wxCommandEvent&)
{ {
m_plugin.controls_crit.Enter(); // enter / prolly fine not being here std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
m_control_dialog->control_reference->range = (ControlState)(m_control_dialog->range_slider->GetValue()) / SLIDER_TICK_COUNT; 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) void GamepadPage::ConfigControl(wxCommandEvent& event)
@ -432,9 +423,8 @@ void GamepadPage::ClearControl(wxCommandEvent& event)
btn->control_reference->expression.clear(); btn->control_reference->expression.clear();
btn->control_reference->range = 1.0f; btn->control_reference->range = 1.0f;
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->UpdateReferences(g_controller_interface); controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave(); // leave
// update changes // update changes
UpdateGUI(); UpdateGUI();
@ -453,9 +443,8 @@ void ControlDialog::DetectControl(wxCommandEvent& event)
// apparently, this makes the "waiting" text work on Linux // apparently, this makes the "waiting" text work on Linux
wxTheApp->Yield(); wxTheApp->Yield();
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
ControllerInterface::Device::Control* const ctrl = control_reference->Detect(DETECT_WAIT_TIME, dev); 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 we got input, select it in the list
if (ctrl) if (ctrl)
@ -478,7 +467,7 @@ void GamepadPage::DetectControl(wxCommandEvent& event)
// apparently, this makes the "waiting" text work on Linux // apparently, this makes the "waiting" text work on Linux
wxTheApp->Yield(); wxTheApp->Yield();
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
ControllerInterface::Device::Control* const ctrl = btn->control_reference->Detect(DETECT_WAIT_TIME, dev); ControllerInterface::Device::Control* const ctrl = btn->control_reference->Detect(DETECT_WAIT_TIME, dev);
// if we got input, update expression and reference // 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); 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)); btn->SetLabel(WXSTR_FROM_STR(btn->control_reference->expression));
} }
} }
@ -597,10 +584,9 @@ void GamepadPage::LoadProfile(wxCommandEvent&)
IniFile inifile; IniFile inifile;
inifile.Load(fname); inifile.Load(fname);
m_plugin.controls_crit.Enter(); std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
controller->LoadConfig(inifile.GetOrCreateSection("Profile")); controller->LoadConfig(inifile.GetOrCreateSection("Profile"));
controller->UpdateReferences(g_controller_interface); controller->UpdateReferences(g_controller_interface);
m_plugin.controls_crit.Leave();
UpdateGUI(); UpdateGUI();
} }
@ -662,7 +648,7 @@ void InputConfigDialog::UpdateDeviceComboBox()
void GamepadPage::RefreshDevices(wxCommandEvent&) void GamepadPage::RefreshDevices(wxCommandEvent&)
{ {
m_plugin.controls_crit.Enter(); // enter std::lock_guard<std::mutex> lk(m_plugin.controls_lock);
// refresh devices // refresh devices
g_controller_interface.Shutdown(); g_controller_interface.Shutdown();
@ -673,8 +659,6 @@ void GamepadPage::RefreshDevices(wxCommandEvent&)
// update device cbox // update device cbox
m_config_dialog->UpdateDeviceComboBox(); m_config_dialog->UpdateDeviceComboBox();
m_plugin.controls_crit.Leave(); // leave
} }
ControlGroupBox::~ControlGroupBox() ControlGroupBox::~ControlGroupBox()

View File

@ -22,8 +22,10 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD); wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
g_controller_interface.UpdateInput(); g_controller_interface.UpdateInput();
// don't want game thread updating input when we are using it here // don't want game thread updating input when we are using it here
if (false == g_controller_interface.update_lock.TryEnter()) std::unique_lock<std::mutex> lk(g_controller_interface.update_lock, std::try_to_lock);
if (!lk.owns_lock())
return; return;
GamepadPage* const current_page = (GamepadPage*)m_pad_notebook->GetPage(m_pad_notebook->GetSelection()); 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)->static_bitmap->SetBitmap(bitmap);
} }
} }
g_controller_interface.update_lock.Leave();
} }

View File

@ -42,7 +42,6 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos,
, x(0), y(0), winpos(0) , x(0), y(0), winpos(0)
, Parent(parent) , m_LogAccess(true) , Parent(parent) , m_LogAccess(true)
, m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL) , m_Log(NULL), m_cmdline(NULL), m_FontChoice(NULL)
, m_LogSection(1)
, m_SJISConv(wxT("")) , m_SJISConv(wxT(""))
{ {
#ifdef _WIN32 #ifdef _WIN32
@ -212,11 +211,12 @@ void CLogWindow::OnClear(wxCommandEvent& WXUNUSED (event))
{ {
m_Log->Clear(); m_Log->Clear();
m_LogSection.Enter(); {
std::lock_guard<std::mutex> lk(m_LogSection);
int msgQueueSize = (int)msgQueue.size(); int msgQueueSize = (int)msgQueue.size();
for (int i = 0; i < msgQueueSize; i++) for (int i = 0; i < msgQueueSize; i++)
msgQueue.pop(); msgQueue.pop();
m_LogSection.Leave(); }
m_LogManager->getConsoleListener()->ClearScreen(); m_LogManager->getConsoleListener()->ClearScreen();
} }
@ -308,7 +308,8 @@ void CLogWindow::UpdateLog()
m_LogTimer->Stop(); m_LogTimer->Stop();
m_LogSection.Enter(); {
std::lock_guard<std::mutex> lk(m_LogSection);
int msgQueueSize = (int)msgQueue.size(); int msgQueueSize = (int)msgQueue.size();
for (int i = 0; i < msgQueueSize; i++) for (int i = 0; i < msgQueueSize; i++)
{ {
@ -348,16 +349,16 @@ void CLogWindow::UpdateLog()
} }
msgQueue.pop(); msgQueue.pop();
} }
m_LogSection.Leave(); } // unlock log
m_LogTimer->Start(UPDATETIME); m_LogTimer->Start(UPDATETIME);
} }
void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text) void CLogWindow::Log(LogTypes::LOG_LEVELS level, const char *text)
{ {
m_LogSection.Enter(); std::lock_guard<std::mutex> lk(m_LogSection);
if (msgQueue.size() >= 100) if (msgQueue.size() >= 100)
msgQueue.pop(); msgQueue.pop();
msgQueue.push(std::pair<u8, wxString>((u8)level, wxString(text, m_SJISConv))); msgQueue.push(std::pair<u8, wxString>((u8)level, wxString(text, m_SJISConv)));
m_LogSection.Leave();
} }

View File

@ -72,7 +72,7 @@ private:
wxChoice *m_FontChoice; wxChoice *m_FontChoice;
wxCheckBox *m_WrapLine; wxCheckBox *m_WrapLine;
Common::CriticalSection m_LogSection; std::mutex m_LogSection;
wxCSConv m_SJISConv; wxCSConv m_SJISConv;

View File

@ -118,9 +118,11 @@ void ControllerInterface::SetHwnd( void* const hwnd )
// //
bool ControllerInterface::UpdateInput(const bool force) bool ControllerInterface::UpdateInput(const bool force)
{ {
std::unique_lock<std::mutex> lk(update_lock, std::defer_lock);
if (force) if (force)
update_lock.Enter(); lk.lock();
else if (false == update_lock.TryEnter()) else if (!lk.try_lock())
return false; return false;
size_t ok_count = 0; size_t ok_count = 0;
@ -137,7 +139,6 @@ bool ControllerInterface::UpdateInput(const bool force)
//(*d)->ClearInputState(); //(*d)->ClearInputState();
} }
update_lock.Leave();
return (m_devices.size() == ok_count); return (m_devices.size() == ok_count);
} }
@ -148,9 +149,11 @@ bool ControllerInterface::UpdateInput(const bool force)
// //
bool ControllerInterface::UpdateOutput(const bool force) bool ControllerInterface::UpdateOutput(const bool force)
{ {
std::unique_lock<std::mutex> lk(update_lock, std::defer_lock);
if (force) if (force)
update_lock.Enter(); lk.lock();
else if (false == update_lock.TryEnter()) else if (!lk.try_lock())
return false; return false;
size_t ok_count = 0; size_t ok_count = 0;
@ -161,7 +164,6 @@ bool ControllerInterface::UpdateOutput(const bool force)
for (;d != e; ++d) for (;d != e; ++d)
(*d)->UpdateOutput(); (*d)->UpdateOutput();
update_lock.Leave();
return (m_devices.size() == ok_count); return (m_devices.size() == ok_count);
} }
@ -470,8 +472,8 @@ void ControllerInterface::UpdateReference(ControllerInterface::ControlReference*
else if ('`' == c) else if ('`' == c)
{ {
// different device // different device
if (false == /*XXX*/(bool)std::getline(ss, dev_str, '`')) if (std::getline(ss, dev_str, '`').eof())
break; break; // no terminating '`' character
} }
else else
ctrl_str += c; ctrl_str += c;

View File

@ -222,7 +222,7 @@ public:
const std::vector<Device*>& Devices() const { return m_devices; } const std::vector<Device*>& Devices() const { return m_devices; }
Device* FindDevice(const DeviceQualifier& devq) const; Device* FindDevice(const DeviceQualifier& devq) const;
Common::CriticalSection update_lock; std::mutex update_lock;
private: private:
bool m_is_init; bool m_is_init;

View File

@ -47,7 +47,7 @@ public:
std::vector< ControllerEmu* > controllers; 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 ini_name;
const char * const gui_name; const char * const gui_name;

View File

@ -52,9 +52,9 @@ struct UDPWiimote::_d
{ {
std::thread thread; std::thread thread;
std::list<sock_t> sockfds; std::list<sock_t> sockfds;
Common::CriticalSection termLock,mutex,nameMutex; std::mutex termLock, mutex, nameMutex;
volatile bool exit; volatile bool exit;
sock_t bipv4_fd,bipv6_fd; sock_t bipv4_fd, bipv6_fd;
}; };
int UDPWiimote::noinst = 0; int UDPWiimote::noinst = 0;
@ -132,15 +132,17 @@ UDPWiimote::UDPWiimote(const char *_port, const char * name, int _index) :
d->exit=false; d->exit=false;
initBroadcastIPv4(); initBroadcastIPv4();
initBroadcastIPv6(); initBroadcastIPv6();
d->termLock.Enter();
std::lock_guard<std::mutex> lk(d->termLock);
d->thread = std::thread(std::mem_fun(&UDPWiimote::mainThread), this); d->thread = std::thread(std::mem_fun(&UDPWiimote::mainThread), this);
d->termLock.Leave();
return; return;
} }
void UDPWiimote::mainThread() void UDPWiimote::mainThread()
{ {
d->termLock.Enter(); std::unique_lock<std::mutex> lk(d->termLock);
Common::Timer time; Common::Timer time;
fd_set fds; fd_set fds;
struct timeval timeout; struct timeval timeout;
@ -174,11 +176,11 @@ void UDPWiimote::mainThread()
timeout.tv_usec=(tleft%1000)*1000; 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; if (d->exit) return;
int rt=select(maxfd,&fds,NULL,NULL,&timeout); int rt=select(maxfd,&fds,NULL,NULL,&timeout);
if (d->exit) return; if (d->exit) return;
d->termLock.Enter(); lk.lock();
if (d->exit) return; if (d->exit) return;
if (rt) if (rt)
@ -200,27 +202,26 @@ void UDPWiimote::mainThread()
} }
else else
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lkm(d->mutex);
if (pharsePacket(bf,size)==0) if (pharsePacket(bf,size)==0)
{ {
//NOTICE_LOG(WIIMOTE,"UDPWII New pack"); //NOTICE_LOG(WIIMOTE,"UDPWII New pack");
} else { } else {
//NOTICE_LOG(WIIMOTE,"UDPWII Wrong pack format... ignoring"); //NOTICE_LOG(WIIMOTE,"UDPWII Wrong pack format... ignoring");
} }
d->mutex.Leave();
} }
} }
} }
} while (!(d->exit)); } while (!(d->exit));
d->termLock.Leave();
} }
UDPWiimote::~UDPWiimote() UDPWiimote::~UDPWiimote()
{ {
d->exit = true; d->exit = true;
{
std::lock_guard<std::mutex> lk(d->termLock);
d->thread.join(); d->thread.join();
d->termLock.Enter(); }
d->termLock.Leave();
for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++) for (std::list<sock_t>::iterator i=d->sockfds.begin(); i!=d->sockfds.end(); i++)
close(*i); close(*i);
close(d->bipv4_fd); close(d->bipv4_fd);
@ -289,7 +290,6 @@ int UDPWiimote::pharsePacket(u8 * bf, size_t size)
return 0; return 0;
} }
void UDPWiimote::initBroadcastIPv4() void UDPWiimote::initBroadcastIPv4()
{ {
d->bipv4_fd=socket(AF_INET, SOCK_DGRAM, 0); 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 *((u16*)(&(bf[1])))=htons(bcastMagic); //unique per-wiimote 16-bit ID
bf[3]=(u8)index; //wiimote index bf[3]=(u8)index; //wiimote index
*((u16*)(&(bf[4])))=htons(int_port); //port *((u16*)(&(bf[4])))=htons(int_port); //port
d->nameMutex.Enter(); {
std::lock_guard<std::mutex> lk(d->nameMutex);
slen=displayName.size(); slen=displayName.size();
if (slen>=256) if (slen>=256)
slen=255; slen=255;
bf[6]=(u8)slen; //display name size (max 255) bf[6]=(u8)slen; //display name size (max 255)
memcpy(&(bf[7]),displayName.c_str(),slen); //display name memcpy(&(bf[7]),displayName.c_str(),slen); //display name
d->nameMutex.Leave(); }
broadcastIPv4(bf,7+slen); broadcastIPv4(bf,7+slen);
broadcastIPv6(bf,7+slen); broadcastIPv6(bf,7+slen);
} }
void UDPWiimote::getAccel(float &_x, float &_y, float &_z) void UDPWiimote::getAccel(float &_x, float &_y, float &_z)
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
_x=(float)x; _x=(float)x;
_y=(float)y; _y=(float)y;
_z=(float)z; _z=(float)z;
d->mutex.Leave();
} }
u32 UDPWiimote::getButtons() u32 UDPWiimote::getButtons()
{ {
u32 msk; u32 msk;
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
msk=mask; msk=mask;
d->mutex.Leave();
return msk; return msk;
} }
void UDPWiimote::getIR(float &_x, float &_y) void UDPWiimote::getIR(float &_x, float &_y)
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
_x=(float)pointerX; _x=(float)pointerX;
_y=(float)pointerY; _y=(float)pointerY;
d->mutex.Leave();
} }
void UDPWiimote::getNunchuck(float &_x, float &_y, u8 &_mask) void UDPWiimote::getNunchuck(float &_x, float &_y, u8 &_mask)
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
_x=(float)nunX; _x=(float)nunX;
_y=(float)nunY; _y=(float)nunY;
_mask=nunMask; _mask=nunMask;
d->mutex.Leave();
} }
void UDPWiimote::getNunchuckAccel(float &_x, float &_y, float &_z) void UDPWiimote::getNunchuckAccel(float &_x, float &_y, float &_z)
{ {
d->mutex.Enter(); std::lock_guard<std::mutex> lk(d->mutex);
_x=(float)naX; _x=(float)naX;
_y=(float)naY; _y=(float)naY;
_z=(float)naZ; _z=(float)naZ;
d->mutex.Leave();
} }
const char * UDPWiimote::getPort() const char * UDPWiimote::getPort()
{ {
return port.c_str(); return port.c_str();
} }
void UDPWiimote::changeName(const char * name) void UDPWiimote::changeName(const char * name)
{ {
d->nameMutex.Enter(); std::lock_guard<std::mutex> lk(d->nameMutex);
displayName=name; displayName=name;
d->nameMutex.Leave();
} }

View File

@ -46,7 +46,7 @@ int OSDChoice, OSDTime;
Renderer *g_renderer = NULL; Renderer *g_renderer = NULL;
bool s_bLastFrameDumped = false; bool s_bLastFrameDumped = false;
Common::CriticalSection Renderer::s_criticalScreenshot; std::mutex Renderer::s_criticalScreenshot;
std::string Renderer::s_sScreenshotName; std::string Renderer::s_sScreenshotName;
volatile bool Renderer::s_bScreenshot; volatile bool Renderer::s_bScreenshot;
@ -182,10 +182,9 @@ bool Renderer::CalculateTargetSize(int multiplier)
void Renderer::SetScreenshot(const char *filename) void Renderer::SetScreenshot(const char *filename)
{ {
s_criticalScreenshot.Enter(); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
s_sScreenshotName = filename; s_sScreenshotName = filename;
s_bScreenshot = true; s_bScreenshot = true;
s_criticalScreenshot.Leave();
} }
// Create On-Screen-Messages // Create On-Screen-Messages

View File

@ -142,7 +142,7 @@ public:
protected: protected:
static Common::CriticalSection s_criticalScreenshot; static std::mutex s_criticalScreenshot;
static std::string s_sScreenshotName; static std::string s_sScreenshotName;
static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY); static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY);

View File

@ -1094,10 +1094,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// Save screenshot // Save screenshot
if (s_bScreenshot) if (s_bScreenshot)
{ {
s_criticalScreenshot.Enter(); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
SaveScreenshot(s_sScreenshotName, dst_rect); SaveScreenshot(s_sScreenshotName, dst_rect);
s_bScreenshot = false; s_bScreenshot = false;
s_criticalScreenshot.Leave();
} }
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
{ {

View File

@ -1150,19 +1150,18 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// Save screenshot // Save screenshot
if (s_bScreenshot) if (s_bScreenshot)
{ {
s_criticalScreenshot.Enter(); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
SaveScreenshot(s_sScreenshotName, dst_rect); SaveScreenshot(s_sScreenshotName, dst_rect);
// Reset settings // Reset settings
s_sScreenshotName.clear(); s_sScreenshotName.clear();
s_bScreenshot = false; s_bScreenshot = false;
s_criticalScreenshot.Leave();
} }
// Frame dumps are handled a little differently in Windows // Frame dumps are handled a little differently in Windows
#if defined _WIN32 || defined HAVE_LIBAV #if defined _WIN32 || defined HAVE_LIBAV
if (g_ActiveConfig.bDumpFrames) if (g_ActiveConfig.bDumpFrames)
{ {
s_criticalScreenshot.Enter(); std::lock_guard<std::mutex> lk(s_criticalScreenshot);
if (!data || w != dst_rect.GetWidth() || if (!data || w != dst_rect.GetWidth() ||
h != dst_rect.GetHeight()) h != dst_rect.GetHeight())
{ {
@ -1205,8 +1204,6 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
} }
else else
NOTICE_LOG(VIDEO, "Error reading framebuffer"); NOTICE_LOG(VIDEO, "Error reading framebuffer");
s_criticalScreenshot.Leave();
} }
else else
{ {

View File

@ -70,8 +70,6 @@ volatile bool interruptWaiting;
CPReg cpreg; // shared between gfx and emulator thread CPReg cpreg; // shared between gfx and emulator thread
Common::CriticalSection criticalSection;
void DoState(PointerWrap &p) void DoState(PointerWrap &p)
{ {
p.Do(cpreg); p.Do(cpreg);