diff options
| author | bunnei <bunneidev@gmail.com> | 2020-12-09 21:27:05 -0800 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2020-12-28 16:33:47 -0800 | 
| commit | 28281ae2500a4af9c36c26de5ba07b80d440b335 (patch) | |
| tree | 8113b0af071dbe7004f5f072862d47f557a9eb27 /src/core | |
| parent | 7dbdda908c8eca9a47475112ef2f32059e6e2de2 (diff) | |
core: hle: server_session: Use separate threads for each service connection.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.cpp | 20 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.h | 12 | ||||
| -rw-r--r-- | src/core/hle/kernel/service_thread.cpp | 100 | ||||
| -rw-r--r-- | src/core/hle/kernel/service_thread.h | 27 | 
6 files changed, 140 insertions, 23 deletions
| diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 59bd3d2a6..87712a3ce 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -202,6 +202,8 @@ add_library(core STATIC      hle/kernel/server_port.h      hle/kernel/server_session.cpp      hle/kernel/server_session.h +    hle/kernel/service_thread.cpp +    hle/kernel/service_thread.h      hle/kernel/session.cpp      hle/kernel/session.h      hle/kernel/shared_memory.cpp diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 04cae3a43..1bf4c3355 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -329,7 +329,7 @@ struct KernelCore::Impl {      std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES};      // Number of host threads is a relatively high number to avoid overflowing -    static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64; +    static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 1024;      std::atomic<size_t> num_host_threads{0};      std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS>          register_host_thread_keys{}; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index a35c8aa4b..079c3911a 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -32,12 +32,9 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern                                                                  std::string name) {      std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; -    session->request_event = -        Core::Timing::CreateEvent(name, [session](std::uintptr_t, std::chrono::nanoseconds) { -            session->CompleteSyncRequest(); -        });      session->name = std::move(name);      session->parent = std::move(parent); +    session->service_thread = std::make_unique<ServiceThread>(kernel);      return MakeResult(std::move(session));  } @@ -142,16 +139,12 @@ ResultCode ServerSession::QueueSyncRequest(std::shared_ptr<Thread> thread,          std::make_shared<HLERequestContext>(kernel, memory, SharedFrom(this), std::move(thread));      context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); -    request_queue.Push(std::move(context)); +    service_thread->QueueSyncRequest(*this, std::move(context));      return RESULT_SUCCESS;  } -ResultCode ServerSession::CompleteSyncRequest() { -    ASSERT(!request_queue.Empty()); - -    auto& context = *request_queue.Front(); - +ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) {      ResultCode result = RESULT_SUCCESS;      // If the session has been converted to a domain, handle the domain request      if (IsDomain() && context.HasDomainMessageHeader()) { @@ -177,18 +170,13 @@ ResultCode ServerSession::CompleteSyncRequest() {          }      } -    request_queue.Pop(); -      return result;  }  ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,                                              Core::Memory::Memory& memory,                                              Core::Timing::CoreTiming& core_timing) { -    const ResultCode result = QueueSyncRequest(std::move(thread), memory); -    const auto delay = std::chrono::nanoseconds{kernel.IsMulticore() ? 0 : 20000}; -    core_timing.ScheduleEvent(delay, request_event, {}); -    return result; +    return QueueSyncRequest(std::move(thread), memory);  }  } // namespace Kernel diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index d23e9ec68..8466b03e6 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -10,6 +10,7 @@  #include <vector>  #include "common/threadsafe_queue.h" +#include "core/hle/kernel/service_thread.h"  #include "core/hle/kernel/synchronization_object.h"  #include "core/hle/result.h" @@ -43,6 +44,8 @@ class Thread;   * TLS buffer and control is transferred back to it.   */  class ServerSession final : public SynchronizationObject { +    friend class ServiceThread; +  public:      explicit ServerSession(KernelCore& kernel);      ~ServerSession() override; @@ -132,7 +135,7 @@ private:      ResultCode QueueSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory);      /// Completes a sync request from the emulated application. -    ResultCode CompleteSyncRequest(); +    ResultCode CompleteSyncRequest(HLERequestContext& context);      /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an      /// object handle. @@ -163,11 +166,8 @@ private:      /// The name of this session (optional)      std::string name; -    /// Core timing event used to schedule the service request at some point in the future -    std::shared_ptr<Core::Timing::EventType> request_event; - -    /// Queue of scheduled service requests -    Common::MPSCQueue<std::shared_ptr<Kernel::HLERequestContext>> request_queue; +    /// Thread to dispatch service requests +    std::unique_ptr<ServiceThread> service_thread;  };  } // namespace Kernel diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp new file mode 100644 index 000000000..59a6045df --- /dev/null +++ b/src/core/hle/kernel/service_thread.cpp @@ -0,0 +1,100 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <condition_variable> +#include <functional> +#include <mutex> +#include <thread> +#include <vector> +#include <queue> + +#include "common/assert.h" +#include "common/scope_exit.h" +#include "core/core.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/server_session.h" +#include "core/hle/kernel/service_thread.h" +#include "core/hle/lock.h" +#include "video_core/renderer_base.h" + +namespace Kernel { + +class ServiceThread::Impl final { +public: +    explicit Impl(KernelCore& kernel); +    ~Impl(); + +    void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context); + +private: +    std::vector<std::thread> threads; +    std::queue<std::function<void()>> requests; +    std::mutex queue_mutex; +    std::condition_variable condition; +    bool stop{}; +}; + +ServiceThread::Impl::Impl(KernelCore& kernel) { +    constexpr std::size_t SizeOfPool{1}; +    for (std::size_t i = 0; i < SizeOfPool; ++i) +        threads.emplace_back([&] { +            // Wait for first request before trying to acquire a render context +            { +                std::unique_lock lock{queue_mutex}; +                condition.wait(lock, [this] { return stop || !requests.empty(); }); +            } + +            kernel.RegisterHostThread(); + +            while (true) { +                std::function<void()> task; + +                { +                    std::unique_lock lock{queue_mutex}; +                    condition.wait(lock, [this] { return stop || !requests.empty(); }); +                    if (stop && requests.empty()) { +                        return; +                    } +                    task = std::move(requests.front()); +                    requests.pop(); +                } + +                task(); +            } +        }); +} + +void ServiceThread::Impl::QueueSyncRequest(ServerSession& session, +                                           std::shared_ptr<HLERequestContext>&& context) { +    { +        std::unique_lock lock{queue_mutex}; +        requests.emplace([session{SharedFrom(&session)}, context{std::move(context)}]() { +            session->CompleteSyncRequest(*context); +            return; +        }); +    } +    condition.notify_one(); +} + +ServiceThread::Impl::~Impl() { +    { +        std::unique_lock lock{queue_mutex}; +        stop = true; +    } +    condition.notify_all(); +    for (std::thread& thread : threads) { +        thread.join(); +    } +} + +ServiceThread::ServiceThread(KernelCore& kernel) : impl{std::make_unique<Impl>(kernel)} {} + +ServiceThread::~ServiceThread() = default; + +void ServiceThread::QueueSyncRequest(ServerSession& session, +                                     std::shared_ptr<HLERequestContext>&& context) { +    impl->QueueSyncRequest(session, std::move(context)); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/service_thread.h b/src/core/hle/kernel/service_thread.h new file mode 100644 index 000000000..d252490bb --- /dev/null +++ b/src/core/hle/kernel/service_thread.h @@ -0,0 +1,27 @@ +// Copyright 2020 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> + +namespace Kernel { + +class HLERequestContext; +class KernelCore; +class ServerSession; + +class ServiceThread final { +public: +    explicit ServiceThread(KernelCore& kernel); +    ~ServiceThread(); + +    void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context); + +private: +    class Impl; +    std::unique_ptr<Impl> impl; +}; + +} // namespace Kernel | 
