summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2020-12-29 15:55:30 -0800
committerGravatar bunnei2020-12-29 15:55:30 -0800
commitc192da3f82ea3b2563ce43a340c88ac9a6602f26 (patch)
tree0161769d0ea55afcb7e01f0841e9348f644ad281 /src/core/hle/kernel/kernel.cpp
parenthle: kernel: Move ServiceThread ownership to KernelCore. (diff)
downloadyuzu-c192da3f82ea3b2563ce43a340c88ac9a6602f26.tar.gz
yuzu-c192da3f82ea3b2563ce43a340c88ac9a6602f26.tar.xz
yuzu-c192da3f82ea3b2563ce43a340c88ac9a6602f26.zip
hle: kernel: Manage host thread IDs using TLS.
- Avoids the need to have a large map of host to guest thread IDs.
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp77
1 files changed, 31 insertions, 46 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 5f917686f..022cd413d 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -104,10 +104,8 @@ struct KernelCore::Impl {
104 104
105 exclusive_monitor.reset(); 105 exclusive_monitor.reset();
106 106
107 num_host_threads = 0; 107 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
108 std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(), 108 next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
109 std::thread::id{});
110 std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0);
111 109
112 // Ensures all service threads gracefully shutdown 110 // Ensures all service threads gracefully shutdown
113 service_threads.clear(); 111 service_threads.clear();
@@ -190,52 +188,46 @@ struct KernelCore::Impl {
190 } 188 }
191 } 189 }
192 190
191 /// Creates a new host thread ID, should only be called by GetHostThreadId
192 u32 AllocateHostThreadId(std::optional<std::size_t> core_id) {
193 if (core_id) {
194 // The first for slots are reserved for CPU core threads
195 ASSERT(*core_id < Core::Hardware::NUM_CPU_CORES);
196 return static_cast<u32>(*core_id);
197 } else {
198 return next_host_thread_id++;
199 }
200 }
201
202 /// Gets the host thread ID for the caller, allocating a new one if this is the first time
203 u32 GetHostThreadId(std::optional<std::size_t> core_id = std::nullopt) {
204 const thread_local auto host_thread_id{AllocateHostThreadId(core_id)};
205 return host_thread_id;
206 }
207
208 /// Registers a CPU core thread by allocating a host thread ID for it
193 void RegisterCoreThread(std::size_t core_id) { 209 void RegisterCoreThread(std::size_t core_id) {
194 const std::thread::id this_id = std::this_thread::get_id(); 210 ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
211 const auto this_id = GetHostThreadId(core_id);
195 if (!is_multicore) { 212 if (!is_multicore) {
196 single_core_thread_id = this_id; 213 single_core_thread_id = this_id;
197 } 214 }
198 const auto end =
199 register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
200 const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
201 ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
202 ASSERT(it == end);
203 InsertHostThread(static_cast<u32>(core_id));
204 } 215 }
205 216
217 /// Registers a new host thread by allocating a host thread ID for it
206 void RegisterHostThread() { 218 void RegisterHostThread() {
207 const std::thread::id this_id = std::this_thread::get_id(); 219 [[maybe_unused]] const auto this_id = GetHostThreadId();
208 const auto end =
209 register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
210 const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
211 if (it == end) {
212 InsertHostThread(registered_thread_ids++);
213 }
214 }
215
216 void InsertHostThread(u32 value) {
217 const size_t index = num_host_threads++;
218 ASSERT_MSG(index < NUM_REGISTRABLE_HOST_THREADS, "Too many host threads");
219 register_host_thread_values[index] = value;
220 register_host_thread_keys[index] = std::this_thread::get_id();
221 } 220 }
222 221
223 [[nodiscard]] u32 GetCurrentHostThreadID() const { 222 [[nodiscard]] u32 GetCurrentHostThreadID() {
224 const std::thread::id this_id = std::this_thread::get_id(); 223 const auto this_id = GetHostThreadId();
225 if (!is_multicore && single_core_thread_id == this_id) { 224 if (!is_multicore && single_core_thread_id == this_id) {
226 return static_cast<u32>(system.GetCpuManager().CurrentCore()); 225 return static_cast<u32>(system.GetCpuManager().CurrentCore());
227 } 226 }
228 const auto end = 227 return this_id;
229 register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
230 const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
231 if (it == end) {
232 return Core::INVALID_HOST_THREAD_ID;
233 }
234 return register_host_thread_values[static_cast<size_t>(
235 std::distance(register_host_thread_keys.begin(), it))];
236 } 228 }
237 229
238 Core::EmuThreadHandle GetCurrentEmuThreadID() const { 230 [[nodiscard]] Core::EmuThreadHandle GetCurrentEmuThreadID() {
239 Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle(); 231 Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
240 result.host_handle = GetCurrentHostThreadID(); 232 result.host_handle = GetCurrentHostThreadID();
241 if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) { 233 if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
@@ -329,15 +321,8 @@ struct KernelCore::Impl {
329 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; 321 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
330 std::vector<Kernel::PhysicalCore> cores; 322 std::vector<Kernel::PhysicalCore> cores;
331 323
332 // 0-3 IDs represent core threads, >3 represent others 324 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
333 std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; 325 std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES};
334
335 // Number of host threads is a relatively high number to avoid overflowing
336 static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 1024;
337 std::atomic<size_t> num_host_threads{0};
338 std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS>
339 register_host_thread_keys{};
340 std::array<std::atomic<u32>, NUM_REGISTRABLE_HOST_THREADS> register_host_thread_values{};
341 326
342 // Kernel memory management 327 // Kernel memory management
343 std::unique_ptr<Memory::MemoryManager> memory_manager; 328 std::unique_ptr<Memory::MemoryManager> memory_manager;
@@ -357,7 +342,7 @@ struct KernelCore::Impl {
357 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 342 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
358 343
359 bool is_multicore{}; 344 bool is_multicore{};
360 std::thread::id single_core_thread_id{}; 345 u32 single_core_thread_id{};
361 346
362 std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{}; 347 std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
363 348