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() {
return *audio_renderer;
}
+1
View File
@@ -45,6 +45,7 @@ public:
explicit ADSP(Core::System& system, Sink::Sink& sink);
~ADSP() = default;
void NotifyShutdown();
AudioRenderer::AudioRenderer& AudioRenderer();
OpusDecoder::OpusDecoder& OpusDecoder();
@@ -82,6 +82,9 @@ void OpusDecoder::Main(std::stop_token stop_token) {
while (!stop_token.stop_requested()) {
auto msg = Receive(Direction::DSP, stop_token);
if (stop_token.stop_requested())
break;
switch (msg) {
case Shutdown:
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
@@ -67,6 +67,8 @@ public:
shared_memory = &shared_memory_;
}
void NotifyShutdown();
private:
/**
* 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());
}
void AudioCore::NotifyShutdown() {
audio_manager->NotifyShutdown();
adsp->NotifyShutdown();
}
void AudioCore::Shutdown() {
audio_manager->Shutdown();
}
+2
View File
@@ -24,6 +24,8 @@ public:
explicit AudioCore(Core::System& system);
~AudioCore();
void NotifyShutdown();
/**
* Shutdown the audio core.
*/
+6 -1
View File
@@ -17,7 +17,7 @@ AudioManager::AudioManager() {
std::unique_lock l{events.GetAudioEventLock()};
events.ClearEvents();
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)) {
break;
}
@@ -34,6 +34,11 @@ AudioManager::AudioManager() {
});
}
void AudioManager::NotifyShutdown() {
events.SetAudioEvent(Event::Type::Max, true);
thread.request_stop();
}
void AudioManager::Shutdown() {
events.SetAudioEvent(Event::Type::Max, true);
if (thread.joinable()) {
+4 -3
View File
@@ -39,9 +39,10 @@ class AudioManager {
public:
explicit AudioManager();
/**
* Shutdown the audio manager.
*/
/// @brief Notify of impending shutdown
void NotifyShutdown();
/// @brief Shutdown the audio manager.
void Shutdown();
/**
+44 -20
View File
@@ -110,8 +110,13 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
struct System::Impl {
explicit Impl(System& system)
: kernel{system}, fs_controller{system}, hid_core{kernel}, cpu_manager{system},
reporter{system}, applet_manager{system}, frontend_applets{system}, profile_manager{} {}
: kernel{system}
, fs_controller{system}
, hid_core{kernel}
, cpu_manager{system}
, reporter{system}
, profile_manager{}
{}
u64 program_id;
@@ -124,6 +129,12 @@ struct System::Impl {
core_timing.SetMulticore(is_multicore);
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.
if (virtual_filesystem == nullptr) {
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
@@ -133,7 +144,7 @@ struct System::Impl {
}
// 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();
@@ -376,7 +387,7 @@ struct System::Impl {
// Register with applet manager
// 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_current_game) {
@@ -429,9 +440,22 @@ struct System::Impl {
Network::CancelPendingSocketOperations();
kernel.SuspendEmulation(true);
kernel.ShutdownCores();
// Notify services helpers of shutdown
audio_core->NotifyShutdown();
// Wait for threads/services to join
kernel.CloseServices();
// service shutdown
services.reset();
service_manager.reset();
frontend_applets.reset();
applet_manager.reset();
apm_controller.reset();
arp_manager.reset();
profile_manager.reset();
fs_controller.Reset();
cheat_engine.reset();
core_timing.ClearPendingEvents();
@@ -452,7 +476,7 @@ struct System::Impl {
}
// Reset all glue registrations
arp_manager.ResetAll();
arp_manager->ResetAll();
LOG_DEBUG(Core, "Shutdown OK");
}
@@ -482,13 +506,13 @@ struct System::Impl {
CpuManager cpu_manager;
Reporter reporter;
/// Applets
Service::AM::AppletManager applet_manager;
Service::AM::Frontend::FrontendAppletHolder frontend_applets;
std::optional<Service::AM::AppletManager> applet_manager;
std::optional<Service::AM::Frontend::FrontendAppletHolder> frontend_applets;
/// APM (Performance) services
Service::APM::Controller apm_controller{core_timing};
std::optional<Service::APM::Controller> apm_controller;
/// Service State
Service::Glue::ARPManager arp_manager;
Service::Account::ProfileManager profile_manager;
std::optional<Service::Glue::ARPManager> arp_manager;
std::optional<Service::Account::ProfileManager> profile_manager;
/// Network instance
Network::NetworkInstance network_instance;
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) {
impl->frontend_applets.SetFrontendAppletSet(std::move(set));
impl->frontend_applets->SetFrontendAppletSet(std::move(set));
}
Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() {
return impl->frontend_applets;
return *impl->frontend_applets;
}
const Service::AM::Frontend::FrontendAppletHolder& System::GetFrontendAppletHolder() const {
return impl->frontend_applets;
return *impl->frontend_applets;
}
Service::AM::AppletManager& System::GetAppletManager() {
return impl->applet_manager;
return *impl->applet_manager;
}
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
@@ -868,27 +892,27 @@ const Reporter& System::GetReporter() const {
}
Service::Glue::ARPManager& System::GetARPManager() {
return impl->arp_manager;
return *impl->arp_manager;
}
const Service::Glue::ARPManager& System::GetARPManager() const {
return impl->arp_manager;
return *impl->arp_manager;
}
Service::APM::Controller& System::GetAPMController() {
return impl->apm_controller;
return *impl->apm_controller;
}
const Service::APM::Controller& System::GetAPMController() const {
return impl->apm_controller;
return *impl->apm_controller;
}
Service::Account::ProfileManager& System::GetProfileManager() {
return impl->profile_manager;
return *impl->profile_manager;
}
const Service::Account::ProfileManager& System::GetProfileManager() const {
return impl->profile_manager;
return *impl->profile_manager;
}
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;
{
KScopedLightLock proc_lk(process->GetListLock());
auto& thread_list = process->GetThreadList();
for (auto it = thread_list.begin(); it != thread_list.end(); ++it) {
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() {
// Notify shutdown (pre-emptively)
for (auto& sm : impl->server_managers) {
sm->NotifyShutdown();
}
impl->TerminateAllProcesses();
KScopedSchedulerLock lk{*this};
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() {
SCOPE_EXIT {
m_stopped.Set();
@@ -285,9 +292,8 @@ MultiWaitHolder* ServerManager::WaitSignaled() {
this->LinkDeferred();
// If we're done, return before we start waiting.
if (m_stop_source.stop_requested()) {
if (m_stop_source.stop_requested())
return nullptr;
}
auto* selected = m_multi_wait.WaitAny(m_system.Kernel());
if (selected == std::addressof(*m_wakeup_holder)) {
+1
View File
@@ -49,6 +49,7 @@ public:
Result LoopProcess();
void StartAdditionalHostThreads(const char* name, size_t num_threads);
void NotifyShutdown();
static void RunServer(std::unique_ptr<ServerManager>&& server);