mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-26 11:08:02 +00:00
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user