kernel/address_arbiter: Pass in system instance to constructor

Allows getting rid of reliance on the global accessor functions and
instead operating on the provided system instance.
This commit is contained in:
Lioncash 2019-03-05 12:28:10 -05:00
parent 9d9676f620
commit c161389a0f
6 changed files with 45 additions and 26 deletions

View file

@ -78,6 +78,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
return vfs->OpenFile(path, FileSys::Mode::Read); return vfs->OpenFile(path, FileSys::Mode::Read);
} }
struct System::Impl { struct System::Impl {
explicit Impl(System& system) : kernel{system} {}
Cpu& CurrentCpuCore() { Cpu& CurrentCpuCore() {
return cpu_core_manager.GetCurrentCore(); return cpu_core_manager.GetCurrentCore();
@ -95,7 +96,7 @@ struct System::Impl {
LOG_DEBUG(HW_Memory, "initialized OK"); LOG_DEBUG(HW_Memory, "initialized OK");
core_timing.Initialize(); core_timing.Initialize();
kernel.Initialize(core_timing); kernel.Initialize();
const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch()); std::chrono::system_clock::now().time_since_epoch());
@ -265,7 +266,7 @@ struct System::Impl {
Core::FrameLimiter frame_limiter; Core::FrameLimiter frame_limiter;
}; };
System::System() : impl{std::make_unique<Impl>()} {} System::System() : impl{std::make_unique<Impl>(*this)} {}
System::~System() = default; System::~System() = default;
Cpu& System::CurrentCpuCore() { Cpu& System::CurrentCpuCore() {

View file

@ -39,7 +39,7 @@ void WakeThreads(const std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_
} }
} // Anonymous namespace } // Anonymous namespace
AddressArbiter::AddressArbiter() = default; AddressArbiter::AddressArbiter(Core::System& system) : system{system} {}
AddressArbiter::~AddressArbiter() = default; AddressArbiter::~AddressArbiter() = default;
ResultCode AddressArbiter::SignalToAddress(VAddr address, s32 num_to_wake) { ResultCode AddressArbiter::SignalToAddress(VAddr address, s32 num_to_wake) {
@ -134,22 +134,22 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
} }
ResultCode AddressArbiter::WaitForAddress(VAddr address, s64 timeout) { ResultCode AddressArbiter::WaitForAddress(VAddr address, s64 timeout) {
SharedPtr<Thread> current_thread = GetCurrentThread(); SharedPtr<Thread> current_thread = system.CurrentScheduler().GetCurrentThread();
current_thread->SetArbiterWaitAddress(address); current_thread->SetArbiterWaitAddress(address);
current_thread->SetStatus(ThreadStatus::WaitArb); current_thread->SetStatus(ThreadStatus::WaitArb);
current_thread->InvalidateWakeupCallback(); current_thread->InvalidateWakeupCallback();
current_thread->WakeAfterDelay(timeout); current_thread->WakeAfterDelay(timeout);
Core::System::GetInstance().CpuCore(current_thread->GetProcessorID()).PrepareReschedule(); system.CpuCore(current_thread->GetProcessorID()).PrepareReschedule();
return RESULT_TIMEOUT; return RESULT_TIMEOUT;
} }
std::vector<SharedPtr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) const { std::vector<SharedPtr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) const {
const auto RetrieveWaitingThreads = [](std::size_t core_index, const auto RetrieveWaitingThreads = [this](std::size_t core_index,
std::vector<SharedPtr<Thread>>& waiting_threads, std::vector<SharedPtr<Thread>>& waiting_threads,
VAddr arb_addr) { VAddr arb_addr) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index); const auto& scheduler = system.Scheduler(core_index);
const auto& thread_list = scheduler.GetThreadList(); const auto& thread_list = scheduler.GetThreadList();
for (const auto& thread : thread_list) { for (const auto& thread : thread_list) {

View file

@ -9,6 +9,10 @@
union ResultCode; union ResultCode;
namespace Core {
class System;
}
namespace Kernel { namespace Kernel {
class Thread; class Thread;
@ -27,7 +31,7 @@ public:
ModifyByWaitingCountAndSignalIfEqual = 2, ModifyByWaitingCountAndSignalIfEqual = 2,
}; };
AddressArbiter(); explicit AddressArbiter(Core::System& system);
~AddressArbiter(); ~AddressArbiter();
AddressArbiter(const AddressArbiter&) = delete; AddressArbiter(const AddressArbiter&) = delete;
@ -61,6 +65,8 @@ private:
// Gets the threads waiting on an address. // Gets the threads waiting on an address.
std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const; std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const;
Core::System& system;
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -87,11 +87,13 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] int cycles_
} }
struct KernelCore::Impl { struct KernelCore::Impl {
void Initialize(KernelCore& kernel, Core::Timing::CoreTiming& core_timing) { explicit Impl(Core::System& system) : address_arbiter{system}, system{system} {}
void Initialize(KernelCore& kernel) {
Shutdown(); Shutdown();
InitializeSystemResourceLimit(kernel); InitializeSystemResourceLimit(kernel);
InitializeThreads(core_timing); InitializeThreads();
} }
void Shutdown() { void Shutdown() {
@ -123,9 +125,9 @@ struct KernelCore::Impl {
ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
} }
void InitializeThreads(Core::Timing::CoreTiming& core_timing) { void InitializeThreads() {
thread_wakeup_event_type = thread_wakeup_event_type =
core_timing.RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
} }
std::atomic<u32> next_object_id{0}; std::atomic<u32> next_object_id{0};
@ -148,15 +150,18 @@ struct KernelCore::Impl {
/// 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.
NamedPortTable named_ports; NamedPortTable named_ports;
// System context
Core::System& system;
}; };
KernelCore::KernelCore() : impl{std::make_unique<Impl>()} {} KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system)} {}
KernelCore::~KernelCore() { KernelCore::~KernelCore() {
Shutdown(); Shutdown();
} }
void KernelCore::Initialize(Core::Timing::CoreTiming& core_timing) { void KernelCore::Initialize() {
impl->Initialize(*this, core_timing); impl->Initialize(*this);
} }
void KernelCore::Shutdown() { void KernelCore::Shutdown() {

View file

@ -11,6 +11,10 @@
template <typename T> template <typename T>
class ResultVal; class ResultVal;
namespace Core {
class System;
}
namespace Core::Timing { namespace Core::Timing {
class CoreTiming; class CoreTiming;
struct EventType; struct EventType;
@ -31,7 +35,14 @@ private:
using NamedPortTable = std::unordered_map<std::string, SharedPtr<ClientPort>>; using NamedPortTable = std::unordered_map<std::string, SharedPtr<ClientPort>>;
public: public:
KernelCore(); /// Constructs an instance of the kernel using the given System
/// instance as a context for any necessary system-related state,
/// such as threads, CPU core state, etc.
///
/// @post After execution of the constructor, the provided System
/// object *must* outlive the kernel instance itself.
///
explicit KernelCore(Core::System& system);
~KernelCore(); ~KernelCore();
KernelCore(const KernelCore&) = delete; KernelCore(const KernelCore&) = delete;
@ -41,11 +52,7 @@ public:
KernelCore& operator=(KernelCore&&) = delete; KernelCore& operator=(KernelCore&&) = delete;
/// Resets the kernel to a clean slate for use. /// Resets the kernel to a clean slate for use.
/// void Initialize();
/// @param core_timing CoreTiming instance used to create any necessary
/// kernel-specific callback events.
///
void Initialize(Core::Timing::CoreTiming& core_timing);
/// Clears all resources in use by the kernel instance. /// Clears all resources in use by the kernel instance.
void Shutdown(); void Shutdown();

View file

@ -13,11 +13,11 @@
namespace ArmTests { namespace ArmTests {
TestEnvironment::TestEnvironment(bool mutable_memory_) TestEnvironment::TestEnvironment(bool mutable_memory_)
: mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { : mutable_memory(mutable_memory_),
test_memory(std::make_shared<TestMemory>(this)), kernel{Core::System::GetInstance()} {
auto process = Kernel::Process::Create(kernel, ""); auto process = Kernel::Process::Create(kernel, "");
kernel.MakeCurrentProcess(process.get()); kernel.MakeCurrentProcess(process.get());
page_table = &Core::CurrentProcess()->VMManager().page_table; page_table = &process->VMManager().page_table;
std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr); std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr);
page_table->special_regions.clear(); page_table->special_regions.clear();