hle: kernel: Remove service thread manager and use weak_ptr.
- We no longer need to queue up service threads to be destroyed. - Fixes a race condition where a thread could be destroyed too early, which caused a crash in Pokemon Sword/Shield.
This commit is contained in:
parent
df91c9f5e6
commit
a493ab2678
|
@ -85,8 +85,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void ClientDisconnected(KServerSession* session);
|
void ClientDisconnected(KServerSession* session);
|
||||||
|
|
||||||
std::shared_ptr<ServiceThread> GetServiceThread() const {
|
std::weak_ptr<ServiceThread> GetServiceThread() const {
|
||||||
return service_thread.lock();
|
return service_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -152,7 +152,7 @@ public:
|
||||||
session_handler = std::move(handler);
|
session_handler = std::move(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ServiceThread> GetServiceThread() const {
|
std::weak_ptr<ServiceThread> GetServiceThread() const {
|
||||||
return session_handler->GetServiceThread();
|
return session_handler->GetServiceThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,7 +119,7 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor
|
||||||
|
|
||||||
context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
|
context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
|
||||||
|
|
||||||
if (auto strong_ptr = manager->GetServiceThread(); strong_ptr) {
|
if (auto strong_ptr = manager->GetServiceThread().lock()) {
|
||||||
strong_ptr->QueueSyncRequest(*parent, std::move(context));
|
strong_ptr->QueueSyncRequest(*parent, std::move(context));
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -63,8 +63,6 @@ struct KernelCore::Impl {
|
||||||
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
|
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
|
||||||
global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
|
global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
|
||||||
|
|
||||||
service_thread_manager =
|
|
||||||
std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager");
|
|
||||||
is_phantom_mode_for_singlecore = false;
|
is_phantom_mode_for_singlecore = false;
|
||||||
|
|
||||||
InitializePhysicalCores();
|
InitializePhysicalCores();
|
||||||
|
@ -96,7 +94,6 @@ struct KernelCore::Impl {
|
||||||
process_list.clear();
|
process_list.clear();
|
||||||
|
|
||||||
// Ensures all service threads gracefully shutdown
|
// Ensures all service threads gracefully shutdown
|
||||||
service_thread_manager.reset();
|
|
||||||
service_threads.clear();
|
service_threads.clear();
|
||||||
|
|
||||||
next_object_id = 0;
|
next_object_id = 0;
|
||||||
|
@ -680,10 +677,6 @@ struct KernelCore::Impl {
|
||||||
// Threads used for services
|
// Threads used for services
|
||||||
std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
|
std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
|
||||||
|
|
||||||
// Service threads are managed by a worker thread, so that a calling service thread can queue up
|
|
||||||
// the release of itself
|
|
||||||
std::unique_ptr<Common::ThreadWorker> service_thread_manager;
|
|
||||||
|
|
||||||
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads;
|
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads;
|
||||||
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
|
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
|
||||||
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
|
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
|
||||||
|
@ -986,17 +979,14 @@ void KernelCore::ExitSVCProfile() {
|
||||||
|
|
||||||
std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
|
std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
|
||||||
auto service_thread = std::make_shared<Kernel::ServiceThread>(*this, 1, name);
|
auto service_thread = std::make_shared<Kernel::ServiceThread>(*this, 1, name);
|
||||||
impl->service_thread_manager->QueueWork(
|
impl->service_threads.emplace(service_thread);
|
||||||
[this, service_thread] { impl->service_threads.emplace(service_thread); });
|
|
||||||
return service_thread;
|
return service_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
|
void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
|
||||||
impl->service_thread_manager->QueueWork([this, service_thread] {
|
if (auto strong_ptr = service_thread.lock()) {
|
||||||
if (auto strong_ptr = service_thread.lock()) {
|
impl->service_threads.erase(strong_ptr);
|
||||||
impl->service_threads.erase(strong_ptr);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() {
|
Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() {
|
||||||
|
|
Loading…
Reference in New Issue