hle: kernel: Fix service_threads access to be thread safe.
- CreateServiceThread and ReleaseServiceThread can be accessed by different threads, uses a lock to make this thread safe. - Fixes a rare crash in Pokemon Sword/Shield that can occur when a new service thread is being created while an old one is being destroyed.
This commit is contained in:
parent
f1aa7ff893
commit
2147240e47
1 changed files with 27 additions and 7 deletions
|
@ -121,7 +121,7 @@ struct KernelCore::Impl {
|
||||||
object_list_container.Finalize();
|
object_list_container.Finalize();
|
||||||
|
|
||||||
// Ensures all service threads gracefully shutdown.
|
// Ensures all service threads gracefully shutdown.
|
||||||
service_threads.clear();
|
ClearServiceThreads();
|
||||||
|
|
||||||
next_object_id = 0;
|
next_object_id = 0;
|
||||||
next_kernel_process_id = KProcess::InitialKIPIDMin;
|
next_kernel_process_id = KProcess::InitialKIPIDMin;
|
||||||
|
@ -704,11 +704,35 @@ struct KernelCore::Impl {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel,
|
||||||
|
const std::string& name) {
|
||||||
|
auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, 1, name);
|
||||||
|
{
|
||||||
|
std::lock_guard lk(service_threads_lock);
|
||||||
|
service_threads.emplace(service_thread);
|
||||||
|
}
|
||||||
|
return service_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
|
||||||
|
auto strong_ptr = service_thread.lock();
|
||||||
|
{
|
||||||
|
std::lock_guard lk(service_threads_lock);
|
||||||
|
service_threads.erase(strong_ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearServiceThreads() {
|
||||||
|
std::lock_guard lk(service_threads_lock);
|
||||||
|
service_threads.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::mutex server_ports_lock;
|
std::mutex server_ports_lock;
|
||||||
std::mutex server_sessions_lock;
|
std::mutex server_sessions_lock;
|
||||||
std::mutex registered_objects_lock;
|
std::mutex registered_objects_lock;
|
||||||
std::mutex registered_in_use_objects_lock;
|
std::mutex registered_in_use_objects_lock;
|
||||||
std::mutex dummy_thread_lock;
|
std::mutex dummy_thread_lock;
|
||||||
|
std::mutex service_threads_lock;
|
||||||
|
|
||||||
std::atomic<u32> next_object_id{0};
|
std::atomic<u32> next_object_id{0};
|
||||||
std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin};
|
std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin};
|
||||||
|
@ -1099,15 +1123,11 @@ 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);
|
return impl->CreateServiceThread(*this, name);
|
||||||
impl->service_threads.emplace(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) {
|
||||||
if (auto strong_ptr = service_thread.lock()) {
|
impl->ReleaseServiceThread(service_thread);
|
||||||
impl->service_threads.erase(strong_ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() {
|
Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() {
|
||||||
|
|
Loading…
Reference in a new issue