From 1ba3b4e7ac9d53710454c46ac5384ee44a096b70 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 27 May 2015 03:08:48 -0400 Subject: [PATCH] CommandProcessor: Replace volatile usages with atomics Also remove said variables from being globals. --- Source/Core/VideoCommon/CommandProcessor.cpp | 81 ++++++++++++++------ Source/Core/VideoCommon/CommandProcessor.h | 14 ++-- Source/Core/VideoCommon/Fifo.cpp | 12 +-- Source/Core/VideoCommon/PixelEngine.cpp | 11 ++- 4 files changed, 78 insertions(+), 40 deletions(-) diff --git a/Source/Core/VideoCommon/CommandProcessor.cpp b/Source/Core/VideoCommon/CommandProcessor.cpp index f682abdeee..449e99982f 100644 --- a/Source/Core/VideoCommon/CommandProcessor.cpp +++ b/Source/Core/VideoCommon/CommandProcessor.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include + #include "Common/Atomic.h" #include "Common/ChunkFile.h" #include "Common/CommonTypes.h" @@ -40,15 +42,15 @@ static u16 m_bboxright; static u16 m_bboxbottom; static u16 m_tokenReg; -volatile bool interruptSet= false; -volatile bool interruptWaiting= false; -volatile bool interruptTokenWaiting = false; -volatile bool interruptFinishWaiting = false; +static std::atomic s_interrupt_set; +static std::atomic s_interrupt_waiting; +static std::atomic s_interrupt_token_waiting; +static std::atomic s_interrupt_finish_waiting; + +static std::atomic s_vi_ticks(CommandProcessor::m_cpClockOrigin); Common::Flag s_gpuMaySleep; -volatile u32 VITicks = CommandProcessor::m_cpClockOrigin; - static bool IsOnThread() { return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread; @@ -71,10 +73,10 @@ void DoState(PointerWrap &p) p.Do(m_tokenReg); p.Do(fifo); - p.Do(interruptSet); - p.Do(interruptWaiting); - p.Do(interruptTokenWaiting); - p.Do(interruptFinishWaiting); + p.Do(s_interrupt_set); + p.Do(s_interrupt_waiting); + p.Do(s_interrupt_token_waiting); + p.Do(s_interrupt_finish_waiting); } static inline void WriteLow(volatile u32& _reg, u16 lowbits) @@ -118,10 +120,10 @@ void Init() fifo.bFF_LoWatermark = 0; fifo.bFF_LoWatermarkInt = 0; - interruptSet = false; - interruptWaiting = false; - interruptFinishWaiting = false; - interruptTokenWaiting = false; + s_interrupt_set.store(false); + s_interrupt_waiting.store(false); + s_interrupt_finish_waiting.store(false); + s_interrupt_token_waiting.store(false); et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper); } @@ -358,18 +360,18 @@ void UpdateInterrupts(u64 userdata) { if (userdata) { - interruptSet = true; + s_interrupt_set.store(true); INFO_LOG(COMMANDPROCESSOR,"Interrupt set"); ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true); } else { - interruptSet = false; + s_interrupt_set.store(false); INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared"); ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false); } CoreTiming::ForceExceptionCheck(0); - interruptWaiting = false; + s_interrupt_waiting.store(false); RunGpu(); } @@ -379,6 +381,21 @@ void UpdateInterruptsFromVideoBackend(u64 userdata) CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata); } +bool IsInterruptWaiting() +{ + return s_interrupt_waiting.load(); +} + +void SetInterruptTokenWaiting(bool waiting) +{ + s_interrupt_token_waiting.store(waiting); +} + +void SetInterruptFinishWaiting(bool waiting) +{ + s_interrupt_finish_waiting.store(waiting); +} + void SetCPStatusFromGPU() { // breakpoint @@ -416,7 +433,7 @@ void SetCPStatusFromGPU() bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable; - if (interrupt != interruptSet && !interruptWaiting) + if (interrupt != s_interrupt_set.load() && !s_interrupt_waiting.load()) { u64 userdata = interrupt ? 1 : 0; if (IsOnThread()) @@ -424,7 +441,7 @@ void SetCPStatusFromGPU() if (!interrupt || bpInt || undfInt || ovfInt) { // Schedule the interrupt asynchronously - interruptWaiting = true; + s_interrupt_waiting.store(true); CommandProcessor::UpdateInterruptsFromVideoBackend(userdata); } } @@ -447,14 +464,14 @@ void SetCPStatusFromCPU() bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable; - if (interrupt != interruptSet && !interruptWaiting) + if (interrupt != s_interrupt_set.load() && !s_interrupt_waiting.load()) { u64 userdata = interrupt ? 1 : 0; if (IsOnThread()) { if (!interrupt || bpInt || undfInt || ovfInt) { - interruptSet = interrupt; + s_interrupt_set.store(interrupt); INFO_LOG(COMMANDPROCESSOR,"Interrupt set"); ProcessorInterface::SetInterrupt(INT_CAUSE_CP, interrupt); } @@ -468,7 +485,7 @@ void SetCPStatusFromCPU() void ProcessFifoEvents() { - if (IsOnThread() && (interruptWaiting || interruptFinishWaiting || interruptTokenWaiting)) + if (IsOnThread() && (s_interrupt_waiting.load() || s_interrupt_finish_waiting.load() || s_interrupt_token_waiting.load())) CoreTiming::ProcessFifoWaitEvents(); } @@ -533,12 +550,28 @@ void SetCpClearRegister() void Update() { - while (VITicks > m_cpClockOrigin && fifo.isGpuReadingData && IsOnThread()) + while (s_vi_ticks.load() > m_cpClockOrigin && fifo.isGpuReadingData && IsOnThread()) Common::YieldCPU(); if (fifo.isGpuReadingData) - Common::AtomicAdd(VITicks, SystemTimers::GetTicksPerSecond() / 10000); + s_vi_ticks.fetch_add(SystemTimers::GetTicksPerSecond() / 10000); RunGpu(); } + +u32 GetVITicks() +{ + return s_vi_ticks.load(); +} + +void SetVITicks(u32 ticks) +{ + s_vi_ticks.store(ticks); +} + +void DecrementVITicks(u32 ticks) +{ + s_vi_ticks.fetch_sub(ticks); +} + } // end of namespace CommandProcessor diff --git a/Source/Core/VideoCommon/CommandProcessor.h b/Source/Core/VideoCommon/CommandProcessor.h index 5c49f0bb69..0b33150ce4 100644 --- a/Source/Core/VideoCommon/CommandProcessor.h +++ b/Source/Core/VideoCommon/CommandProcessor.h @@ -17,11 +17,6 @@ namespace CommandProcessor { extern SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread. - -extern volatile bool interruptSet; -extern volatile bool interruptWaiting; -extern volatile bool interruptTokenWaiting; -extern volatile bool interruptFinishWaiting; extern Common::Flag s_gpuMaySleep; // internal hardware addresses @@ -143,12 +138,19 @@ void GatherPipeBursted(); void UpdateInterrupts(u64 userdata); void UpdateInterruptsFromVideoBackend(u64 userdata); +bool IsInterruptWaiting(); +void SetInterruptTokenWaiting(bool waiting); +void SetInterruptFinishWaiting(bool waiting); + void SetCpClearRegister(); void SetCpControlRegister(); void SetCpStatusRegister(); void ProcessFifoEvents(); void Update(); -extern volatile u32 VITicks; + +u32 GetVITicks(); +void SetVITicks(u32 ticks); +void DecrementVITicks(u32 ticks); } // namespace CommandProcessor diff --git a/Source/Core/VideoCommon/Fifo.cpp b/Source/Core/VideoCommon/Fifo.cpp index 1b556cca58..289a62d8e7 100644 --- a/Source/Core/VideoCommon/Fifo.cpp +++ b/Source/Core/VideoCommon/Fifo.cpp @@ -103,7 +103,7 @@ void Fifo_Init() s_video_buffer = (u8*)AllocateMemoryPages(FIFO_SIZE + 4); ResetVideoBuffer(); s_gpu_running_state.store(false); - Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin); + CommandProcessor::SetVITicks(CommandProcessor::m_cpClockOrigin); } void Fifo_Shutdown() @@ -321,17 +321,17 @@ void RunGpuLoop() if (!fifo.isGpuReadingData) { - Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin); + CommandProcessor::SetVITicks(CommandProcessor::m_cpClockOrigin); } bool run_loop = true; // check if we are able to run this buffer - while (run_loop && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint()) + while (run_loop && !CommandProcessor::IsInterruptWaiting() && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint()) { fifo.isGpuReadingData = true; - if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU || Common::AtomicLoad(CommandProcessor::VITicks) > CommandProcessor::m_cpClockOrigin) + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU || CommandProcessor::GetVITicks() > CommandProcessor::m_cpClockOrigin) { u32 readPtr = fifo.CPReadPointer; ReadDataFromFifo(readPtr); @@ -349,8 +349,8 @@ void RunGpuLoop() s_video_buffer_read_ptr = OpcodeDecoder_Run(DataReader(s_video_buffer_read_ptr, write_ptr), &cyclesExecuted, false); - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU && Common::AtomicLoad(CommandProcessor::VITicks) >= cyclesExecuted) - Common::AtomicAdd(CommandProcessor::VITicks, -(s32)cyclesExecuted); + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU && CommandProcessor::GetVITicks() >= cyclesExecuted) + CommandProcessor::DecrementVITicks(cyclesExecuted); Common::AtomicStore(fifo.CPReadPointer, readPtr); Common::AtomicAdd(fifo.CPReadWriteDistance, -32); diff --git a/Source/Core/VideoCommon/PixelEngine.cpp b/Source/Core/VideoCommon/PixelEngine.cpp index 9b2c48876b..45db963d23 100644 --- a/Source/Core/VideoCommon/PixelEngine.cpp +++ b/Source/Core/VideoCommon/PixelEngine.cpp @@ -274,14 +274,14 @@ void SetToken_OnMainThread(u64 userdata, int cyclesLate) s_signal_token_interrupt.store(1); UpdateInterrupts(); } - CommandProcessor::interruptTokenWaiting = false; + CommandProcessor::SetInterruptTokenWaiting(false); } void SetFinish_OnMainThread(u64 userdata, int cyclesLate) { s_signal_finish_interrupt.store(1); UpdateInterrupts(); - CommandProcessor::interruptFinishWaiting = false; + CommandProcessor::SetInterruptFinishWaiting(false); } // SetToken @@ -293,7 +293,8 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge) s_signal_token_interrupt.store(1); } - CommandProcessor::interruptTokenWaiting = true; + CommandProcessor::SetInterruptTokenWaiting(true); + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread || g_use_deterministic_gpu_thread) CoreTiming::ScheduleEvent(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); else @@ -304,11 +305,13 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge) // THIS IS EXECUTED FROM VIDEO THREAD (BPStructs.cpp) when a new frame has been drawn void SetFinish() { - CommandProcessor::interruptFinishWaiting = true; + CommandProcessor::SetInterruptFinishWaiting(true); + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread || g_use_deterministic_gpu_thread) CoreTiming::ScheduleEvent(0, et_SetFinishOnMainThread, 0); else CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0); + INFO_LOG(PIXELENGINE, "VIDEO Set Finish"); }