core_timing: Convert core timing into a class
Gets rid of the largest set of mutable global state within the core. This also paves a way for eliminating usages of GetInstance() on the System class as a follow-up. Note that no behavioral changes have been made, and this simply extracts the functionality into a class. This also has the benefit of making dependencies on the core timing functionality explicit within the relevant interfaces.
This commit is contained in:
		@@ -86,11 +86,11 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] int cycles_
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct KernelCore::Impl {
 | 
			
		||||
    void Initialize(KernelCore& kernel) {
 | 
			
		||||
    void Initialize(KernelCore& kernel, Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        Shutdown();
 | 
			
		||||
 | 
			
		||||
        InitializeSystemResourceLimit(kernel);
 | 
			
		||||
        InitializeThreads();
 | 
			
		||||
        InitializeThreads(core_timing);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Shutdown() {
 | 
			
		||||
@@ -122,9 +122,9 @@ struct KernelCore::Impl {
 | 
			
		||||
        ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void InitializeThreads() {
 | 
			
		||||
    void InitializeThreads(Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
        thread_wakeup_event_type =
 | 
			
		||||
            Core::Timing::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
 | 
			
		||||
            core_timing.RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::atomic<u32> next_object_id{0};
 | 
			
		||||
@@ -152,8 +152,8 @@ KernelCore::~KernelCore() {
 | 
			
		||||
    Shutdown();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KernelCore::Initialize() {
 | 
			
		||||
    impl->Initialize(*this);
 | 
			
		||||
void KernelCore::Initialize(Core::Timing::CoreTiming& core_timing) {
 | 
			
		||||
    impl->Initialize(*this, core_timing);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KernelCore::Shutdown() {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,8 +12,9 @@ template <typename T>
 | 
			
		||||
class ResultVal;
 | 
			
		||||
 | 
			
		||||
namespace Core::Timing {
 | 
			
		||||
class CoreTiming;
 | 
			
		||||
struct EventType;
 | 
			
		||||
}
 | 
			
		||||
} // namespace Core::Timing
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
 | 
			
		||||
@@ -39,7 +40,11 @@ public:
 | 
			
		||||
    KernelCore& operator=(KernelCore&&) = delete;
 | 
			
		||||
 | 
			
		||||
    /// 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.
 | 
			
		||||
    void Shutdown();
 | 
			
		||||
 
 | 
			
		||||
@@ -111,7 +111,7 @@ void Scheduler::SwitchContext(Thread* new_thread) {
 | 
			
		||||
 | 
			
		||||
void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
 | 
			
		||||
    const u64 prev_switch_ticks = last_context_switch_time;
 | 
			
		||||
    const u64 most_recent_switch_ticks = Core::Timing::GetTicks();
 | 
			
		||||
    const u64 most_recent_switch_ticks = Core::System::GetInstance().CoreTiming().GetTicks();
 | 
			
		||||
    const u64 update_ticks = most_recent_switch_ticks - prev_switch_ticks;
 | 
			
		||||
 | 
			
		||||
    if (thread != nullptr) {
 | 
			
		||||
 
 | 
			
		||||
@@ -918,6 +918,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const auto& system = Core::System::GetInstance();
 | 
			
		||||
        const auto& core_timing = system.CoreTiming();
 | 
			
		||||
        const auto& scheduler = system.CurrentScheduler();
 | 
			
		||||
        const auto* const current_thread = scheduler.GetCurrentThread();
 | 
			
		||||
        const bool same_thread = current_thread == thread;
 | 
			
		||||
@@ -927,9 +928,9 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
 | 
			
		||||
        if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
 | 
			
		||||
            const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks();
 | 
			
		||||
 | 
			
		||||
            out_ticks = thread_ticks + (Core::Timing::GetTicks() - prev_ctx_ticks);
 | 
			
		||||
            out_ticks = thread_ticks + (core_timing.GetTicks() - prev_ctx_ticks);
 | 
			
		||||
        } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) {
 | 
			
		||||
            out_ticks = Core::Timing::GetTicks() - prev_ctx_ticks;
 | 
			
		||||
            out_ticks = core_timing.GetTicks() - prev_ctx_ticks;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        *result = out_ticks;
 | 
			
		||||
@@ -1546,10 +1547,11 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to
 | 
			
		||||
static u64 GetSystemTick() {
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called");
 | 
			
		||||
 | 
			
		||||
    const u64 result{Core::Timing::GetTicks()};
 | 
			
		||||
    auto& core_timing = Core::System::GetInstance().CoreTiming();
 | 
			
		||||
    const u64 result{core_timing.GetTicks()};
 | 
			
		||||
 | 
			
		||||
    // Advance time to defeat dumb games that busy-wait for the frame to end.
 | 
			
		||||
    Core::Timing::AddTicks(400);
 | 
			
		||||
    core_timing.AddTicks(400);
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,8 @@ Thread::~Thread() = default;
 | 
			
		||||
 | 
			
		||||
void Thread::Stop() {
 | 
			
		||||
    // Cancel any outstanding wakeup events for this thread
 | 
			
		||||
    Core::Timing::UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), callback_handle);
 | 
			
		||||
    Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(),
 | 
			
		||||
                                                             callback_handle);
 | 
			
		||||
    kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle);
 | 
			
		||||
    callback_handle = 0;
 | 
			
		||||
 | 
			
		||||
@@ -85,13 +86,14 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
 | 
			
		||||
 | 
			
		||||
    // This function might be called from any thread so we have to be cautious and use the
 | 
			
		||||
    // thread-safe version of ScheduleEvent.
 | 
			
		||||
    Core::Timing::ScheduleEventThreadsafe(Core::Timing::nsToCycles(nanoseconds),
 | 
			
		||||
                                          kernel.ThreadWakeupCallbackEventType(), callback_handle);
 | 
			
		||||
    Core::System::GetInstance().CoreTiming().ScheduleEventThreadsafe(
 | 
			
		||||
        Core::Timing::nsToCycles(nanoseconds), kernel.ThreadWakeupCallbackEventType(),
 | 
			
		||||
        callback_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Thread::CancelWakeupTimer() {
 | 
			
		||||
    Core::Timing::UnscheduleEventThreadsafe(kernel.ThreadWakeupCallbackEventType(),
 | 
			
		||||
                                            callback_handle);
 | 
			
		||||
    Core::System::GetInstance().CoreTiming().UnscheduleEventThreadsafe(
 | 
			
		||||
        kernel.ThreadWakeupCallbackEventType(), callback_handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static std::optional<s32> GetNextProcessorId(u64 mask) {
 | 
			
		||||
@@ -190,6 +192,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name
 | 
			
		||||
        return ResultCode(-1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& system = Core::System::GetInstance();
 | 
			
		||||
    SharedPtr<Thread> thread(new Thread(kernel));
 | 
			
		||||
 | 
			
		||||
    thread->thread_id = kernel.CreateNewThreadID();
 | 
			
		||||
@@ -198,7 +201,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name
 | 
			
		||||
    thread->stack_top = stack_top;
 | 
			
		||||
    thread->tpidr_el0 = 0;
 | 
			
		||||
    thread->nominal_priority = thread->current_priority = priority;
 | 
			
		||||
    thread->last_running_ticks = Core::Timing::GetTicks();
 | 
			
		||||
    thread->last_running_ticks = system.CoreTiming().GetTicks();
 | 
			
		||||
    thread->processor_id = processor_id;
 | 
			
		||||
    thread->ideal_core = processor_id;
 | 
			
		||||
    thread->affinity_mask = 1ULL << processor_id;
 | 
			
		||||
@@ -209,7 +212,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name
 | 
			
		||||
    thread->name = std::move(name);
 | 
			
		||||
    thread->callback_handle = kernel.ThreadWakeupCallbackHandleTable().Create(thread).Unwrap();
 | 
			
		||||
    thread->owner_process = &owner_process;
 | 
			
		||||
    thread->scheduler = &Core::System::GetInstance().Scheduler(processor_id);
 | 
			
		||||
    thread->scheduler = &system.Scheduler(processor_id);
 | 
			
		||||
    thread->scheduler->AddThread(thread, priority);
 | 
			
		||||
    thread->tls_address = thread->owner_process->MarkNextAvailableTLSSlotAsUsed(*thread);
 | 
			
		||||
 | 
			
		||||
@@ -258,7 +261,7 @@ void Thread::SetStatus(ThreadStatus new_status) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (status == ThreadStatus::Running) {
 | 
			
		||||
        last_running_ticks = Core::Timing::GetTicks();
 | 
			
		||||
        last_running_ticks = Core::System::GetInstance().CoreTiming().GetTicks();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    status = new_status;
 | 
			
		||||
 
 | 
			
		||||
@@ -68,12 +68,12 @@ public:
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
 | 
			
		||||
        // This is the event handle used to check if the audio buffer was released
 | 
			
		||||
        auto& kernel = Core::System::GetInstance().Kernel();
 | 
			
		||||
        buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
 | 
			
		||||
                                                              "IAudioOutBufferReleased");
 | 
			
		||||
        auto& system = Core::System::GetInstance();
 | 
			
		||||
        buffer_event = Kernel::WritableEvent::CreateEventPair(
 | 
			
		||||
            system.Kernel(), Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
 | 
			
		||||
 | 
			
		||||
        stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,
 | 
			
		||||
                                       std::move(unique_name),
 | 
			
		||||
        stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
 | 
			
		||||
                                       audio_params.channel_count, std::move(unique_name),
 | 
			
		||||
                                       [=]() { buffer_event.writable->Signal(); });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -42,10 +42,11 @@ public:
 | 
			
		||||
        // clang-format on
 | 
			
		||||
        RegisterHandlers(functions);
 | 
			
		||||
 | 
			
		||||
        auto& kernel = Core::System::GetInstance().Kernel();
 | 
			
		||||
        system_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
 | 
			
		||||
                                                              "IAudioRenderer:SystemEvent");
 | 
			
		||||
        renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event.writable);
 | 
			
		||||
        auto& system = Core::System::GetInstance();
 | 
			
		||||
        system_event = Kernel::WritableEvent::CreateEventPair(
 | 
			
		||||
            system.Kernel(), Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");
 | 
			
		||||
        renderer = std::make_unique<AudioCore::AudioRenderer>(system.CoreTiming(), audren_params,
 | 
			
		||||
                                                              system_event.writable);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,10 @@
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "common/swap.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::Timing {
 | 
			
		||||
class CoreTiming;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
class ControllerBase {
 | 
			
		||||
public:
 | 
			
		||||
@@ -20,7 +24,8 @@ public:
 | 
			
		||||
    virtual void OnRelease() = 0;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    virtual void OnUpdate(u8* data, std::size_t size) = 0;
 | 
			
		||||
    virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                          std::size_t size) = 0;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    virtual void OnLoadInputDevices() = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,9 @@ void Controller_DebugPad::OnInit() {}
 | 
			
		||||
 | 
			
		||||
void Controller_DebugPad::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Controller_DebugPad::OnUpdate(u8* data, std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = Core::Timing::GetTicks();
 | 
			
		||||
void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                                   std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = core_timing.GetTicks();
 | 
			
		||||
    shared_memory.header.total_entry_count = 17;
 | 
			
		||||
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ public:
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(u8* data, std::size_t size) override;
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    void OnLoadInputDevices() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,8 +17,9 @@ void Controller_Gesture::OnInit() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Gesture::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Gesture::OnUpdate(u8* data, std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = Core::Timing::GetTicks();
 | 
			
		||||
void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                                  std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = core_timing.GetTicks();
 | 
			
		||||
    shared_memory.header.total_entry_count = 17;
 | 
			
		||||
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ public:
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(u8* data, size_t size) override;
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    void OnLoadInputDevices() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,9 @@ void Controller_Keyboard::OnInit() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Keyboard::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Keyboard::OnUpdate(u8* data, std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = Core::Timing::GetTicks();
 | 
			
		||||
void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                                   std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = core_timing.GetTicks();
 | 
			
		||||
    shared_memory.header.total_entry_count = 17;
 | 
			
		||||
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ public:
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(u8* data, std::size_t size) override;
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    void OnLoadInputDevices() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,8 +17,9 @@ Controller_Mouse::~Controller_Mouse() = default;
 | 
			
		||||
void Controller_Mouse::OnInit() {}
 | 
			
		||||
void Controller_Mouse::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Mouse::OnUpdate(u8* data, std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = Core::Timing::GetTicks();
 | 
			
		||||
void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                                std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = core_timing.GetTicks();
 | 
			
		||||
    shared_memory.header.total_entry_count = 17;
 | 
			
		||||
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ public:
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(u8* data, std::size_t size) override;
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    void OnLoadInputDevices() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -288,7 +288,8 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
 | 
			
		||||
    rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
 | 
			
		||||
void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                               std::size_t data_len) {
 | 
			
		||||
    if (!IsControllerActivated())
 | 
			
		||||
        return;
 | 
			
		||||
    for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
 | 
			
		||||
@@ -308,7 +309,7 @@ void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
 | 
			
		||||
            const auto& last_entry =
 | 
			
		||||
                main_controller->npad[main_controller->common.last_entry_index];
 | 
			
		||||
 | 
			
		||||
            main_controller->common.timestamp = Core::Timing::GetTicks();
 | 
			
		||||
            main_controller->common.timestamp = core_timing.GetTicks();
 | 
			
		||||
            main_controller->common.last_entry_index =
 | 
			
		||||
                (main_controller->common.last_entry_index + 1) % 17;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ public:
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(u8* data, std::size_t size) override;
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    void OnLoadInputDevices() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,13 +16,14 @@ void Controller_Stubbed::OnInit() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Stubbed::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Stubbed::OnUpdate(u8* data, std::size_t size) {
 | 
			
		||||
void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                                  std::size_t size) {
 | 
			
		||||
    if (!smart_update) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CommonHeader header{};
 | 
			
		||||
    header.timestamp = Core::Timing::GetTicks();
 | 
			
		||||
    header.timestamp = core_timing.GetTicks();
 | 
			
		||||
    header.total_entry_count = 17;
 | 
			
		||||
    header.entry_count = 0;
 | 
			
		||||
    header.last_entry_index = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ public:
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(u8* data, std::size_t size) override;
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    void OnLoadInputDevices() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,9 @@ void Controller_Touchscreen::OnInit() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Touchscreen::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = Core::Timing::GetTicks();
 | 
			
		||||
void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                                      std::size_t size) {
 | 
			
		||||
    shared_memory.header.timestamp = core_timing.GetTicks();
 | 
			
		||||
    shared_memory.header.total_entry_count = 17;
 | 
			
		||||
 | 
			
		||||
    if (!IsControllerActivated()) {
 | 
			
		||||
@@ -48,7 +49,7 @@ void Controller_Touchscreen::OnUpdate(u8* data, std::size_t size) {
 | 
			
		||||
        touch_entry.diameter_x = Settings::values.touchscreen.diameter_x;
 | 
			
		||||
        touch_entry.diameter_y = Settings::values.touchscreen.diameter_y;
 | 
			
		||||
        touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle;
 | 
			
		||||
        const u64 tick = Core::Timing::GetTicks();
 | 
			
		||||
        const u64 tick = core_timing.GetTicks();
 | 
			
		||||
        touch_entry.delta_time = tick - last_touch;
 | 
			
		||||
        last_touch = tick;
 | 
			
		||||
        touch_entry.finger = Settings::values.touchscreen.finger;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ public:
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(u8* data, std::size_t size) override;
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    void OnLoadInputDevices() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,9 +17,10 @@ void Controller_XPad::OnInit() {}
 | 
			
		||||
 | 
			
		||||
void Controller_XPad::OnRelease() {}
 | 
			
		||||
 | 
			
		||||
void Controller_XPad::OnUpdate(u8* data, std::size_t size) {
 | 
			
		||||
void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
 | 
			
		||||
                               std::size_t size) {
 | 
			
		||||
    for (auto& xpad_entry : shared_memory.shared_memory_entries) {
 | 
			
		||||
        xpad_entry.header.timestamp = Core::Timing::GetTicks();
 | 
			
		||||
        xpad_entry.header.timestamp = core_timing.GetTicks();
 | 
			
		||||
        xpad_entry.header.total_entry_count = 17;
 | 
			
		||||
 | 
			
		||||
        if (!IsControllerActivated()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ public:
 | 
			
		||||
    void OnRelease() override;
 | 
			
		||||
 | 
			
		||||
    // When the controller is requesting an update for the shared memory
 | 
			
		||||
    void OnUpdate(u8* data, std::size_t size) override;
 | 
			
		||||
    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override;
 | 
			
		||||
 | 
			
		||||
    // Called when input devices should be loaded
 | 
			
		||||
    void OnLoadInputDevices() override;
 | 
			
		||||
 
 | 
			
		||||
@@ -73,13 +73,15 @@ IAppletResource::IAppletResource() : ServiceFramework("IAppletResource") {
 | 
			
		||||
    GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000);
 | 
			
		||||
 | 
			
		||||
    // Register update callbacks
 | 
			
		||||
    pad_update_event = Core::Timing::RegisterEvent(
 | 
			
		||||
        "HID::UpdatePadCallback",
 | 
			
		||||
        [this](u64 userdata, int cycles_late) { UpdateControllers(userdata, cycles_late); });
 | 
			
		||||
    auto& core_timing = Core::System::GetInstance().CoreTiming();
 | 
			
		||||
    pad_update_event =
 | 
			
		||||
        core_timing.RegisterEvent("HID::UpdatePadCallback", [this](u64 userdata, int cycles_late) {
 | 
			
		||||
            UpdateControllers(userdata, cycles_late);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
 | 
			
		||||
 | 
			
		||||
    Core::Timing::ScheduleEvent(pad_update_ticks, pad_update_event);
 | 
			
		||||
    core_timing.ScheduleEvent(pad_update_ticks, pad_update_event);
 | 
			
		||||
 | 
			
		||||
    ReloadInputDevices();
 | 
			
		||||
}
 | 
			
		||||
@@ -93,7 +95,7 @@ void IAppletResource::DeactivateController(HidController controller) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IAppletResource ::~IAppletResource() {
 | 
			
		||||
    Core::Timing::UnscheduleEvent(pad_update_event, 0);
 | 
			
		||||
    Core::System::GetInstance().CoreTiming().UnscheduleEvent(pad_update_event, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -105,15 +107,17 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IAppletResource::UpdateControllers(u64 userdata, int cycles_late) {
 | 
			
		||||
    auto& core_timing = Core::System::GetInstance().CoreTiming();
 | 
			
		||||
 | 
			
		||||
    const bool should_reload = Settings::values.is_device_reload_pending.exchange(false);
 | 
			
		||||
    for (const auto& controller : controllers) {
 | 
			
		||||
        if (should_reload) {
 | 
			
		||||
            controller->OnLoadInputDevices();
 | 
			
		||||
        }
 | 
			
		||||
        controller->OnUpdate(shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
 | 
			
		||||
        controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Core::Timing::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
 | 
			
		||||
    core_timing.ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
 | 
			
		||||
 
 | 
			
		||||
@@ -98,7 +98,7 @@ void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 5};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.PushRaw<u64>(Core::Timing::GetTicks());
 | 
			
		||||
    rb.PushRaw<u64>(Core::System::GetInstance().CoreTiming().GetTicks());
 | 
			
		||||
    rb.PushRaw<u32>(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/core_timing_util.h"
 | 
			
		||||
#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
 | 
			
		||||
@@ -184,7 +185,7 @@ u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& o
 | 
			
		||||
 | 
			
		||||
    IoctlGetGpuTime params{};
 | 
			
		||||
    std::memcpy(¶ms, input.data(), input.size());
 | 
			
		||||
    params.gpu_time = Core::Timing::cyclesToNs(Core::Timing::GetTicks());
 | 
			
		||||
    params.gpu_time = Core::Timing::cyclesToNs(Core::System::GetInstance().CoreTiming().GetTicks());
 | 
			
		||||
    std::memcpy(output.data(), ¶ms, output.size());
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,19 +27,19 @@ namespace Service::NVFlinger {
 | 
			
		||||
constexpr std::size_t SCREEN_REFRESH_RATE = 60;
 | 
			
		||||
constexpr u64 frame_ticks = static_cast<u64>(Core::Timing::BASE_CLOCK_RATE / SCREEN_REFRESH_RATE);
 | 
			
		||||
 | 
			
		||||
NVFlinger::NVFlinger() {
 | 
			
		||||
NVFlinger::NVFlinger(Core::Timing::CoreTiming& core_timing) : core_timing{core_timing} {
 | 
			
		||||
    // Schedule the screen composition events
 | 
			
		||||
    composition_event =
 | 
			
		||||
        Core::Timing::RegisterEvent("ScreenComposition", [this](u64 userdata, int cycles_late) {
 | 
			
		||||
        core_timing.RegisterEvent("ScreenComposition", [this](u64 userdata, int cycles_late) {
 | 
			
		||||
            Compose();
 | 
			
		||||
            Core::Timing::ScheduleEvent(frame_ticks - cycles_late, composition_event);
 | 
			
		||||
            this->core_timing.ScheduleEvent(frame_ticks - cycles_late, composition_event);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    Core::Timing::ScheduleEvent(frame_ticks, composition_event);
 | 
			
		||||
    core_timing.ScheduleEvent(frame_ticks, composition_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NVFlinger::~NVFlinger() {
 | 
			
		||||
    Core::Timing::UnscheduleEvent(composition_event, 0);
 | 
			
		||||
    core_timing.UnscheduleEvent(composition_event, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,8 +15,9 @@
 | 
			
		||||
#include "core/hle/kernel/object.h"
 | 
			
		||||
 | 
			
		||||
namespace Core::Timing {
 | 
			
		||||
class CoreTiming;
 | 
			
		||||
struct EventType;
 | 
			
		||||
}
 | 
			
		||||
} // namespace Core::Timing
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
class ReadableEvent;
 | 
			
		||||
@@ -52,7 +53,7 @@ struct Display {
 | 
			
		||||
 | 
			
		||||
class NVFlinger final {
 | 
			
		||||
public:
 | 
			
		||||
    NVFlinger();
 | 
			
		||||
    explicit NVFlinger(Core::Timing::CoreTiming& core_timing);
 | 
			
		||||
    ~NVFlinger();
 | 
			
		||||
 | 
			
		||||
    /// Sets the NVDrv module instance to use to send buffers to the GPU.
 | 
			
		||||
@@ -117,6 +118,9 @@ private:
 | 
			
		||||
 | 
			
		||||
    /// Event that handles screen composition.
 | 
			
		||||
    Core::Timing::EventType* composition_event;
 | 
			
		||||
 | 
			
		||||
    /// Core timing instance for registering/unregistering the composition event.
 | 
			
		||||
    Core::Timing::CoreTiming& core_timing;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::NVFlinger
 | 
			
		||||
 
 | 
			
		||||
@@ -194,10 +194,11 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
 | 
			
		||||
// Module interface
 | 
			
		||||
 | 
			
		||||
/// Initialize ServiceManager
 | 
			
		||||
void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs) {
 | 
			
		||||
void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
 | 
			
		||||
          FileSys::VfsFilesystem& vfs) {
 | 
			
		||||
    // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
 | 
			
		||||
    // here and pass it into the respective InstallInterfaces functions.
 | 
			
		||||
    auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>();
 | 
			
		||||
    auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>(system.CoreTiming());
 | 
			
		||||
 | 
			
		||||
    SM::ServiceManager::InstallInterfaces(sm);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,14 @@
 | 
			
		||||
////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Namespace Service
 | 
			
		||||
 | 
			
		||||
namespace Core {
 | 
			
		||||
class System;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace FileSys {
 | 
			
		||||
class VfsFilesystem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
class ClientPort;
 | 
			
		||||
class ServerPort;
 | 
			
		||||
@@ -21,10 +29,6 @@ class ServerSession;
 | 
			
		||||
class HLERequestContext;
 | 
			
		||||
} // namespace Kernel
 | 
			
		||||
 | 
			
		||||
namespace FileSys {
 | 
			
		||||
class VfsFilesystem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace Service {
 | 
			
		||||
 | 
			
		||||
namespace SM {
 | 
			
		||||
@@ -178,7 +182,8 @@ private:
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// Initialize ServiceManager
 | 
			
		||||
void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs);
 | 
			
		||||
void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system,
 | 
			
		||||
          FileSys::VfsFilesystem& vfs);
 | 
			
		||||
 | 
			
		||||
/// Shutdown ServiceManager
 | 
			
		||||
void Shutdown();
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/core_timing.h"
 | 
			
		||||
#include "core/core_timing_util.h"
 | 
			
		||||
#include "core/hle/ipc_helpers.h"
 | 
			
		||||
@@ -106,8 +107,9 @@ private:
 | 
			
		||||
    void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        LOG_DEBUG(Service_Time, "called");
 | 
			
		||||
 | 
			
		||||
        const auto& core_timing = Core::System::GetInstance().CoreTiming();
 | 
			
		||||
        const SteadyClockTimePoint steady_clock_time_point{
 | 
			
		||||
            Core::Timing::cyclesToMs(Core::Timing::GetTicks()) / 1000};
 | 
			
		||||
            Core::Timing::cyclesToMs(core_timing.GetTicks()) / 1000};
 | 
			
		||||
        IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
 | 
			
		||||
        rb.Push(RESULT_SUCCESS);
 | 
			
		||||
        rb.PushRaw(steady_clock_time_point);
 | 
			
		||||
@@ -281,8 +283,9 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& core_timing = Core::System::GetInstance().CoreTiming();
 | 
			
		||||
    const SteadyClockTimePoint steady_clock_time_point{
 | 
			
		||||
        Core::Timing::cyclesToMs(Core::Timing::GetTicks()) / 1000, {}};
 | 
			
		||||
        Core::Timing::cyclesToMs(core_timing.GetTicks()) / 1000, {}};
 | 
			
		||||
 | 
			
		||||
    CalendarTime calendar_time{};
 | 
			
		||||
    calendar_time.year = tm->tm_year + 1900;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user