summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/server_session.cpp20
-rw-r--r--src/core/hle/kernel/server_session.h12
-rw-r--r--src/core/hle/kernel/service_thread.cpp100
-rw-r--r--src/core/hle/kernel/service_thread.h27
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
202 hle/kernel/server_port.h 202 hle/kernel/server_port.h
203 hle/kernel/server_session.cpp 203 hle/kernel/server_session.cpp
204 hle/kernel/server_session.h 204 hle/kernel/server_session.h
205 hle/kernel/service_thread.cpp
206 hle/kernel/service_thread.h
205 hle/kernel/session.cpp 207 hle/kernel/session.cpp
206 hle/kernel/session.h 208 hle/kernel/session.h
207 hle/kernel/shared_memory.cpp 209 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 {
329 std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; 329 std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
330 330
331 // Number of host threads is a relatively high number to avoid overflowing 331 // Number of host threads is a relatively high number to avoid overflowing
332 static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64; 332 static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 1024;
333 std::atomic<size_t> num_host_threads{0}; 333 std::atomic<size_t> num_host_threads{0};
334 std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS> 334 std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS>
335 register_host_thread_keys{}; 335 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
32 std::string name) { 32 std::string name) {
33 std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; 33 std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)};
34 34
35 session->request_event =
36 Core::Timing::CreateEvent(name, [session](std::uintptr_t, std::chrono::nanoseconds) {
37 session->CompleteSyncRequest();
38 });
39 session->name = std::move(name); 35 session->name = std::move(name);
40 session->parent = std::move(parent); 36 session->parent = std::move(parent);
37 session->service_thread = std::make_unique<ServiceThread>(kernel);
41 38
42 return MakeResult(std::move(session)); 39 return MakeResult(std::move(session));
43} 40}
@@ -142,16 +139,12 @@ ResultCode ServerSession::QueueSyncRequest(std::shared_ptr<Thread> thread,
142 std::make_shared<HLERequestContext>(kernel, memory, SharedFrom(this), std::move(thread)); 139 std::make_shared<HLERequestContext>(kernel, memory, SharedFrom(this), std::move(thread));
143 140
144 context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); 141 context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
145 request_queue.Push(std::move(context)); 142 service_thread->QueueSyncRequest(*this, std::move(context));
146 143
147 return RESULT_SUCCESS; 144 return RESULT_SUCCESS;
148} 145}
149 146
150ResultCode ServerSession::CompleteSyncRequest() { 147ResultCode ServerSession::CompleteSyncRequest(HLERequestContext& context) {
151 ASSERT(!request_queue.Empty());
152
153 auto& context = *request_queue.Front();
154
155 ResultCode result = RESULT_SUCCESS; 148 ResultCode result = RESULT_SUCCESS;
156 // If the session has been converted to a domain, handle the domain request 149 // If the session has been converted to a domain, handle the domain request
157 if (IsDomain() && context.HasDomainMessageHeader()) { 150 if (IsDomain() && context.HasDomainMessageHeader()) {
@@ -177,18 +170,13 @@ ResultCode ServerSession::CompleteSyncRequest() {
177 } 170 }
178 } 171 }
179 172
180 request_queue.Pop();
181
182 return result; 173 return result;
183} 174}
184 175
185ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread, 176ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
186 Core::Memory::Memory& memory, 177 Core::Memory::Memory& memory,
187 Core::Timing::CoreTiming& core_timing) { 178 Core::Timing::CoreTiming& core_timing) {
188 const ResultCode result = QueueSyncRequest(std::move(thread), memory); 179 return QueueSyncRequest(std::move(thread), memory);
189 const auto delay = std::chrono::nanoseconds{kernel.IsMulticore() ? 0 : 20000};
190 core_timing.ScheduleEvent(delay, request_event, {});
191 return result;
192} 180}
193 181
194} // namespace Kernel 182} // 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 @@
10#include <vector> 10#include <vector>
11 11
12#include "common/threadsafe_queue.h" 12#include "common/threadsafe_queue.h"
13#include "core/hle/kernel/service_thread.h"
13#include "core/hle/kernel/synchronization_object.h" 14#include "core/hle/kernel/synchronization_object.h"
14#include "core/hle/result.h" 15#include "core/hle/result.h"
15 16
@@ -43,6 +44,8 @@ class Thread;
43 * TLS buffer and control is transferred back to it. 44 * TLS buffer and control is transferred back to it.
44 */ 45 */
45class ServerSession final : public SynchronizationObject { 46class ServerSession final : public SynchronizationObject {
47 friend class ServiceThread;
48
46public: 49public:
47 explicit ServerSession(KernelCore& kernel); 50 explicit ServerSession(KernelCore& kernel);
48 ~ServerSession() override; 51 ~ServerSession() override;
@@ -132,7 +135,7 @@ private:
132 ResultCode QueueSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory); 135 ResultCode QueueSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory);
133 136
134 /// Completes a sync request from the emulated application. 137 /// Completes a sync request from the emulated application.
135 ResultCode CompleteSyncRequest(); 138 ResultCode CompleteSyncRequest(HLERequestContext& context);
136 139
137 /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an 140 /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an
138 /// object handle. 141 /// object handle.
@@ -163,11 +166,8 @@ private:
163 /// The name of this session (optional) 166 /// The name of this session (optional)
164 std::string name; 167 std::string name;
165 168
166 /// Core timing event used to schedule the service request at some point in the future 169 /// Thread to dispatch service requests
167 std::shared_ptr<Core::Timing::EventType> request_event; 170 std::unique_ptr<ServiceThread> service_thread;
168
169 /// Queue of scheduled service requests
170 Common::MPSCQueue<std::shared_ptr<Kernel::HLERequestContext>> request_queue;
171}; 171};
172 172
173} // namespace Kernel 173} // 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 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <condition_variable>
6#include <functional>
7#include <mutex>
8#include <thread>
9#include <vector>
10#include <queue>
11
12#include "common/assert.h"
13#include "common/scope_exit.h"
14#include "core/core.h"
15#include "core/hle/kernel/kernel.h"
16#include "core/hle/kernel/server_session.h"
17#include "core/hle/kernel/service_thread.h"
18#include "core/hle/lock.h"
19#include "video_core/renderer_base.h"
20
21namespace Kernel {
22
23class ServiceThread::Impl final {
24public:
25 explicit Impl(KernelCore& kernel);
26 ~Impl();
27
28 void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context);
29
30private:
31 std::vector<std::thread> threads;
32 std::queue<std::function<void()>> requests;
33 std::mutex queue_mutex;
34 std::condition_variable condition;
35 bool stop{};
36};
37
38ServiceThread::Impl::Impl(KernelCore& kernel) {
39 constexpr std::size_t SizeOfPool{1};
40 for (std::size_t i = 0; i < SizeOfPool; ++i)
41 threads.emplace_back([&] {
42 // Wait for first request before trying to acquire a render context
43 {
44 std::unique_lock lock{queue_mutex};
45 condition.wait(lock, [this] { return stop || !requests.empty(); });
46 }
47
48 kernel.RegisterHostThread();
49
50 while (true) {
51 std::function<void()> task;
52
53 {
54 std::unique_lock lock{queue_mutex};
55 condition.wait(lock, [this] { return stop || !requests.empty(); });
56 if (stop && requests.empty()) {
57 return;
58 }
59 task = std::move(requests.front());
60 requests.pop();
61 }
62
63 task();
64 }
65 });
66}
67
68void ServiceThread::Impl::QueueSyncRequest(ServerSession& session,
69 std::shared_ptr<HLERequestContext>&& context) {
70 {
71 std::unique_lock lock{queue_mutex};
72 requests.emplace([session{SharedFrom(&session)}, context{std::move(context)}]() {
73 session->CompleteSyncRequest(*context);
74 return;
75 });
76 }
77 condition.notify_one();
78}
79
80ServiceThread::Impl::~Impl() {
81 {
82 std::unique_lock lock{queue_mutex};
83 stop = true;
84 }
85 condition.notify_all();
86 for (std::thread& thread : threads) {
87 thread.join();
88 }
89}
90
91ServiceThread::ServiceThread(KernelCore& kernel) : impl{std::make_unique<Impl>(kernel)} {}
92
93ServiceThread::~ServiceThread() = default;
94
95void ServiceThread::QueueSyncRequest(ServerSession& session,
96 std::shared_ptr<HLERequestContext>&& context) {
97 impl->QueueSyncRequest(session, std::move(context));
98}
99
100} // 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 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8
9namespace Kernel {
10
11class HLERequestContext;
12class KernelCore;
13class ServerSession;
14
15class ServiceThread final {
16public:
17 explicit ServiceThread(KernelCore& kernel);
18 ~ServiceThread();
19
20 void QueueSyncRequest(ServerSession& session, std::shared_ptr<HLERequestContext>&& context);
21
22private:
23 class Impl;
24 std::unique_ptr<Impl> impl;
25};
26
27} // namespace Kernel