Fix a race condition when pausing the CPU core.
This affects enabling and disabling block profiling on the fly. The block profiling pauses the CPU cores and then flushes the JIT's block cache and enables block profile. The issue with this is that when we pause the CPU core, we don't have a way to tell if the JIT recompiler has actually left. So if the secondary thread that is clearing the JIT block cache is too quick, it will clear the cache as a recompiler is still running that block that has been cleared.
This commit is contained in:
parent
805eaa91d0
commit
af305aa168
|
@ -277,6 +277,9 @@ void Interpreter::Run()
|
|||
PC = NPC;
|
||||
}
|
||||
}
|
||||
|
||||
// Let the waiting thread know we are done leaving
|
||||
PowerPC::FinishStateMove();
|
||||
}
|
||||
|
||||
void Interpreter::unknown_instruction(UGeckoInstruction _inst)
|
||||
|
|
|
@ -216,6 +216,12 @@ void Jit64AsmRoutineManager::Generate()
|
|||
ADD(64, R(RSP), Imm8(0x18));
|
||||
POP(RSP);
|
||||
}
|
||||
|
||||
// Let the waiting thread know we are done leaving
|
||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::FinishStateMove));
|
||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||
|
||||
ABI_PopRegistersAndAdjustStack(ABI_ALL_CALLEE_SAVED, 8, 16);
|
||||
RET();
|
||||
|
||||
|
|
|
@ -136,6 +136,10 @@ void JitArmAsmRoutineManager::Generate()
|
|||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging)
|
||||
SetJumpTarget(dbg_exit);
|
||||
|
||||
// Let the waiting thread know we are done leaving
|
||||
MOVI2R(R0, (u32)&PowerPC::FinishStateMove);
|
||||
BL(R0);
|
||||
|
||||
ADD(_SP, _SP, 4);
|
||||
|
||||
POP(9, R4, R5, R6, R7, R8, R9, R10, R11, _PC); // Returns
|
||||
|
|
|
@ -87,6 +87,10 @@ void JitArm64AsmRoutineManager::Generate()
|
|||
|
||||
SetJumpTarget(Exit);
|
||||
|
||||
// Let the waiting thread know we are done leaving
|
||||
MOVI2R(X0, (u64)&PowerPC::FinishStateMove);
|
||||
BLR(X0);
|
||||
|
||||
ABI_PopRegisters(regs_to_save);
|
||||
RET(X30);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Event.h"
|
||||
#include "Common/FPURoundMode.h"
|
||||
#include "Common/MathUtil.h"
|
||||
|
||||
|
@ -33,6 +34,7 @@ static volatile CPUState state = CPU_POWERDOWN;
|
|||
|
||||
Interpreter * const interpreter = Interpreter::getInstance();
|
||||
static CoreMode mode;
|
||||
static Common::Event s_state_change;
|
||||
|
||||
Watches watches;
|
||||
BreakPoints breakpoints;
|
||||
|
@ -238,16 +240,31 @@ void Start()
|
|||
|
||||
void Pause()
|
||||
{
|
||||
volatile CPUState old_state = state;
|
||||
state = CPU_STEPPING;
|
||||
|
||||
// Wait for the CPU core to leave
|
||||
if (old_state == CPU_RUNNING)
|
||||
s_state_change.WaitFor(std::chrono::seconds(1));
|
||||
Host_UpdateDisasmDialog();
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
volatile CPUState old_state = state;
|
||||
state = CPU_POWERDOWN;
|
||||
|
||||
// Wait for the CPU core to leave
|
||||
if (old_state == CPU_RUNNING)
|
||||
s_state_change.WaitFor(std::chrono::seconds(1));
|
||||
Host_UpdateDisasmDialog();
|
||||
}
|
||||
|
||||
void FinishStateMove()
|
||||
{
|
||||
s_state_change.Set();
|
||||
}
|
||||
|
||||
void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst)
|
||||
{
|
||||
switch (MMCR0.PMC1SELECT)
|
||||
|
|
|
@ -156,6 +156,7 @@ void RunLoop();
|
|||
void Start();
|
||||
void Pause();
|
||||
void Stop();
|
||||
void FinishStateMove();
|
||||
CPUState GetState();
|
||||
volatile CPUState *GetStatePtr(); // this oddity is here instead of an extern declaration to easily be able to find all direct accesses throughout the code.
|
||||
|
||||
|
|
Loading…
Reference in New Issue