diff options
| author | ayuanx <ayuanx@gmail.com> | 2010-01-14 10:52:14 +0000 |
|---|---|---|
| committer | ayuanx <ayuanx@gmail.com> | 2010-01-14 10:52:14 +0000 |
| commit | 571a47ef9abb4f6ec01d3f1202b74750f9964d0d (patch) | |
| tree | 46c90bb862b128cebc588745afc253be8121287e /Source/Core/Common | |
| parent | b186f0821eb6120c395e8ebd4eba1b6835936dbc (diff) | |
This could alleviate the suffering of dual core synchronization a bit.
But I doubt you would notice it in most cases.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4830 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/Common')
| -rw-r--r-- | Source/Core/Common/Src/Thread.cpp | 55 | ||||
| -rw-r--r-- | Source/Core/Common/Src/Thread.h | 33 |
2 files changed, 84 insertions, 4 deletions
diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index bb0d591771..37f52e9ce9 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -117,6 +117,60 @@ void Thread::SetCurrentThreadAffinity(int mask) SetThreadAffinityMask(GetCurrentThread(), mask); } +#ifdef _WIN32 +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; +} +#endif + // Regular same thread loop based waiting Event::Event() { @@ -164,6 +218,7 @@ void Event::MsgWait() if (msg.message == WM_QUIT) return; // Otherwise, dispatch the message. + TranslateMessage(&msg); DispatchMessage(&msg); } diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index 4df20da844..f667cc170c 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -137,7 +137,31 @@ private: #endif }; - +#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 { @@ -182,9 +206,10 @@ private: void InitThreading(); void SleepCurrentThread(int ms); -// YieldCPU: 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. +// YieldCPU: This function is only effective on HyperThreading CPU +// 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 |
