2026-09-21 00:39:13

Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie
2026-09-21 00:39:13 +00:00
parent 9fac15716d
commit 3bab4fdc2e
13 changed files with 90 additions and 27 deletions
+4
View File
@@ -19,6 +19,10 @@ ADSP::ADSP(Core::System& system, Sink::Sink& sink) {
} }
} }
void ADSP::NotifyShutdown() {
opus_decoder->NotifyShutdown();
}
AudioRenderer::AudioRenderer& ADSP::AudioRenderer() { AudioRenderer::AudioRenderer& ADSP::AudioRenderer() {
return *audio_renderer; return *audio_renderer;
} }
+1
View File
@@ -45,6 +45,7 @@ public:
explicit ADSP(Core::System& system, Sink::Sink& sink); explicit ADSP(Core::System& system, Sink::Sink& sink);
~ADSP() = default; ~ADSP() = default;
void NotifyShutdown();
AudioRenderer::AudioRenderer& AudioRenderer(); AudioRenderer::AudioRenderer& AudioRenderer();
OpusDecoder::OpusDecoder& OpusDecoder(); OpusDecoder::OpusDecoder& OpusDecoder();
@@ -82,6 +82,9 @@ void OpusDecoder::Main(std::stop_token stop_token) {
while (!stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
auto msg = Receive(Direction::DSP, stop_token); auto msg = Receive(Direction::DSP, stop_token);
if (stop_token.stop_requested())
break;
switch (msg) { switch (msg) {
case Shutdown: case Shutdown:
Send(Direction::Host, Message::ShutdownOK); Send(Direction::Host, Message::ShutdownOK);
@@ -266,4 +269,9 @@ void OpusDecoder::Main(std::stop_token stop_token) {
} }
} }
void OpusDecoder::NotifyShutdown() {
init_thread.request_stop();
main_thread.request_stop();
}
} // namespace AudioCore::ADSP::OpusDecoder } // namespace AudioCore::ADSP::OpusDecoder
@@ -67,6 +67,8 @@ public:
shared_memory = &shared_memory_; shared_memory = &shared_memory_;
} }
void NotifyShutdown();
private: private:
/** /**
* Initializing thread, launched at audio_core boot to avoid blocking the main emu boot thread. * Initializing thread, launched at audio_core boot to avoid blocking the main emu boot thread.
+5
View File
@@ -31,6 +31,11 @@ void AudioCore::CreateSinks() {
input_sink = Sink::CreateSinkFromID(sink_id.GetValue(), audio_input_device_id.GetValue()); input_sink = Sink::CreateSinkFromID(sink_id.GetValue(), audio_input_device_id.GetValue());
} }
void AudioCore::NotifyShutdown() {
audio_manager->NotifyShutdown();
adsp->NotifyShutdown();
}
void AudioCore::Shutdown() { void AudioCore::Shutdown() {
audio_manager->Shutdown(); audio_manager->Shutdown();
} }
+2
View File
@@ -24,6 +24,8 @@ public:
explicit AudioCore(Core::System& system); explicit AudioCore(Core::System& system);
~AudioCore(); ~AudioCore();
void NotifyShutdown();
/** /**
* Shutdown the audio core. * Shutdown the audio core.
*/ */
+6 -1
View File
@@ -17,7 +17,7 @@ AudioManager::AudioManager() {
std::unique_lock l{events.GetAudioEventLock()}; std::unique_lock l{events.GetAudioEventLock()};
events.ClearEvents(); events.ClearEvents();
while (!stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
const auto timed_out{events.Wait(l, std::chrono::seconds(2))}; const auto timed_out = events.Wait(l, std::chrono::seconds{2});
if (events.CheckAudioEventSet(Event::Type::Max)) { if (events.CheckAudioEventSet(Event::Type::Max)) {
break; break;
} }
@@ -34,6 +34,11 @@ AudioManager::AudioManager() {
}); });
} }
void AudioManager::NotifyShutdown() {
events.SetAudioEvent(Event::Type::Max, true);
thread.request_stop();
}
void AudioManager::Shutdown() { void AudioManager::Shutdown() {
events.SetAudioEvent(Event::Type::Max, true); events.SetAudioEvent(Event::Type::Max, true);
if (thread.joinable()) { if (thread.joinable()) {
+4 -3
View File
@@ -39,9 +39,10 @@ class AudioManager {
public: public:
explicit AudioManager(); explicit AudioManager();
/** /// @brief Notify of impending shutdown
* Shutdown the audio manager. void NotifyShutdown();
*/
/// @brief Shutdown the audio manager.
void Shutdown(); void Shutdown();
/** /**
+44 -20
View File
@@ -110,8 +110,13 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
struct System::Impl { struct System::Impl {
explicit Impl(System& system) explicit Impl(System& system)
: kernel{system}, fs_controller{system}, hid_core{kernel}, cpu_manager{system}, : kernel{system}
reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {} , fs_controller{system}
, hid_core{kernel}
, cpu_manager{system}
, reporter{system}
, profile_manager{}
{}
u64 program_id; u64 program_id;
@@ -124,6 +129,12 @@ struct System::Impl {
core_timing.SetMulticore(is_multicore); core_timing.SetMulticore(is_multicore);
core_timing.Initialize([&system]() { system.RegisterHostThread(); }); core_timing.Initialize([&system]() { system.RegisterHostThread(); });
applet_manager.emplace(system);
frontend_applets.emplace(system);
apm_controller.emplace(core_timing);
arp_manager.emplace();
profile_manager.emplace();
// Create a default fs if one doesn't already exist. // Create a default fs if one doesn't already exist.
if (virtual_filesystem == nullptr) { if (virtual_filesystem == nullptr) {
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>(); virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
@@ -133,7 +144,7 @@ struct System::Impl {
} }
// Create default implementations of applets if one is not provided. // Create default implementations of applets if one is not provided.
frontend_applets.SetDefaultAppletsIfMissing(); frontend_applets->SetDefaultAppletsIfMissing();
auto const is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue(); auto const is_async_gpu = Settings::values.use_asynchronous_gpu_emulation.GetValue();
@@ -376,7 +387,7 @@ struct System::Impl {
// Register with applet manager // Register with applet manager
// All threads are started, begin main process execution, now that we're in the clear // All threads are started, begin main process execution, now that we're in the clear
applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params); applet_manager->CreateAndInsertByFrontendAppletParameters(std::move(process), params);
if (Settings::values.gamecard_inserted) { if (Settings::values.gamecard_inserted) {
if (Settings::values.gamecard_current_game) { if (Settings::values.gamecard_current_game) {
@@ -429,9 +440,22 @@ struct System::Impl {
Network::CancelPendingSocketOperations(); Network::CancelPendingSocketOperations();
kernel.SuspendEmulation(true); kernel.SuspendEmulation(true);
kernel.ShutdownCores(); kernel.ShutdownCores();
// Notify services helpers of shutdown
audio_core->NotifyShutdown();
// Wait for threads/services to join
kernel.CloseServices(); kernel.CloseServices();
// service shutdown
services.reset(); services.reset();
service_manager.reset(); service_manager.reset();
frontend_applets.reset();
applet_manager.reset();
apm_controller.reset();
arp_manager.reset();
profile_manager.reset();
fs_controller.Reset(); fs_controller.Reset();
cheat_engine.reset(); cheat_engine.reset();
core_timing.ClearPendingEvents(); core_timing.ClearPendingEvents();
@@ -452,7 +476,7 @@ struct System::Impl {
} }
// Reset all glue registrations // Reset all glue registrations
arp_manager.ResetAll(); arp_manager->ResetAll();
LOG_DEBUG(Core, "Shutdown OK"); LOG_DEBUG(Core, "Shutdown OK");
} }
@@ -482,13 +506,13 @@ struct System::Impl {
CpuManager cpu_manager; CpuManager cpu_manager;
Reporter reporter; Reporter reporter;
/// Applets /// Applets
Service::AM::AppletManager applet_manager; std::optional<Service::AM::AppletManager> applet_manager;
Service::AM::Frontend::FrontendAppletHolder frontend_applets; std::optional<Service::AM::Frontend::FrontendAppletHolder> frontend_applets;
/// APM (Performance) services /// APM (Performance) services
Service::APM::Controller apm_controller{core_timing}; std::optional<Service::APM::Controller> apm_controller;
/// Service State /// Service State
Service::Glue::ARPManager arp_manager; std::optional<Service::Glue::ARPManager> arp_manager;
Service::Account::ProfileManager profile_manager; std::optional<Service::Account::ProfileManager> profile_manager;
/// Network instance /// Network instance
Network::NetworkInstance network_instance; Network::NetworkInstance network_instance;
Core::SpeedLimiter speed_limiter; Core::SpeedLimiter speed_limiter;
@@ -815,19 +839,19 @@ void System::RegisterCheatList(const std::vector<Memory::CheatEntry>& list,
} }
void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) { void System::SetFrontendAppletSet(Service::AM::Frontend::FrontendAppletSet&& set) {
impl->frontend_applets.SetFrontendAppletSet(std::move(set)); impl->frontend_applets->SetFrontendAppletSet(std::move(set));
} }
Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() { Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
return impl->frontend_applets; return *impl->frontend_applets;
} }
const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const { const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const {
return impl->frontend_applets; return *impl->frontend_applets;
} }
Service::AM::AppletManager& System::GetAppletManager() { Service::AM::AppletManager& System::GetAppletManager() {
return impl->applet_manager; return *impl->applet_manager;
} }
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) { void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
@@ -868,27 +892,27 @@ const Reporter& System::GetReporter() const {
} }
Service::Glue::ARPManager& System::GetARPManager() { Service::Glue::ARPManager& System::GetARPManager() {
return impl->arp_manager; return *impl->arp_manager;
} }
const Service::Glue::ARPManager& System::GetARPManager() const { const Service::Glue::ARPManager& System::GetARPManager() const {
return impl->arp_manager; return *impl->arp_manager;
} }
Service::APM::Controller& System::GetAPMController() { Service::APM::Controller& System::GetAPMController() {
return impl->apm_controller; return *impl->apm_controller;
} }
const Service::APM::Controller& System::GetAPMController() const { const Service::APM::Controller& System::GetAPMController() const {
return impl->apm_controller; return *impl->apm_controller;
} }
Service::Account::ProfileManager& System::GetProfileManager() { Service::Account::ProfileManager& System::GetProfileManager() {
return impl->profile_manager; return *impl->profile_manager;
} }
const Service::Account::ProfileManager& System::GetProfileManager() const { const Service::Account::ProfileManager& System::GetProfileManager() const {
return impl->profile_manager; return *impl->profile_manager;
} }
void System::SetExitLocked(bool locked) { void System::SetExitLocked(bool locked) {
-1
View File
@@ -59,7 +59,6 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* t
KThread* cur_child = nullptr; KThread* cur_child = nullptr;
{ {
KScopedLightLock proc_lk(process->GetListLock()); KScopedLightLock proc_lk(process->GetListLock());
auto& thread_list = process->GetThreadList(); auto& thread_list = process->GetThreadList();
for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) {
+5
View File
@@ -1253,6 +1253,11 @@ void KernelCore::SuspendEmulation(bool suspended) {
} }
void KernelCore::ShutdownCores() { void KernelCore::ShutdownCores() {
// Notify shutdown (pre-emptively)
for (auto& sm : impl->server_managers) {
sm->NotifyShutdown();
}
impl->TerminateAllProcesses(); impl->TerminateAllProcesses();
KScopedSchedulerLock lk{*this}; KScopedSchedulerLock lk{*this};
for (auto* thread : impl->shutdown_threads) for (auto* thread : impl->shutdown_threads)
+8 -2
View File
@@ -253,6 +253,13 @@ void ServerManager::StartAdditionalHostThreads(const char* name, size_t num_thre
} }
} }
/// @brief Notifies that the system is shutting down (pre-emptively terminate threads)
void ServerManager::NotifyShutdown() {
m_stop_source.request_stop();
// Wake them up regardless
m_wakeup_event->Signal(m_system.Kernel());
}
Result ServerManager::LoopProcess() { Result ServerManager::LoopProcess() {
SCOPE_EXIT { SCOPE_EXIT {
m_stopped.Set(); m_stopped.Set();
@@ -285,9 +292,8 @@ MultiWaitHolder* ServerManager::WaitSignaled() {
this->LinkDeferred(); this->LinkDeferred();
// If we're done, return before we start waiting. // If we're done, return before we start waiting.
if (m_stop_source.stop_requested()) { if (m_stop_source.stop_requested())
return nullptr; return nullptr;
}
auto* selected = m_multi_wait.WaitAny(m_system.Kernel()); auto* selected = m_multi_wait.WaitAny(m_system.Kernel());
if (selected == std::addressof(*m_wakeup_holder)) { if (selected == std::addressof(*m_wakeup_holder)) {
+1
View File
@@ -49,6 +49,7 @@ public:
Result LoopProcess(); Result LoopProcess();
void StartAdditionalHostThreads(const char* name, size_t num_threads); void StartAdditionalHostThreads(const char* name, size_t num_threads);
void NotifyShutdown();
static void RunServer(std::unique_ptr<ServerManager>&& server); static void RunServer(std::unique_ptr<ServerManager>&& server);