diff options
author | bunnei <bunneidev@gmail.com> | 2020-12-10 06:27:05 +0100 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2020-12-29 01:33:47 +0100 |
commit | 28281ae2500a4af9c36c26de5ba07b80d440b335 (patch) | |
tree | 8113b0af071dbe7004f5f072862d47f557a9eb27 /src/core/hle/kernel/service_thread.cpp | |
parent | Merge pull request #5233 from german77/inverted (diff) | |
download | yuzu-28281ae2500a4af9c36c26de5ba07b80d440b335.tar yuzu-28281ae2500a4af9c36c26de5ba07b80d440b335.tar.gz yuzu-28281ae2500a4af9c36c26de5ba07b80d440b335.tar.bz2 yuzu-28281ae2500a4af9c36c26de5ba07b80d440b335.tar.lz yuzu-28281ae2500a4af9c36c26de5ba07b80d440b335.tar.xz yuzu-28281ae2500a4af9c36c26de5ba07b80d440b335.tar.zst yuzu-28281ae2500a4af9c36c26de5ba07b80d440b335.zip |
Diffstat (limited to 'src/core/hle/kernel/service_thread.cpp')
-rw-r--r-- | src/core/hle/kernel/service_thread.cpp | 100 |
1 files changed, 100 insertions, 0 deletions
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 |