Merge pull request #9199 from liamwhite/service-oops

service_thread: fix deletion
master
Mai 2022-11-09 03:25:53 +07:00 committed by GitHub
commit ad9e5bc5b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 39 deletions

@ -27,16 +27,12 @@ namespace Kernel {
SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
ServiceThreadType thread_type)
: kernel{kernel_} {
if (thread_type == ServiceThreadType::CreateNew) {
service_thread = kernel.CreateServiceThread(service_name_);
} else {
service_thread = kernel.GetDefaultServiceThread();
}
}
: kernel{kernel_}, service_thread{thread_type == ServiceThreadType::CreateNew
? kernel.CreateServiceThread(service_name_)
: kernel.GetDefaultServiceThread()} {}
SessionRequestHandler::~SessionRequestHandler() {
kernel.ReleaseServiceThread(service_thread.lock());
kernel.ReleaseServiceThread(service_thread);
}
void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
@ -49,7 +45,7 @@ void SessionRequestHandler::AcceptSession(KServerPort* server_port) {
void SessionRequestHandler::RegisterSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager) {
manager->SetSessionHandler(shared_from_this());
service_thread.lock()->RegisterServerSession(server_session, manager);
service_thread.RegisterServerSession(server_session, manager);
server_session->Close();
}

@ -82,13 +82,13 @@ public:
void RegisterSession(KServerSession* server_session,
std::shared_ptr<SessionRequestManager> manager);
std::weak_ptr<ServiceThread> GetServiceThread() const {
ServiceThread& GetServiceThread() const {
return service_thread;
}
protected:
KernelCore& kernel;
std::weak_ptr<ServiceThread> service_thread;
ServiceThread& service_thread;
};
using SessionRequestHandlerWeakPtr = std::weak_ptr<SessionRequestHandler>;
@ -154,7 +154,7 @@ public:
session_handler = std::move(handler);
}
std::weak_ptr<ServiceThread> GetServiceThread() const {
ServiceThread& GetServiceThread() const {
return session_handler->GetServiceThread();
}

@ -93,7 +93,7 @@ struct KernelCore::Impl {
RegisterHostThread();
default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread");
default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
}
void InitializeCores() {
@ -779,33 +779,31 @@ struct KernelCore::Impl {
search->second(system.ServiceManager(), server_port);
}
std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel,
const std::string& name) {
auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, name);
Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) {
auto* ptr = new ServiceThread(kernel, name);
service_threads_manager.QueueWork(
[this, service_thread]() { service_threads.emplace(service_thread); });
[this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); });
return service_thread;
return *ptr;
}
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
if (auto strong_ptr = service_thread.lock()) {
if (strong_ptr == default_service_thread.lock()) {
// Nothing to do here, the service is using default_service_thread, which will be
// released on shutdown.
return;
}
void ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
auto* ptr = &service_thread;
service_threads_manager.QueueWork(
[this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); });
if (ptr == default_service_thread) {
// Nothing to do here, the service is using default_service_thread, which will be
// released on shutdown.
return;
}
service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
}
void ClearServiceThreads() {
service_threads_manager.QueueWork([this] {
service_threads.clear();
default_service_thread.reset();
default_service_thread = nullptr;
service_thread_barrier.Sync();
});
service_thread_barrier.Sync();
@ -881,8 +879,8 @@ struct KernelCore::Impl {
std::unique_ptr<KMemoryLayout> memory_layout;
// Threads used for services
std::unordered_set<std::shared_ptr<ServiceThread>> service_threads;
std::weak_ptr<ServiceThread> default_service_thread;
std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads;
ServiceThread* default_service_thread{};
Common::ThreadWorker service_threads_manager;
Common::Barrier service_thread_barrier;
@ -1239,15 +1237,15 @@ void KernelCore::ExitSVCProfile() {
MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
}
std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) {
return impl->CreateServiceThread(*this, name);
}
std::weak_ptr<Kernel::ServiceThread> KernelCore::GetDefaultServiceThread() const {
return impl->default_service_thread;
Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const {
return *impl->default_service_thread;
}
void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
impl->ReleaseServiceThread(service_thread);
}

@ -309,24 +309,24 @@ public:
* See GetDefaultServiceThread.
* @param name String name for the ServerSession creating this thread, used for debug
* purposes.
* @returns The a weak pointer newly created service thread.
* @returns A reference to the newly created service thread.
*/
std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name);
Kernel::ServiceThread& CreateServiceThread(const std::string& name);
/**
* Gets the default host service thread, which executes HLE service requests. Unless service
* requests need to block on the host, the default service thread should be used in favor of
* creating a new service thread.
* @returns The a weak pointer for the default service thread.
* @returns A reference to the default service thread.
*/
std::weak_ptr<Kernel::ServiceThread> GetDefaultServiceThread() const;
Kernel::ServiceThread& GetDefaultServiceThread() const;
/**
* Releases a HLE service thread, instructing KernelCore to free it. This should be called when
* the ServerSession associated with the thread is destroyed.
* @param service_thread Service thread to release.
*/
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread);
void ReleaseServiceThread(Kernel::ServiceThread& service_thread);
/// Workaround for single-core mode when preempting threads while idle.
bool IsPhantomModeForSingleCore() const;