Merge pull request #9199 from liamwhite/service-oops
service_thread: fix deletion
This commit is contained in:
		@@ -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;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user