Просмотр исходного кода

Merge pull request #8122 from bunnei/improve-thread-usage

Improve usage of service host threads
bunnei 4 лет назад
Родитель
Сommit
eb8c8db899

+ 9 - 2
src/core/hle/kernel/hle_ipc.cpp

@@ -24,8 +24,15 @@
 
 
 namespace Kernel {
 namespace Kernel {
 
 
-SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_)
-    : kernel{kernel_}, service_thread{kernel.CreateServiceThread(service_name_)} {}
+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();
+    }
+}
 
 
 SessionRequestHandler::~SessionRequestHandler() {
 SessionRequestHandler::~SessionRequestHandler() {
     kernel.ReleaseServiceThread(service_thread);
     kernel.ReleaseServiceThread(service_thread);

+ 7 - 1
src/core/hle/kernel/hle_ipc.h

@@ -33,6 +33,11 @@ namespace Service {
 class ServiceFrameworkBase;
 class ServiceFrameworkBase;
 }
 }
 
 
+enum class ServiceThreadType {
+    Default,
+    CreateNew,
+};
+
 namespace Kernel {
 namespace Kernel {
 
 
 class Domain;
 class Domain;
@@ -57,7 +62,8 @@ enum class ThreadWakeupReason;
  */
  */
 class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
 class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
 public:
 public:
-    SessionRequestHandler(KernelCore& kernel, const char* service_name_);
+    SessionRequestHandler(KernelCore& kernel_, const char* service_name_,
+                          ServiceThreadType thread_type);
     virtual ~SessionRequestHandler();
     virtual ~SessionRequestHandler();
 
 
     /**
     /**

+ 13 - 1
src/core/hle/kernel/kernel.cpp

@@ -61,6 +61,7 @@ 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);
         global_handle_table->Initialize(KHandleTable::MaxTableSize);
         global_handle_table->Initialize(KHandleTable::MaxTableSize);
+        default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread");
 
 
         is_phantom_mode_for_singlecore = false;
         is_phantom_mode_for_singlecore = false;
 
 
@@ -677,6 +678,12 @@ struct KernelCore::Impl {
 
 
     void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
     void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
         if (auto strong_ptr = service_thread.lock()) {
         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;
+            }
+
             service_threads_manager.QueueWork(
             service_threads_manager.QueueWork(
                 [this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); });
                 [this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); });
         }
         }
@@ -739,7 +746,8 @@ struct KernelCore::Impl {
     std::unique_ptr<KMemoryLayout> memory_layout;
     std::unique_ptr<KMemoryLayout> memory_layout;
 
 
     // Threads used for services
     // Threads used for services
-    std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
+    std::unordered_set<std::shared_ptr<ServiceThread>> service_threads;
+    std::weak_ptr<ServiceThread> default_service_thread;
     Common::ThreadWorker service_threads_manager;
     Common::ThreadWorker service_threads_manager;
 
 
     std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads;
     std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads;
@@ -1065,6 +1073,10 @@ std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::
     return impl->CreateServiceThread(*this, name);
     return impl->CreateServiceThread(*this, name);
 }
 }
 
 
+std::weak_ptr<Kernel::ServiceThread> KernelCore::GetDefaultServiceThread() const {
+    return impl->default_service_thread;
+}
+
 void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
 void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
     impl->ReleaseServiceThread(service_thread);
     impl->ReleaseServiceThread(service_thread);
 }
 }

+ 13 - 3
src/core/hle/kernel/kernel.h

@@ -271,15 +271,25 @@ public:
     void ExitSVCProfile();
     void ExitSVCProfile();
 
 
     /**
     /**
-     * Creates an HLE service thread, which are used to execute service routines asynchronously.
-     * While these are allocated per ServerSession, these need to be owned and managed outside
-     * of ServerSession to avoid a circular dependency.
+     * Creates a host thread to execute HLE service requests, which are used to execute service
+     * routines asynchronously. While these are allocated per ServerSession, these need to be owned
+     * and managed outside of ServerSession to avoid a circular dependency. In general, most
+     * services can just use the default service thread, and not need their own host service thread.
+     * See GetDefaultServiceThread.
      * @param name String name for the ServerSession creating this thread, used for debug
      * @param name String name for the ServerSession creating this thread, used for debug
      * purposes.
      * purposes.
      * @returns The a weak pointer newly created service thread.
      * @returns The a weak pointer newly created service thread.
      */
      */
     std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(const std::string& name);
     std::weak_ptr<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.
+     */
+    std::weak_ptr<Kernel::ServiceThread> GetDefaultServiceThread() const;
+
     /**
     /**
      * Releases a HLE service thread, instructing KernelCore to free it. This should be called when
      * Releases a HLE service thread, instructing KernelCore to free it. This should be called when
      * the ServerSession associated with the thread is destroyed.
      * the ServerSession associated with the thread is destroyed.

+ 4 - 3
src/core/hle/service/audio/audout_u.cpp

@@ -41,9 +41,10 @@ public:
     explicit IAudioOut(Core::System& system_, AudoutParams audio_params_,
     explicit IAudioOut(Core::System& system_, AudoutParams audio_params_,
                        AudioCore::AudioOut& audio_core_, std::string&& device_name_,
                        AudioCore::AudioOut& audio_core_, std::string&& device_name_,
                        std::string&& unique_name)
                        std::string&& unique_name)
-        : ServiceFramework{system_, "IAudioOut"}, audio_core{audio_core_},
-          device_name{std::move(device_name_)}, audio_params{audio_params_},
-          main_memory{system.Memory()}, service_context{system_, "IAudioOut"} {
+        : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew},
+          audio_core{audio_core_}, device_name{std::move(device_name_)},
+          audio_params{audio_params_}, main_memory{system.Memory()}, service_context{system_,
+                                                                                     "IAudioOut"} {
         // clang-format off
         // clang-format off
         static const FunctionInfo functions[] = {
         static const FunctionInfo functions[] = {
             {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
             {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},

+ 2 - 1
src/core/hle/service/audio/audren_u.cpp

@@ -24,7 +24,8 @@ public:
     explicit IAudioRenderer(Core::System& system_,
     explicit IAudioRenderer(Core::System& system_,
                             const AudioCommon::AudioRendererParameter& audren_params,
                             const AudioCommon::AudioRendererParameter& audren_params,
                             const std::size_t instance_number)
                             const std::size_t instance_number)
-        : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"} {
+        : ServiceFramework{system_, "IAudioRenderer", ServiceThreadType::CreateNew},
+          service_context{system_, "IAudioRenderer"} {
         // clang-format off
         // clang-format off
         static const FunctionInfo functions[] = {
         static const FunctionInfo functions[] = {
             {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
             {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},

+ 8 - 5
src/core/hle/service/filesystem/fsp_srv.cpp

@@ -58,7 +58,8 @@ enum class FileSystemType : u8 {
 class IStorage final : public ServiceFramework<IStorage> {
 class IStorage final : public ServiceFramework<IStorage> {
 public:
 public:
     explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_)
     explicit IStorage(Core::System& system_, FileSys::VirtualFile backend_)
-        : ServiceFramework{system_, "IStorage"}, backend(std::move(backend_)) {
+        : ServiceFramework{system_, "IStorage", ServiceThreadType::CreateNew},
+          backend(std::move(backend_)) {
         static const FunctionInfo functions[] = {
         static const FunctionInfo functions[] = {
             {0, &IStorage::Read, "Read"},
             {0, &IStorage::Read, "Read"},
             {1, nullptr, "Write"},
             {1, nullptr, "Write"},
@@ -116,7 +117,8 @@ private:
 class IFile final : public ServiceFramework<IFile> {
 class IFile final : public ServiceFramework<IFile> {
 public:
 public:
     explicit IFile(Core::System& system_, FileSys::VirtualFile backend_)
     explicit IFile(Core::System& system_, FileSys::VirtualFile backend_)
-        : ServiceFramework{system_, "IFile"}, backend(std::move(backend_)) {
+        : ServiceFramework{system_, "IFile", ServiceThreadType::CreateNew},
+          backend(std::move(backend_)) {
         static const FunctionInfo functions[] = {
         static const FunctionInfo functions[] = {
             {0, &IFile::Read, "Read"},
             {0, &IFile::Read, "Read"},
             {1, &IFile::Write, "Write"},
             {1, &IFile::Write, "Write"},
@@ -252,7 +254,8 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec
 class IDirectory final : public ServiceFramework<IDirectory> {
 class IDirectory final : public ServiceFramework<IDirectory> {
 public:
 public:
     explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_)
     explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_)
-        : ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) {
+        : ServiceFramework{system_, "IDirectory", ServiceThreadType::CreateNew},
+          backend(std::move(backend_)) {
         static const FunctionInfo functions[] = {
         static const FunctionInfo functions[] = {
             {0, &IDirectory::Read, "Read"},
             {0, &IDirectory::Read, "Read"},
             {1, &IDirectory::GetEntryCount, "GetEntryCount"},
             {1, &IDirectory::GetEntryCount, "GetEntryCount"},
@@ -308,8 +311,8 @@ private:
 class IFileSystem final : public ServiceFramework<IFileSystem> {
 class IFileSystem final : public ServiceFramework<IFileSystem> {
 public:
 public:
     explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_)
     explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_)
-        : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move(
-                                                                                      size_)} {
+        : ServiceFramework{system_, "IFileSystem", ServiceThreadType::CreateNew},
+          backend{std::move(backend_)}, size{std::move(size_)} {
         static const FunctionInfo functions[] = {
         static const FunctionInfo functions[] = {
             {0, &IFileSystem::CreateFile, "CreateFile"},
             {0, &IFileSystem::CreateFile, "CreateFile"},
             {1, &IFileSystem::DeleteFile, "DeleteFile"},
             {1, &IFileSystem::DeleteFile, "DeleteFile"},

+ 1 - 1
src/core/hle/service/nvdrv/nvdrv_interface.cpp

@@ -230,7 +230,7 @@ void NVDRV::DumpGraphicsMemoryInfo(Kernel::HLERequestContext& ctx) {
 }
 }
 
 
 NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name)
 NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name)
-    : ServiceFramework{system_, name}, nvdrv{std::move(nvdrv_)} {
+    : ServiceFramework{system_, name, ServiceThreadType::CreateNew}, nvdrv{std::move(nvdrv_)} {
     static const FunctionInfo functions[] = {
     static const FunctionInfo functions[] = {
         {0, &NVDRV::Open, "Open"},
         {0, &NVDRV::Open, "Open"},
         {1, &NVDRV::Ioctl1, "Ioctl"},
         {1, &NVDRV::Ioctl1, "Ioctl"},

+ 3 - 2
src/core/hle/service/service.cpp

@@ -91,8 +91,9 @@ namespace Service {
 }
 }
 
 
 ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
 ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
-                                           u32 max_sessions_, InvokerFn* handler_invoker_)
-    : SessionRequestHandler(system_.Kernel(), service_name_), system{system_},
+                                           ServiceThreadType thread_type, u32 max_sessions_,
+                                           InvokerFn* handler_invoker_)
+    : SessionRequestHandler(system_.Kernel(), service_name_, thread_type), system{system_},
       service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {}
       service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {}
 
 
 ServiceFrameworkBase::~ServiceFrameworkBase() {
 ServiceFrameworkBase::~ServiceFrameworkBase() {

+ 9 - 5
src/core/hle/service/service.h

@@ -114,7 +114,8 @@ private:
                            Kernel::HLERequestContext& ctx);
                            Kernel::HLERequestContext& ctx);
 
 
     explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_,
     explicit ServiceFrameworkBase(Core::System& system_, const char* service_name_,
-                                  u32 max_sessions_, InvokerFn* handler_invoker_);
+                                  ServiceThreadType thread_type, u32 max_sessions_,
+                                  InvokerFn* handler_invoker_);
     ~ServiceFrameworkBase() override;
     ~ServiceFrameworkBase() override;
 
 
     void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
     void RegisterHandlersBase(const FunctionInfoBase* functions, std::size_t n);
@@ -176,14 +177,17 @@ protected:
     /**
     /**
      * Initializes the handler with no functions installed.
      * Initializes the handler with no functions installed.
      *
      *
-     * @param system_       The system context to construct this service under.
+     * @param system_ The system context to construct this service under.
      * @param service_name_ Name of the service.
      * @param service_name_ Name of the service.
-     * @param max_sessions_ Maximum number of sessions that can be
-     *                      connected to this service at the same time.
+     * @param thread_type Specifies the thread type for this service. If this is set to CreateNew,
+     *                    it creates a new thread for it, otherwise this uses the default thread.
+     * @param max_sessions_ Maximum number of sessions that can be connected to this service at the
+     * same time.
      */
      */
     explicit ServiceFramework(Core::System& system_, const char* service_name_,
     explicit ServiceFramework(Core::System& system_, const char* service_name_,
+                              ServiceThreadType thread_type = ServiceThreadType::Default,
                               u32 max_sessions_ = ServerSessionCountMax)
                               u32 max_sessions_ = ServerSessionCountMax)
-        : ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {}
+        : ServiceFrameworkBase(system_, service_name_, thread_type, max_sessions_, Invoker) {}
 
 
     /// Registers handlers in the service.
     /// Registers handlers in the service.
     template <std::size_t N>
     template <std::size_t N>

+ 1 - 1
src/core/hle/service/sm/sm.cpp

@@ -206,7 +206,7 @@ void SM::UnregisterService(Kernel::HLERequestContext& ctx) {
 }
 }
 
 
 SM::SM(ServiceManager& service_manager_, Core::System& system_)
 SM::SM(ServiceManager& service_manager_, Core::System& system_)
-    : ServiceFramework{system_, "sm:", 4},
+    : ServiceFramework{system_, "sm:", ServiceThreadType::Default, 4},
       service_manager{service_manager_}, kernel{system_.Kernel()} {
       service_manager{service_manager_}, kernel{system_.Kernel()} {
     RegisterHandlers({
     RegisterHandlers({
         {0, &SM::Initialize, "Initialize"},
         {0, &SM::Initialize, "Initialize"},

+ 2 - 1
src/core/hle/service/sockets/bsd.cpp

@@ -837,7 +837,8 @@ void BSD::BuildErrnoResponse(Kernel::HLERequestContext& ctx, Errno bsd_errno) co
     rb.PushEnum(bsd_errno);
     rb.PushEnum(bsd_errno);
 }
 }
 
 
-BSD::BSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
+BSD::BSD(Core::System& system_, const char* name)
+    : ServiceFramework{system_, name, ServiceThreadType::CreateNew} {
     // clang-format off
     // clang-format off
     static const FunctionInfo functions[] = {
     static const FunctionInfo functions[] = {
         {0, &BSD::RegisterClient, "RegisterClient"},
         {0, &BSD::RegisterClient, "RegisterClient"},

+ 2 - 1
src/core/hle/service/vi/vi.cpp

@@ -77,7 +77,8 @@ static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size");
 class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
 class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
 public:
 public:
     explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_)
     explicit IHOSBinderDriver(Core::System& system_, NVFlinger::HosBinderDriverServer& server_)
-        : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) {
+        : ServiceFramework{system_, "IHOSBinderDriver", ServiceThreadType::CreateNew},
+          server(server_) {
         static const FunctionInfo functions[] = {
         static const FunctionInfo functions[] = {
             {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
             {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
             {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
             {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},