diff options
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 77 |
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 | ||