summaryrefslogtreecommitdiff
path: root/Source/Core
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
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')
-rw-r--r--Source/Core/AudioCommon/Src/DSoundStream.cpp8
-rw-r--r--Source/Core/AudioCommon/Src/DSoundStream.h3
-rw-r--r--Source/Core/AudioCommon/Src/OpenALStream.h3
-rw-r--r--Source/Core/Common/Src/Thread.cpp55
-rw-r--r--Source/Core/Common/Src/Thread.h33
-rw-r--r--Source/Core/Core/Src/Core.cpp13
-rw-r--r--Source/Core/Core/Src/HW/SystemTimers.cpp22
-rw-r--r--Source/Core/DebuggerWX/Src/MemoryWindow.cpp2
-rw-r--r--Source/Core/DolphinWX/Src/LogWindow.cpp4
-rw-r--r--Source/Core/VideoCommon/Src/CommandProcessor.cpp8
-rw-r--r--Source/Core/VideoCommon/Src/Fifo.cpp6
11 files changed, 108 insertions, 49 deletions
diff --git a/Source/Core/AudioCommon/Src/DSoundStream.cpp b/Source/Core/AudioCommon/Src/DSoundStream.cpp
index 2e6cd69146..3d4c868cdb 100644
--- a/Source/Core/AudioCommon/Src/DSoundStream.cpp
+++ b/Source/Core/AudioCommon/Src/DSoundStream.cpp
@@ -106,7 +106,6 @@ void DSound::SoundLoop()
while (!threadData)
{
// No blocking inside the csection
- soundCriticalSection.Enter();
dsBuffer->GetCurrentPosition((DWORD*)&currentPos, 0);
int numBytesToRender = FIX128(ModBufferSize(currentPos - lastPos));
if (numBytesToRender >= 256)
@@ -117,7 +116,6 @@ void DSound::SoundLoop()
WriteDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
lastPos = ModBufferSize(lastPos + numBytesToRender);
}
- soundCriticalSection.Leave();
soundSyncEvent.Wait();
}
}
@@ -149,10 +147,8 @@ void DSound::SetVolume(int volume)
// This is in "dBA attenuation" from 0 to -10000, logarithmic
m_volume = (int)floor(log10((float)volume) * 5000.0f) - 10000;
- soundCriticalSection.Enter();
if (dsBuffer != NULL)
dsBuffer->SetVolume(m_volume);
- soundCriticalSection.Leave();
}
void DSound::Update()
@@ -164,7 +160,6 @@ void DSound::Clear(bool mute)
{
m_muted = mute;
- soundCriticalSection.Enter();
if (m_muted)
{
dsBuffer->Stop();
@@ -173,7 +168,6 @@ void DSound::Clear(bool mute)
{
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
}
- soundCriticalSection.Leave();
}
void DSound::Stop()
@@ -182,13 +176,11 @@ void DSound::Stop()
// kick the thread if it's waiting
soundSyncEvent.Set();
- soundCriticalSection.Enter();
delete thread;
thread = NULL;
dsBuffer->Stop();
dsBuffer->Release();
ds->Release();
- soundCriticalSection.Leave();
soundSyncEvent.Shutdown();
}
diff --git a/Source/Core/AudioCommon/Src/DSoundStream.h b/Source/Core/AudioCommon/Src/DSoundStream.h
index fcf0413ee7..adbeaeb468 100644
--- a/Source/Core/AudioCommon/Src/DSoundStream.h
+++ b/Source/Core/AudioCommon/Src/DSoundStream.h
@@ -32,8 +32,7 @@ class DSound : public SoundStream
{
#ifdef _WIN32
Common::Thread *thread;
- Common::CriticalSection soundCriticalSection;
- Common::Event soundSyncEvent;
+ Common::EventEx soundSyncEvent;
void *hWnd;
IDirectSound8* ds;
diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h
index 57bf2e34b7..8aebf32068 100644
--- a/Source/Core/AudioCommon/Src/OpenALStream.h
+++ b/Source/Core/AudioCommon/Src/OpenALStream.h
@@ -64,8 +64,7 @@ public:
private:
Common::Thread *thread;
- Common::CriticalSection soundCriticalSection;
- Common::Event soundSyncEvent;
+ Common::EventEx soundSyncEvent;
short realtimeBuffer[OAL_MAX_SAMPLES * 2];
ALuint uiBuffers[OAL_NUM_BUFFERS];
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
diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp
index 17c8ba38c9..a5fc0a91dd 100644
--- a/Source/Core/Core/Src/Core.cpp
+++ b/Source/Core/Core/Src/Core.cpp
@@ -548,13 +548,14 @@ void ScreenShot()
// This should only be called from VI
void VideoThrottle()
{
- u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 10
- : VideoInterface::TargetRefreshRate;
+ u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 1) ?
+ SConfig::GetInstance().m_Framelimit * 10 : VideoInterface::TargetRefreshRate;
// When frame limit is NOT off
if (SConfig::GetInstance().m_Framelimit)
{
- u32 frametime = DrawnVideo * 1000 / TargetVPS;
+ // Make the limiter a bit loose
+ u32 frametime = DrawnVideo * 1000 / ++TargetVPS;
while ((u32)Timer.GetTimeDifference() < frametime)
Common::YieldCPU();
//Common::SleepCurrentThread(1);
@@ -567,7 +568,7 @@ void VideoThrottle()
SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
u32 FPS = Common::AtomicLoad(DrawnFrame) * 1000 / ElapseTime;
- u32 VPS = DrawnVideo * 1000 / ElapseTime;
+ u32 VPS = --DrawnVideo * 1000 / ElapseTime;
u32 Speed = VPS * 100 / VideoInterface::TargetRefreshRate;
// Settings are shown the same for both extended and summary info
@@ -611,7 +612,7 @@ void VideoThrottle()
SystemTimers::GetTicksPerSecond() / 1000000,
_CoreParameter.bSkipIdle ? "~" : "",
TicksPercentage);
-
+
#else // Summary information
std::string SFPS = StringFromFormat("FPS: %u - VPS: %u - SPEED: %u%%", FPS, VPS, Speed);
#endif
@@ -630,7 +631,7 @@ void VideoThrottle()
Common::AtomicStore(DrawnFrame, 0);
DrawnVideo = 0;
}
-
+
DrawnVideo++;
}
diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp
index 8661bd7408..d284e2ef0c 100644
--- a/Source/Core/Core/Src/HW/SystemTimers.cpp
+++ b/Source/Core/Core/Src/HW/SystemTimers.cpp
@@ -132,13 +132,7 @@ int
// This is completely arbitrary. If we find that we need lower latency, we can just
// increase this number.
- IPC_HLE_PERIOD,
-
- // For DC watchdog hack
- // Once every 4 frame-period seems to be enough (arbitrary taking 60fps as the ref).
- // TODO: make it VI output frame rate compliant (30/60 and 25/50)
- // Assuming game's frame-finish-watchdog wait more than 4 emulated frame-period before starting its mess.
- FAKE_GP_WATCHDOG_PERIOD;
+ IPC_HLE_PERIOD;
@@ -227,7 +221,7 @@ void AdvanceCallback(int cyclesExecuted)
void FakeGPWatchdogCallback(u64 userdata, int cyclesLate)
{
CPluginManager::GetInstance().GetVideo()->Video_WaitForFrameFinish(); // lock CPUThread until frame finish
- CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD-cyclesLate, et_FakeGPWD);
+ CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_FakeGPWD);
}
void PatchEngineCallback(u64 userdata, int cyclesLate)
@@ -235,7 +229,7 @@ void PatchEngineCallback(u64 userdata, int cyclesLate)
// Patch mem and run the Action Replay
PatchEngine::ApplyFramePatches();
PatchEngine::ApplyARPatches();
- CoreTiming::ScheduleEvent((GetTicksPerSecond() / 5000) - cyclesLate, et_PatchEngine);
+ CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame() - cyclesLate, et_PatchEngine);
}
void Init()
@@ -271,8 +265,6 @@ void Init()
if (UsingDSPLLE)
DSP_PERIOD = 12000; // TO BE TWEAKED
- FAKE_GP_WATCHDOG_PERIOD = GetTicksPerSecond() / 60;
-
// This is the biggest question mark.
AI_PERIOD = GetTicksPerSecond() / 80;
@@ -297,16 +289,14 @@ void Init()
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_VI);
CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP);
- CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_SI);
+ CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI);
CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA);
// For DC watchdog hack
if (Core::GetStartupParameter().bCPUThread)
- {
- CoreTiming::ScheduleEvent(FAKE_GP_WATCHDOG_PERIOD, et_FakeGPWD);
- }
+ CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_FakeGPWD);
- CoreTiming::ScheduleEvent(GetTicksPerSecond() / 60, et_PatchEngine);
+ CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_PatchEngine);
if (Core::GetStartupParameter().bWii)
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
diff --git a/Source/Core/DebuggerWX/Src/MemoryWindow.cpp b/Source/Core/DebuggerWX/Src/MemoryWindow.cpp
index 474fac90ef..729c76ecd3 100644
--- a/Source/Core/DebuggerWX/Src/MemoryWindow.cpp
+++ b/Source/Core/DebuggerWX/Src/MemoryWindow.cpp
@@ -391,7 +391,7 @@ void CMemoryWindow::onSearch(wxCommandEvent& event){
}
if(size){
unsigned char* pnt=&Dest.front();
- int k=0;
+ unsigned int k=0;
//grab
wxString txt = addrbox->GetValue();
diff --git a/Source/Core/DolphinWX/Src/LogWindow.cpp b/Source/Core/DolphinWX/Src/LogWindow.cpp
index eecae934c5..ea3bc012ad 100644
--- a/Source/Core/DolphinWX/Src/LogWindow.cpp
+++ b/Source/Core/DolphinWX/Src/LogWindow.cpp
@@ -187,7 +187,7 @@ void CLogWindow::LoadSettings()
m_verbosity->SetSelection(verbosity - 1);
ini.Get("Options", "Font", &font, 0);
m_FontChoice->SetSelection(font);
- if (m_FontChoice->GetSelection() < Font.size())
+ if (m_FontChoice->GetSelection() < (int)Font.size())
m_Log->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, Font.at(m_FontChoice->GetSelection())));
ini.Get("Options", "WriteToFile", &m_writeFile, true);
m_writeFileCB->SetValue(m_writeFile);
@@ -303,7 +303,7 @@ wxTextCtrl* CLogWindow::CreateTextCtrl(wxPanel* parent, wxWindowID id, long Styl
TC->SetBackgroundColour(*wxBLACK);
if (m_FontChoice)
{
- if (m_FontChoice->GetSelection() < Font.size())
+ if (m_FontChoice->GetSelection() < (int)Font.size())
TC->SetDefaultStyle(wxTextAttr(wxNullColour, wxNullColour, Font.at(m_FontChoice->GetSelection())));
}
return TC;
diff --git a/Source/Core/VideoCommon/Src/CommandProcessor.cpp b/Source/Core/VideoCommon/Src/CommandProcessor.cpp
index c02fd492c7..ea153180c3 100644
--- a/Source/Core/VideoCommon/Src/CommandProcessor.cpp
+++ b/Source/Core/VideoCommon/Src/CommandProcessor.cpp
@@ -105,7 +105,7 @@ int m_bboxbottom;
u16 m_tokenReg;
static u32 fake_GPWatchdogLastToken = 0;
-static Common::Event s_fifoIdleEvent;
+static Common::EventEx s_fifoIdleEvent;
static Common::CriticalSection sFifoCritical;
void FifoCriticalEnter()
@@ -381,7 +381,7 @@ void Write16(const u16 _Value, const u32 _Address)
// Touching that game is a no-go so I don't want to take the risk :p
while (fifo.bFF_GPReadEnable && ((!fifo.bFF_BPEnable && fifo.CPReadWriteDistance) || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)))
{
- s_fifoIdleEvent.MsgWait();
+ s_fifoIdleEvent.Wait();
}
}
}
@@ -573,7 +573,7 @@ void WaitForFrameFinish()
{
while ((fake_GPWatchdogLastToken == fifo.Fake_GPWDToken) && fifo.bFF_GPReadEnable && ((!fifo.bFF_BPEnable && fifo.CPReadWriteDistance) || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)));
{
- s_fifoIdleEvent.MsgWait();
+ s_fifoIdleEvent.Wait();
}
fake_GPWatchdogLastToken = fifo.Fake_GPWDToken;
@@ -618,7 +618,7 @@ void STACKALIGN GatherPipeBursted()
// Wait for GPU to catch up
while (fifo.CPReadWriteDistance > fifo.CPLoWatermark && fifo.bFF_GPReadEnable && (!fifo.bFF_BPEnable || (fifo.bFF_BPEnable && !fifo.bFF_Breakpoint)))
{
- s_fifoIdleEvent.MsgWait();
+ s_fifoIdleEvent.Wait();
}
}
// check if we are in sync
diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp
index 172d6095fa..6ca7c3f259 100644
--- a/Source/Core/VideoCommon/Src/Fifo.cpp
+++ b/Source/Core/VideoCommon/Src/Fifo.cpp
@@ -36,7 +36,7 @@ namespace
static volatile bool fifoStateRun = false;
static volatile bool EmuRunning = false;
static u8 *videoBuffer;
-static Common::Event fifo_run_event;
+static Common::EventEx fifo_run_event;
// STATE_TO_SAVE
static int size = 0;
} // namespace
@@ -170,6 +170,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
{
Common::AtomicStore(_fifo.bFF_Breakpoint, 1);
CommandProcessor::UpdateInterruptsFromVideoPlugin(true);
+ CommandProcessor::FifoCriticalLeave();
break;
}
distToSend = 32;
@@ -208,10 +209,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
// leading the CPU thread to wait in Video_BeginField or Video_AccessEFB thus slowing things down.
VideoFifo_CheckEFBAccess();
VideoFifo_CheckSwapRequest();
-
- CommandProcessor::SetFifoIdleFromVideoPlugin();
}
-
CommandProcessor::SetFifoIdleFromVideoPlugin();
if (EmuRunning)
Common::YieldCPU();