mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-21 09:55:14 +00:00
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ public:
|
||||
explicit AudioCore(Core::System& system);
|
||||
~AudioCore();
|
||||
|
||||
void NotifyShutdown();
|
||||
|
||||
/**
|
||||
* Shutdown the audio core.
|
||||
*/
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user