From 326448636b935e7484ee6a0c3e3f168d710f517c Mon Sep 17 00:00:00 2001 From: Katharine Chui Date: Sun, 1 Jun 2025 21:10:59 +0200 Subject: [PATCH 1/2] Run module_start of plugins before starting boot module --- Core/HLE/Plugins.cpp | 6 +++++- Core/HLE/Plugins.h | 3 ++- Core/HLE/sceKernelModule.cpp | 35 ++++++++++++++++++++++++++++++----- Core/HLE/sceKernelModule.h | 5 +++++ Core/HLE/sceKernelThread.cpp | 1 + Core/HLE/sceKernelThread.h | 1 + 6 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Core/HLE/Plugins.cpp b/Core/HLE/Plugins.cpp index 2373596d65..1092347c1c 100644 --- a/Core/HLE/Plugins.cpp +++ b/Core/HLE/Plugins.cpp @@ -172,7 +172,7 @@ void Init() { } } -bool Load() { +bool Load(PSPModule *pluginWaitingModule, SceUID threadID) { bool started = false; auto sy = GetI18NCategory(I18NCat::SYSTEM); @@ -197,6 +197,10 @@ bool Load() { std::string shortName = Path(filename).GetFilename(); g_OSD.Show(OSDType::MESSAGE_SUCCESS, ApplySafeSubstitutions(sy->T("Loaded plugin: %1"), shortName), 6.0f); started = true; + pluginWaitingModule->startingPlugins.push_back(module); + u32 error; + PSPModule *plugin_module = kernelObjects.Get(module, error); + plugin_module->pluginWaitingThread = threadID; } INFO_LOG(Log::System, "Loaded plugin: %s", filename.c_str()); diff --git a/Core/HLE/Plugins.h b/Core/HLE/Plugins.h index cfb8d15ffb..7c15718465 100644 --- a/Core/HLE/Plugins.h +++ b/Core/HLE/Plugins.h @@ -20,6 +20,7 @@ #include #include #include "Common/Input/KeyCodes.h" +#include "Core/HLE/sceKernelModule.h" class PointerWrap; @@ -28,7 +29,7 @@ namespace HLEPlugins { void Init(); void Shutdown(); -bool Load(); +bool Load(PSPModule *pluginWaitingModule, SceUID threadID); void Unload(); void DoState(PointerWrap &p); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 16ed48db12..d6d56d9f04 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1650,11 +1650,6 @@ static void __KernelStartModule(PSPModule *m, int args, const char *argp, SceKer SceUID threadID = __KernelSetupRootThread(m->GetUID(), args, argp, options->priority, options->stacksize, options->attribute); __KernelSetThreadRA(threadID, NID_MODULERETURN); - - if (HLEPlugins::Load()) { - KernelRotateThreadReadyQueue(0); - __KernelReSchedule("Started plugins"); - } } @@ -1788,6 +1783,13 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str __KernelStartIdleThreads(module->GetUID()); + // Wait until plugins are loaded + module->startingPlugins.clear(); + if (HLEPlugins::Load(module, __KernelGetCurThread())) { + __KernelWaitCurThread(WAITTYPE_PLUGIN, module->GetUID(), 1, 0, false, "started plugins"); + __KernelReSchedule("Started plugins"); + } + delete[] param_argp; delete[] param_key; @@ -2302,6 +2304,29 @@ void __KernelReturnFromModuleFunc() { } module->waitingThreads.clear(); + // Check if we need to wake up a plugin waiting thread + if (module->pluginWaitingThread) { + u32 error; + PSPThread *plugin_waiting_thread = kernelObjects.Get(module->pluginWaitingThread, error); + if (plugin_waiting_thread) { + PSPModule *plugin_waiting_module = kernelObjects.Get(plugin_waiting_thread->moduleId, error); + if (plugin_waiting_module) { + for (auto it = plugin_waiting_module->startingPlugins.begin(), end = plugin_waiting_module->startingPlugins.end(); it < end; ++it) { + if (*it == leftModuleID) { + plugin_waiting_module->startingPlugins.erase(it); + break; + } + } + if (plugin_waiting_module->startingPlugins.empty()) { + INFO_LOG(Log::sceModule, "Resuming LoadExec thread 0x%x", module->pluginWaitingThread); + __KernelResumeThreadFromWait(module->pluginWaitingThread, 0); + } else { + INFO_LOG(Log::sceModule, "LoadExec thread 0x%x still waiting for %ld plugin(s)", module->pluginWaitingThread, plugin_waiting_module->startingPlugins.size()); + } + } + } + } + if (module->nm.status == MODULE_STATUS_UNLOADING) { // TODO: Delete the waiting thread? module->Cleanup(); diff --git a/Core/HLE/sceKernelModule.h b/Core/HLE/sceKernelModule.h index 61ead2a4da..5deb16c5e1 100644 --- a/Core/HLE/sceKernelModule.h +++ b/Core/HLE/sceKernelModule.h @@ -191,6 +191,11 @@ public: NativeModule nm{}; std::vector waitingThreads; + // From the plugin's perspective, this is the reference to the thread started by LoadExec + SceUID pluginWaitingThread = 0; + // Thread started by LoadExec is waiting for these plugins + std::vector startingPlugins; + // TODO: Should we store these grouped by moduleName instead? Seems more reasonable. std::vector exportedFuncs; std::vector importedFuncs; diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index b2eb4d1011..b3d0c59f3c 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -84,6 +84,7 @@ const WaitTypeNames waitTypeNames[] = { { WAITTYPE_MICINPUT, "Microphone input"}, { WAITTYPE_NET, "Network"}, { WAITTYPE_USB, "USB" }, + { WAITTYPE_PLUGIN, "Initial plugin load" }, }; const char *WaitTypeToString(WaitType type) { diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index a9cff92d5e..adab093201 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -115,6 +115,7 @@ enum WaitType : int { WAITTYPE_MICINPUT = 24, // fake WAITTYPE_NET = 25, // fake WAITTYPE_USB = 26, // fake + WAITTYPE_PLUGIN = 27, // this is fake, for when LoadExec thread is waiting for plugins to finish loading NUM_WAITTYPES }; From 7bab953c92ede88b909ccb4cfba5368c35bc724d Mon Sep 17 00:00:00 2001 From: Katharine Chui Date: Sun, 1 Jun 2025 23:00:23 +0200 Subject: [PATCH 2/2] verify thread wait type before resuming thread from plugin waiting --- Core/HLE/sceKernelModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index d6d56d9f04..603cd4b15a 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -2308,7 +2308,7 @@ void __KernelReturnFromModuleFunc() { if (module->pluginWaitingThread) { u32 error; PSPThread *plugin_waiting_thread = kernelObjects.Get(module->pluginWaitingThread, error); - if (plugin_waiting_thread) { + if (plugin_waiting_thread && HLEKernel::VerifyWait(module->pluginWaitingThread, WAITTYPE_PLUGIN, plugin_waiting_thread->moduleId)) { PSPModule *plugin_waiting_module = kernelObjects.Get(plugin_waiting_thread->moduleId, error); if (plugin_waiting_module) { for (auto it = plugin_waiting_module->startingPlugins.begin(), end = plugin_waiting_module->startingPlugins.end(); it < end; ++it) {