mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
SymbolMap: route remaining GUI-thread callers, remove internal locking
Windows/MainWindowMenu.cpp's Load/Save/Clear Symbol Map menu actions mutated g_symbolMap directly from the WinMain thread; route them through Core_RunOnCPUThread like the rest of the debugger. Windows/MainWindow.cpp's WM_USER_GET_MODULE_INFO handler read it directly too; guard with g_frameMutex. Windows/main.cpp's SortSymbols() calls turn out to already be safe as-is - both notifications that trigger them (BOOT_DONE, SYMBOL_MAP_UPDATED) are only ever fired from the CPU/NativeFrame thread - so just fix the stale comment claiming reliance on the (now removed) internal lock. With those covered, every remaining caller is either on the CPU/NativeFrame thread already or routes through Core_RunOnCPUThread/g_frameMutex, so SymbolMap's internal recursive_mutex is redundant - remove it and all ~40 lock_guard call sites. Qt's mainwindow.cpp still pokes at g_symbolMap directly and unguarded (a pre-existing issue, out of scope - Qt isn't a maintained backend), but removing the lock doesn't change its public API, so it still builds. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Hqm11k99viLfbJm2MkH4BH
This commit is contained in:
1 parent
5df8c14f1e
commit
3500293402
5 files changed
+21
-64
No files matched your search
@@ -725,8 +725,12 @@ namespace MainWindow {
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Get all modules from symbol map
|
||||
auto modules = g_symbolMap->getAllModules();
|
||||
// Get all modules from symbol map. Reading it here on the GUI thread would otherwise
|
||||
// race with the CPU thread - hold g_frameMutex for the duration of the read, which
|
||||
// NativeFrame() also holds while it's actually touching that state. See g_frameMutex
|
||||
// in Core.h.
|
||||
std::lock_guard<std::mutex> frameGuard(g_frameMutex);
|
||||
std::vector<LoadedModuleInfo> modules = g_symbolMap->getAllModules();
|
||||
for (const auto& module : modules)
|
||||
{
|
||||
if (module.name == moduleName)
|
||||
|
||||
@@ -769,34 +769,41 @@ namespace MainWindow {
|
||||
break;
|
||||
}
|
||||
|
||||
// g_symbolMap access below is routed through Core_RunOnCPUThread() instead of poking at it
|
||||
// directly from this GUI thread - see Core_RunOnCPUThread() in Core.h. The file-browse
|
||||
// dialogs are modal, so they stay outside the queued callback; NotifyDebuggerMapLoaded()
|
||||
// also stays outside, since it locks g_frameMutex internally (CDisasm/CMemoryDlg's
|
||||
// NotifyMapLoaded()) and Core_RunOnCPUThread's queue can be drained from inside a
|
||||
// g_frameMutex-locked NativeFrame() span, so calling it from within the lambda could
|
||||
// deadlock.
|
||||
case ID_DEBUG_LOADMAPFILE:
|
||||
if (W32Util::BrowseForFileName(true, hWnd, L"Load .ppmap", nullptr, nullptr, L"Maps\0*.ppmap\0All files\0*.*\0\0", L"ppmap", fn)) {
|
||||
g_symbolMap->LoadSymbolMap(Path(fn));
|
||||
Core_RunOnCPUThread([&] { g_symbolMap->LoadSymbolMap(Path(fn)); });
|
||||
NotifyDebuggerMapLoaded();
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_DEBUG_SAVEMAPFILE:
|
||||
if (W32Util::BrowseForFileName(false, hWnd, L"Save .ppmap", nullptr, L"map.ppmap", L"Maps\0*.ppmap\0All files\0*.*\0\0", L"ppmap", fn)) {
|
||||
g_symbolMap->SaveSymbolMap(Path(fn));
|
||||
Core_RunOnCPUThread([&] { g_symbolMap->SaveSymbolMap(Path(fn)); });
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_DEBUG_LOADSYMFILE:
|
||||
if (W32Util::BrowseForFileName(true, hWnd, L"Load .sym", nullptr, nullptr, L"Symbols\0*.sym\0All files\0*.*\0\0", L"sym", fn)) {
|
||||
g_symbolMap->LoadNocashSym(Path(fn));
|
||||
Core_RunOnCPUThread([&] { g_symbolMap->LoadNocashSym(Path(fn)); });
|
||||
NotifyDebuggerMapLoaded();
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_DEBUG_SAVESYMFILE:
|
||||
if (W32Util::BrowseForFileName(false, hWnd, L"Save .sym", nullptr, L"symbols.sym", L"Symbols\0*.sym\0All files\0*.*\0\0", L"sym", fn)) {
|
||||
g_symbolMap->SaveNocashSym(Path(fn));
|
||||
Core_RunOnCPUThread([&] { g_symbolMap->SaveNocashSym(Path(fn)); });
|
||||
}
|
||||
break;
|
||||
|
||||
case ID_DEBUG_RESETSYMBOLTABLE:
|
||||
g_symbolMap->Clear();
|
||||
Core_RunOnCPUThread([&] { g_symbolMap->Clear(); });
|
||||
NotifyDebuggerMapLoaded();
|
||||
break;
|
||||
|
||||
|
||||
+2
-2
@@ -508,7 +508,7 @@ void System_Notify(SystemNotification notification) {
|
||||
case SystemNotification::BOOT_DONE:
|
||||
{
|
||||
if (g_symbolMap)
|
||||
g_symbolMap->SortSymbols(); // internal locking is performed here
|
||||
g_symbolMap->SortSymbols(); // Always fired from the CPU/NativeFrame thread, see AGENTS.md
|
||||
PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0);
|
||||
|
||||
if (Achievements::HardcoreModeActive()) {
|
||||
@@ -548,7 +548,7 @@ void System_Notify(SystemNotification notification) {
|
||||
|
||||
case SystemNotification::SYMBOL_MAP_UPDATED:
|
||||
if (g_symbolMap)
|
||||
g_symbolMap->SortSymbols(); // internal locking is performed here
|
||||
g_symbolMap->SortSymbols(); // Always fired from the CPU/NativeFrame thread, see AGENTS.md
|
||||
PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0);
|
||||
break;
|
||||
|
||||
|
||||
Reference in new issue
Block a user