hle: kernel: Manage host thread IDs using TLS.
- Avoids the need to have a large map of host to guest thread IDs.
This commit is contained in:
parent
dfdac7d38a
commit
c192da3f82
1 changed files with 31 additions and 46 deletions
|
@ -104,10 +104,8 @@ struct KernelCore::Impl {
|
||||||
|
|
||||||
exclusive_monitor.reset();
|
exclusive_monitor.reset();
|
||||||
|
|
||||||
num_host_threads = 0;
|
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
|
||||||
std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(),
|
next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
|
||||||
std::thread::id{});
|
|
||||||
std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0);
|
|
||||||
|
|
||||||
// Ensures all service threads gracefully shutdown
|
// Ensures all service threads gracefully shutdown
|
||||||
service_threads.clear();
|
service_threads.clear();
|
||||||
|
@ -190,52 +188,46 @@ struct KernelCore::Impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new host thread ID, should only be called by GetHostThreadId
|
||||||
|
u32 AllocateHostThreadId(std::optional<std::size_t> core_id) {
|
||||||
|
if (core_id) {
|
||||||
|
// The first for slots are reserved for CPU core threads
|
||||||
|
ASSERT(*core_id < Core::Hardware::NUM_CPU_CORES);
|
||||||
|
return static_cast<u32>(*core_id);
|
||||||
|
} else {
|
||||||
|
return next_host_thread_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
|
||||||
|
u32 GetHostThreadId(std::optional<std::size_t> core_id = std::nullopt) {
|
||||||
|
const thread_local auto host_thread_id{AllocateHostThreadId(core_id)};
|
||||||
|
return host_thread_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a CPU core thread by allocating a host thread ID for it
|
||||||
void RegisterCoreThread(std::size_t core_id) {
|
void RegisterCoreThread(std::size_t core_id) {
|
||||||
const std::thread::id this_id = std::this_thread::get_id();
|
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
||||||
|
const auto this_id = GetHostThreadId(core_id);
|
||||||
if (!is_multicore) {
|
if (!is_multicore) {
|
||||||
single_core_thread_id = this_id;
|
single_core_thread_id = this_id;
|
||||||
}
|
}
|
||||||
const auto end =
|
|
||||||
register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
|
|
||||||
const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
|
|
||||||
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
|
|
||||||
ASSERT(it == end);
|
|
||||||
InsertHostThread(static_cast<u32>(core_id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Registers a new host thread by allocating a host thread ID for it
|
||||||
void RegisterHostThread() {
|
void RegisterHostThread() {
|
||||||
const std::thread::id this_id = std::this_thread::get_id();
|
[[maybe_unused]] const auto this_id = GetHostThreadId();
|
||||||
const auto end =
|
|
||||||
register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
|
|
||||||
const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
|
|
||||||
if (it == end) {
|
|
||||||
InsertHostThread(registered_thread_ids++);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InsertHostThread(u32 value) {
|
[[nodiscard]] u32 GetCurrentHostThreadID() {
|
||||||
const size_t index = num_host_threads++;
|
const auto this_id = GetHostThreadId();
|
||||||
ASSERT_MSG(index < NUM_REGISTRABLE_HOST_THREADS, "Too many host threads");
|
|
||||||
register_host_thread_values[index] = value;
|
|
||||||
register_host_thread_keys[index] = std::this_thread::get_id();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] u32 GetCurrentHostThreadID() const {
|
|
||||||
const std::thread::id this_id = std::this_thread::get_id();
|
|
||||||
if (!is_multicore && single_core_thread_id == this_id) {
|
if (!is_multicore && single_core_thread_id == this_id) {
|
||||||
return static_cast<u32>(system.GetCpuManager().CurrentCore());
|
return static_cast<u32>(system.GetCpuManager().CurrentCore());
|
||||||
}
|
}
|
||||||
const auto end =
|
return this_id;
|
||||||
register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
|
|
||||||
const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
|
|
||||||
if (it == end) {
|
|
||||||
return Core::INVALID_HOST_THREAD_ID;
|
|
||||||
}
|
|
||||||
return register_host_thread_values[static_cast<size_t>(
|
|
||||||
std::distance(register_host_thread_keys.begin(), it))];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::EmuThreadHandle GetCurrentEmuThreadID() const {
|
[[nodiscard]] Core::EmuThreadHandle GetCurrentEmuThreadID() {
|
||||||
Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
|
Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
|
||||||
result.host_handle = GetCurrentHostThreadID();
|
result.host_handle = GetCurrentHostThreadID();
|
||||||
if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
|
if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
|
||||||
|
@ -329,15 +321,8 @@ struct KernelCore::Impl {
|
||||||
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
|
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
|
||||||
std::vector<Kernel::PhysicalCore> cores;
|
std::vector<Kernel::PhysicalCore> cores;
|
||||||
|
|
||||||
// 0-3 IDs represent core threads, >3 represent others
|
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
|
||||||
std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
|
std::atomic<u32> next_host_thread_id{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 = 1024;
|
|
||||||
std::atomic<size_t> num_host_threads{0};
|
|
||||||
std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS>
|
|
||||||
register_host_thread_keys{};
|
|
||||||
std::array<std::atomic<u32>, NUM_REGISTRABLE_HOST_THREADS> register_host_thread_values{};
|
|
||||||
|
|
||||||
// Kernel memory management
|
// Kernel memory management
|
||||||
std::unique_ptr<Memory::MemoryManager> memory_manager;
|
std::unique_ptr<Memory::MemoryManager> memory_manager;
|
||||||
|
@ -357,7 +342,7 @@ struct KernelCore::Impl {
|
||||||
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
|
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
|
||||||
|
|
||||||
bool is_multicore{};
|
bool is_multicore{};
|
||||||
std::thread::id single_core_thread_id{};
|
u32 single_core_thread_id{};
|
||||||
|
|
||||||
std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
|
std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue