yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

Kernel: Rename ThreadCallbackHandleTable and Setup Thread Ids on Kernel.

This commit is contained in:
Fernando Sahmkow 2020-02-14 09:30:53 -04:00 committed by FernandoS27
parent 0728dfef84
commit 179bafa7cb
5 changed files with 107 additions and 24 deletions

View File

@ -20,6 +20,8 @@ constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores
} // namespace Hardware } // namespace Hardware
constexpr u32 INVALID_HOST_THREAD_ID = 0xFFFFFFFF;
struct EmuThreadHandle { struct EmuThreadHandle {
u32 host_handle; u32 host_handle;
u32 guest_handle; u32 guest_handle;

View File

@ -6,6 +6,8 @@
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <thread>
#include <unordered_map>
#include <utility> #include <utility>
#include "common/assert.h" #include "common/assert.h"
@ -44,7 +46,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
std::lock_guard lock{HLE::g_hle_lock}; std::lock_guard lock{HLE::g_hle_lock};
std::shared_ptr<Thread> thread = std::shared_ptr<Thread> thread =
system.Kernel().RetrieveThreadFromWakeupCallbackHandleTable(proper_handle); system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
if (thread == nullptr) { if (thread == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
return; return;
@ -120,7 +122,7 @@ struct KernelCore::Impl {
system_resource_limit = nullptr; system_resource_limit = nullptr;
thread_wakeup_callback_handle_table.Clear(); global_handle_table.Clear();
thread_wakeup_event_type = nullptr; thread_wakeup_event_type = nullptr;
preemption_event = nullptr; preemption_event = nullptr;
@ -138,8 +140,8 @@ struct KernelCore::Impl {
void InitializePhysicalCores() { void InitializePhysicalCores() {
exclusive_monitor = exclusive_monitor =
Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES);
for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
cores.emplace_back(system, i, *exclusive_monitor); cores.emplace_back(system, i, *exclusive_monitor);
} }
} }
@ -184,6 +186,48 @@ struct KernelCore::Impl {
system.Memory().SetCurrentPageTable(*process); system.Memory().SetCurrentPageTable(*process);
} }
void RegisterCoreThread(std::size_t core_id) {
const std::thread::id this_id = std::this_thread::get_id();
const auto it = host_thread_ids.find(this_id);
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
ASSERT(it == host_thread_ids.end());
ASSERT(!registered_core_threads[core_id]);
host_thread_ids[this_id] = static_cast<u32>(core_id);
registered_core_threads.set(core_id);
}
void RegisterHostThread() {
const std::thread::id this_id = std::this_thread::get_id();
const auto it = host_thread_ids.find(this_id);
ASSERT(it == host_thread_ids.end());
host_thread_ids[this_id] = registered_thread_ids++;
}
u32 GetCurrentHostThreadId() const {
const std::thread::id this_id = std::this_thread::get_id();
const auto it = host_thread_ids.find(this_id);
if (it == host_thread_ids.end()) {
return Core::INVALID_HOST_THREAD_ID;
}
return it->second;
}
Core::EmuThreadHandle GetCurrentEmuThreadId() const {
Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
result.host_handle = GetCurrentHostThreadId();
if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
return result;
}
const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler();
const Kernel::Thread* current = sched.GetCurrentThread();
if (current != nullptr) {
result.guest_handle = current->GetGlobalHandle();
} else {
result.guest_handle = InvalidHandle;
}
return result;
}
std::atomic<u32> next_object_id{0}; std::atomic<u32> next_object_id{0};
std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin};
std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; std::atomic<u64> next_user_process_id{Process::ProcessIDMin};
@ -202,7 +246,7 @@ struct KernelCore::Impl {
// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future,
// allowing us to simply use a pool index or similar. // allowing us to simply use a pool index or similar.
Kernel::HandleTable thread_wakeup_callback_handle_table; Kernel::HandleTable global_handle_table;
/// Map of named ports managed by the kernel, which can be retrieved using /// Map of named ports managed by the kernel, which can be retrieved using
/// the ConnectToPort SVC. /// the ConnectToPort SVC.
@ -211,6 +255,11 @@ 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
std::unordered_map<std::thread::id, u32> host_thread_ids;
u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads{};
// System context // System context
Core::System& system; Core::System& system;
}; };
@ -232,9 +281,8 @@ std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
return impl->system_resource_limit; return impl->system_resource_limit;
} }
std::shared_ptr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable( std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
Handle handle) const { return impl->global_handle_table.Get<Thread>(handle);
return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle);
} }
void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) { void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) {
@ -346,12 +394,28 @@ const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallback
return impl->thread_wakeup_event_type; return impl->thread_wakeup_event_type;
} }
Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() { Kernel::HandleTable& KernelCore::GlobalHandleTable() {
return impl->thread_wakeup_callback_handle_table; return impl->global_handle_table;
} }
const Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() const { const Kernel::HandleTable& KernelCore::GlobalHandleTable() const {
return impl->thread_wakeup_callback_handle_table; return impl->global_handle_table;
}
void KernelCore::RegisterCoreThread(std::size_t core_id) {
impl->RegisterCoreThread(core_id);
}
void KernelCore::RegisterHostThread() {
impl->RegisterHostThread();
}
u32 KernelCore::GetCurrentHostThreadId() const {
return impl->GetCurrentHostThreadId();
}
Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadId() const {
return impl->GetCurrentEmuThreadId();
} }
} // namespace Kernel } // namespace Kernel

