Merge pull request #13446 from JosJuice/breakpoints-delayed-update

PowerPC: Add RAII handling for breakpoint updates
This commit is contained in:
Jordan Woyak
2025-07-25 23:26:25 -05:00
committed by GitHub
4 changed files with 52 additions and 20 deletions

View File

@ -252,6 +252,7 @@ MemChecks::TMemChecksStr MemChecks::GetStrings() const
void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
{
const Core::CPUThreadGuard guard(m_system);
DelayedMemCheckUpdate delayed_update(this);
for (const std::string& mc_string : mc_strings)
{
@ -279,13 +280,11 @@ void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
mc.condition = Expression::TryParse(condition);
}
Add(std::move(mc), false);
delayed_update |= Add(std::move(mc));
}
Update();
}
void MemChecks::Add(TMemCheck memory_check, bool update)
DelayedMemCheckUpdate MemChecks::Add(TMemCheck memory_check)
{
const Core::CPUThreadGuard guard(m_system);
@ -304,8 +303,7 @@ void MemChecks::Add(TMemCheck memory_check, bool update)
m_mem_checks.emplace_back(std::move(memory_check));
}
if (update)
Update();
return DelayedMemCheckUpdate(this, true);
}
bool MemChecks::ToggleEnable(u32 address)
@ -319,20 +317,17 @@ bool MemChecks::ToggleEnable(u32 address)
return true;
}
bool MemChecks::Remove(u32 address, bool update)
DelayedMemCheckUpdate MemChecks::Remove(u32 address)
{
const auto iter = std::ranges::find(m_mem_checks, address, &TMemCheck::start_address);
if (iter == m_mem_checks.cend())
return false;
return DelayedMemCheckUpdate(this, false);
const Core::CPUThreadGuard guard(m_system);
m_mem_checks.erase(iter);
if (update)
Update();
return true;
return DelayedMemCheckUpdate(this, true);
}
void MemChecks::Clear()

View File

@ -97,6 +97,8 @@ private:
Core::System& m_system;
};
class DelayedMemCheckUpdate;
// Memory breakpoints
class MemChecks
{
@ -115,13 +117,13 @@ public:
TMemChecksStr GetStrings() const;
void AddFromStrings(const TMemChecksStr& mc_strings);
void Add(TMemCheck memory_check, bool update = true);
DelayedMemCheckUpdate Add(TMemCheck memory_check);
bool ToggleEnable(u32 address);
TMemCheck* GetMemCheck(u32 address, size_t size = 1);
bool OverlapsMemcheck(u32 address, u32 length) const;
bool Remove(u32 address, bool update = true);
DelayedMemCheckUpdate Remove(u32 address);
void Update();
void Clear();
@ -132,3 +134,39 @@ private:
Core::System& m_system;
bool m_mem_breakpoints_set = false;
};
class DelayedMemCheckUpdate final
{
public:
DelayedMemCheckUpdate(MemChecks* memchecks, bool update_needed = false)
: m_memchecks(memchecks), m_update_needed(update_needed)
{
}
DelayedMemCheckUpdate(const DelayedMemCheckUpdate&) = delete;
DelayedMemCheckUpdate(DelayedMemCheckUpdate&& other) = delete;
DelayedMemCheckUpdate& operator=(const DelayedMemCheckUpdate&) = delete;
DelayedMemCheckUpdate& operator=(DelayedMemCheckUpdate&& other) = delete;
~DelayedMemCheckUpdate()
{
if (m_update_needed)
m_memchecks->Update();
}
DelayedMemCheckUpdate& operator|=(DelayedMemCheckUpdate&& other)
{
if (m_memchecks == other.m_memchecks)
{
m_update_needed |= other.m_update_needed;
other.m_update_needed = false;
}
return *this;
}
operator bool() const { return m_update_needed; }
private:
MemChecks* m_memchecks;
bool m_update_needed;
};

View File

@ -172,12 +172,12 @@ static void RemoveBreakpoint(BreakpointType type, u32 addr, u32 len)
else
{
auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks();
DelayedMemCheckUpdate delayed_update(&memchecks);
while (memchecks.GetMemCheck(addr, len) != nullptr)
{
memchecks.Remove(addr, false);
delayed_update |= memchecks.Remove(addr);
INFO_LOG_FMT(GDB_STUB, "gdb: removed a memcheck: {:08x} bytes at {:08x}", len, addr);
}
memchecks.Update();
}
Host_PPCBreakpointsChanged();
}

View File

@ -1010,6 +1010,7 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row)
{
const Core::CPUThreadGuard guard(m_system);
DelayedMemCheckUpdate delayed_update(&memchecks);
for (int i = 0; i < breaks; i++)
{
@ -1028,16 +1029,14 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row)
check.log_on_hit = m_do_log;
check.break_on_hit = true;
memchecks.Add(std::move(check), false);
delayed_update |= memchecks.Add(std::move(check));
}
else if (check_ptr != nullptr)
{
// Using the pointer fixes misaligned breakpoints (0x11 breakpoint in 0x10 aligned view).
memchecks.Remove(check_ptr->start_address, false);
delayed_update |= memchecks.Remove(check_ptr->start_address);
}
}
memchecks.Update();
}
emit Host::GetInstance()->PPCBreakpointsChanged();