Merge pull request #9398 from liamwhite/fail

general: improve handling of system startup failure
This commit is contained in:
bunnei 2022-12-12 14:37:42 -08:00 committed by GitHub
commit 339a37f8cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 21 deletions

View file

@ -11,6 +11,7 @@
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/polyfill_thread.h"
namespace Common { namespace Common {
@ -69,7 +70,7 @@ public:
explicit Barrier(std::size_t count_) : count(count_) {} explicit Barrier(std::size_t count_) : count(count_) {}
/// Blocks until all "count" threads have called Sync() /// Blocks until all "count" threads have called Sync()
void Sync() { bool Sync(std::stop_token token = {}) {
std::unique_lock lk{mutex}; std::unique_lock lk{mutex};
const std::size_t current_generation = generation; const std::size_t current_generation = generation;
@ -77,14 +78,16 @@ public:
generation++; generation++;
waiting = 0; waiting = 0;
condvar.notify_all(); condvar.notify_all();
return true;
} else { } else {
condvar.wait(lk, CondvarWait(condvar, lk, token,
[this, current_generation] { return current_generation != generation; }); [this, current_generation] { return current_generation != generation; });
return !token.stop_requested();
} }
} }
private: private:
std::condition_variable condvar; std::condition_variable_any condvar;
std::mutex mutex; std::mutex mutex;
std::size_t count; std::size_t count;
std::size_t waiting = 0; std::size_t waiting = 0;

View file

@ -389,7 +389,9 @@ struct System::Impl {
kernel.ShutdownCores(); kernel.ShutdownCores();
cpu_manager.Shutdown(); cpu_manager.Shutdown();
debugger.reset(); debugger.reset();
services->KillNVNFlinger(); if (services) {
services->KillNVNFlinger();
}
kernel.CloseServices(); kernel.CloseServices();
services.reset(); services.reset();
service_manager.reset(); service_manager.reset();

View file

@ -20,23 +20,20 @@ namespace Core {
CpuManager::CpuManager(System& system_) : system{system_} {} CpuManager::CpuManager(System& system_) : system{system_} {}
CpuManager::~CpuManager() = default; CpuManager::~CpuManager() = default;
void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager,
std::size_t core) {
cpu_manager.RunThread(core);
}
void CpuManager::Initialize() { void CpuManager::Initialize() {
num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1; num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1;
gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1); gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1);
for (std::size_t core = 0; core < num_cores; core++) { for (std::size_t core = 0; core < num_cores; core++) {
core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core); core_data[core].host_thread =
std::jthread([this, core](std::stop_token token) { RunThread(token, core); });
} }
} }
void CpuManager::Shutdown() { void CpuManager::Shutdown() {
for (std::size_t core = 0; core < num_cores; core++) { for (std::size_t core = 0; core < num_cores; core++) {
if (core_data[core].host_thread.joinable()) { if (core_data[core].host_thread.joinable()) {
core_data[core].host_thread.request_stop();
core_data[core].host_thread.join(); core_data[core].host_thread.join();
} }
} }
@ -184,7 +181,7 @@ void CpuManager::ShutdownThread() {
UNREACHABLE(); UNREACHABLE();
} }
void CpuManager::RunThread(std::size_t core) { void CpuManager::RunThread(std::stop_token token, std::size_t core) {
/// Initialization /// Initialization
system.RegisterCoreThread(core); system.RegisterCoreThread(core);
std::string name; std::string name;
@ -206,7 +203,9 @@ void CpuManager::RunThread(std::size_t core) {
}); });
// Running // Running
gpu_barrier->Sync(); if (!gpu_barrier->Sync(token)) {
return;
}
if (!is_async_gpu && !is_multicore) { if (!is_async_gpu && !is_multicore) {
system.GPU().ObtainContext(); system.GPU().ObtainContext();

View file

@ -81,12 +81,10 @@ private:
void SingleCoreRunGuestThread(); void SingleCoreRunGuestThread();
void SingleCoreRunIdleThread(); void SingleCoreRunIdleThread();
static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
void GuestActivate(); void GuestActivate();
void HandleInterrupt(); void HandleInterrupt();
void ShutdownThread(); void ShutdownThread();
void RunThread(std::size_t core); void RunThread(std::stop_token stop_token, std::size_t core);
struct CoreData { struct CoreData {
std::shared_ptr<Common::Fiber> host_context; std::shared_ptr<Common::Fiber> host_context;

View file

@ -104,12 +104,16 @@ struct KernelCore::Impl {
} }
void CloseCurrentProcess() { void CloseCurrentProcess() {
(*current_process).Finalize(); KProcess* old_process = current_process.exchange(nullptr);
// current_process->Close(); if (old_process == nullptr) {
// TODO: The current process should be destroyed based on accurate ref counting after return;
}
// old_process->Close();
// TODO: The process should be destroyed based on accurate ref counting after
// calling Close(). Adding a manual Destroy() call instead to avoid a memory leak. // calling Close(). Adding a manual Destroy() call instead to avoid a memory leak.
(*current_process).Destroy(); old_process->Finalize();
current_process = nullptr; old_process->Destroy();
} }
void Shutdown() { void Shutdown() {