View File

@ -8,6 +8,7 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "core/hardware_properties.h"
#include "core/hle/kernel/object.h" #include "core/hle/kernel/object.h"
namespace Core { namespace Core {
@ -65,7 +66,7 @@ public:
std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const; std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const;
/// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
std::shared_ptr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const; std::shared_ptr<Thread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
/// Adds the given shared pointer to an internal list of active processes. /// Adds the given shared pointer to an internal list of active processes.
void AppendNewProcess(std::shared_ptr<Process> process); void AppendNewProcess(std::shared_ptr<Process> process);
@ -127,6 +128,18 @@ public:
/// Determines whether or not the given port is a valid named port. /// Determines whether or not the given port is a valid named port.
bool IsValidNamedPort(NamedPortTable::const_iterator port) const; bool IsValidNamedPort(NamedPortTable::const_iterator port) const;
/// Gets the current host_thread/guest_thread handle.
Core::EmuThreadHandle GetCurrentEmuThreadId() const;
/// Gets the current host_thread handle.
u32 GetCurrentHostThreadId() const;
/// Register the current thread as a CPU Core Thread.
void RegisterCoreThread(std::size_t core_id);
/// Register the current thread as a non CPU core thread.
void RegisterHostThread();
private: private:
friend class Object; friend class Object;
friend class Process; friend class Process;
@ -147,11 +160,11 @@ private:
/// Retrieves the event type used for thread wakeup callbacks. /// Retrieves the event type used for thread wakeup callbacks.
const std::shared_ptr<Core::Timing::EventType>& ThreadWakeupCallbackEventType() const; const std::shared_ptr<Core::Timing::EventType>& ThreadWakeupCallbackEventType() const;
/// Provides a reference to the thread wakeup callback handle table. /// Provides a reference to the global handle table.
Kernel::HandleTable& ThreadWakeupCallbackHandleTable(); Kernel::HandleTable& GlobalHandleTable();
/// Provides a const reference to the thread wakeup callback handle table. /// Provides a const reference to the global handle table.
const Kernel::HandleTable& ThreadWakeupCallbackHandleTable() const; const Kernel::HandleTable& GlobalHandleTable() const;
struct Impl; struct Impl;
std::unique_ptr<Impl> impl; std::unique_ptr<Impl> impl;

View File

@ -46,9 +46,9 @@ Thread::~Thread() = default;
void Thread::Stop() { void Thread::Stop() {
// Cancel any outstanding wakeup events for this thread // Cancel any outstanding wakeup events for this thread
Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(),
callback_handle); global_handle);
kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle); kernel.GlobalHandleTable().Close(global_handle);
callback_handle = 0; global_handle = 0;
SetStatus(ThreadStatus::Dead); SetStatus(ThreadStatus::Dead);
Signal(); Signal();
@ -73,12 +73,12 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
// thread-safe version of ScheduleEvent. // thread-safe version of ScheduleEvent.
const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds}); const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds});
Core::System::GetInstance().CoreTiming().ScheduleEvent( Core::System::GetInstance().CoreTiming().ScheduleEvent(
cycles, kernel.ThreadWakeupCallbackEventType(), callback_handle); cycles, kernel.ThreadWakeupCallbackEventType(), global_handle);
} }
void Thread::CancelWakeupTimer() { void Thread::CancelWakeupTimer() {
Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(),
callback_handle); global_handle);
} }
void Thread::ResumeFromWait() { void Thread::ResumeFromWait() {
@ -190,7 +190,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin
thread->condvar_wait_address = 0; thread->condvar_wait_address = 0;
thread->wait_handle = 0; thread->wait_handle = 0;
thread->name = std::move(name); thread->name = std::move(name);
thread->callback_handle = kernel.ThreadWakeupCallbackHandleTable().Create(thread).Unwrap(); thread->global_handle = kernel.GlobalHandleTable().Create(thread).Unwrap();
thread->owner_process = &owner_process; thread->owner_process = &owner_process;
auto& scheduler = kernel.GlobalScheduler(); auto& scheduler = kernel.GlobalScheduler();
scheduler.AddThread(thread); scheduler.AddThread(thread);

View File

@ -453,6 +453,10 @@ public:
is_sync_cancelled = value; is_sync_cancelled = value;
} }
Handle GetGlobalHandle() const {
return global_handle;
}
private: private:
void SetSchedulingStatus(ThreadSchedStatus new_status); void SetSchedulingStatus(ThreadSchedStatus new_status);
void SetCurrentPriority(u32 new_priority); void SetCurrentPriority(u32 new_priority);
@ -514,7 +518,7 @@ private:
VAddr arb_wait_address{0}; VAddr arb_wait_address{0};
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue. /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle callback_handle = 0; Handle global_handle = 0;
/// Callback that will be invoked when the thread is resumed from a waiting state. If the thread /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
/// was waiting via WaitSynchronization then the object will be the last object that became /// was waiting via WaitSynchronization then the object will be the last object that became