summaryrefslogtreecommitdiff
path: root/Source/Core/Common
diff options
context:
space:
mode:
authorayuanx <ayuanx@gmail.com>2010-01-14 10:52:14 +0000
committerayuanx <ayuanx@gmail.com>2010-01-14 10:52:14 +0000
commit571a47ef9abb4f6ec01d3f1202b74750f9964d0d (patch)
tree46c90bb862b128cebc588745afc253be8121287e /Source/Core/Common
parentb186f0821eb6120c395e8ebd4eba1b6835936dbc (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.cpp55
-rw-r--r--Source/Core/Common/Src/Thread.h33
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