Merge pull request #12454 from liamwhite/ct-stuff
core_timing: minor refactors
This commit is contained in:
		@@ -18,9 +18,7 @@ constexpr auto INCREMENT_TIME{5ms};
 | 
			
		||||
DeviceSession::DeviceSession(Core::System& system_)
 | 
			
		||||
    : system{system_}, thread_event{Core::Timing::CreateEvent(
 | 
			
		||||
                           "AudioOutSampleTick",
 | 
			
		||||
                           [this](std::uintptr_t, s64 time, std::chrono::nanoseconds) {
 | 
			
		||||
                               return ThreadFunc();
 | 
			
		||||
                           })} {}
 | 
			
		||||
                           [this](s64 time, std::chrono::nanoseconds) { return ThreadFunc(); })} {}
 | 
			
		||||
 | 
			
		||||
DeviceSession::~DeviceSession() {
 | 
			
		||||
    Finalize();
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@ std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callbac
 | 
			
		||||
struct CoreTiming::Event {
 | 
			
		||||
    s64 time;
 | 
			
		||||
    u64 fifo_order;
 | 
			
		||||
    std::uintptr_t user_data;
 | 
			
		||||
    std::weak_ptr<EventType> type;
 | 
			
		||||
    s64 reschedule_time;
 | 
			
		||||
    heap_t::handle_type handle{};
 | 
			
		||||
@@ -67,17 +66,15 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
 | 
			
		||||
    event_fifo_id = 0;
 | 
			
		||||
    shutting_down = false;
 | 
			
		||||
    cpu_ticks = 0;
 | 
			
		||||
    const auto empty_timed_callback = [](std::uintptr_t, u64, std::chrono::nanoseconds)
 | 
			
		||||
        -> std::optional<std::chrono::nanoseconds> { return std::nullopt; };
 | 
			
		||||
    ev_lost = CreateEvent("_lost_event", empty_timed_callback);
 | 
			
		||||
    if (is_multicore) {
 | 
			
		||||
        timer_thread = std::make_unique<std::jthread>(ThreadEntry, std::ref(*this));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CoreTiming::ClearPendingEvents() {
 | 
			
		||||
    std::scoped_lock lock{basic_lock};
 | 
			
		||||
    std::scoped_lock lock{advance_lock, basic_lock};
 | 
			
		||||
    event_queue.clear();
 | 
			
		||||
    event.Set();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CoreTiming::Pause(bool is_paused) {
 | 
			
		||||
@@ -119,14 +116,12 @@ bool CoreTiming::HasPendingEvents() const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
 | 
			
		||||
                               const std::shared_ptr<EventType>& event_type,
 | 
			
		||||
                               std::uintptr_t user_data, bool absolute_time) {
 | 
			
		||||
                               const std::shared_ptr<EventType>& event_type, bool absolute_time) {
 | 
			
		||||
    {
 | 
			
		||||
        std::scoped_lock scope{basic_lock};
 | 
			
		||||
        const auto next_time{absolute_time ? ns_into_future : GetGlobalTimeNs() + ns_into_future};
 | 
			
		||||
 | 
			
		||||
        auto h{event_queue.emplace(
 | 
			
		||||
            Event{next_time.count(), event_fifo_id++, user_data, event_type, 0})};
 | 
			
		||||
        auto h{event_queue.emplace(Event{next_time.count(), event_fifo_id++, event_type, 0})};
 | 
			
		||||
        (*h).handle = h;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -136,13 +131,13 @@ void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
 | 
			
		||||
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
 | 
			
		||||
                                      std::chrono::nanoseconds resched_time,
 | 
			
		||||
                                      const std::shared_ptr<EventType>& event_type,
 | 
			
		||||
                                      std::uintptr_t user_data, bool absolute_time) {
 | 
			
		||||
                                      bool absolute_time) {
 | 
			
		||||
    {
 | 
			
		||||
        std::scoped_lock scope{basic_lock};
 | 
			
		||||
        const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time};
 | 
			
		||||
 | 
			
		||||
        auto h{event_queue.emplace(Event{next_time.count(), event_fifo_id++, user_data, event_type,
 | 
			
		||||
                                         resched_time.count()})};
 | 
			
		||||
        auto h{event_queue.emplace(
 | 
			
		||||
            Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()})};
 | 
			
		||||
        (*h).handle = h;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -150,14 +145,14 @@ void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
 | 
			
		||||
                                 std::uintptr_t user_data, bool wait) {
 | 
			
		||||
                                 UnscheduleEventType type) {
 | 
			
		||||
    {
 | 
			
		||||
        std::scoped_lock lk{basic_lock};
 | 
			
		||||
 | 
			
		||||
        std::vector<heap_t::handle_type> to_remove;
 | 
			
		||||
        for (auto itr = event_queue.begin(); itr != event_queue.end(); itr++) {
 | 
			
		||||
            const Event& e = *itr;
 | 
			
		||||
            if (e.type.lock().get() == event_type.get() && e.user_data == user_data) {
 | 
			
		||||
            if (e.type.lock().get() == event_type.get()) {
 | 
			
		||||
                to_remove.push_back(itr->handle);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -165,10 +160,12 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
 | 
			
		||||
        for (auto h : to_remove) {
 | 
			
		||||
            event_queue.erase(h);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        event_type->sequence_number++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Force any in-progress events to finish
 | 
			
		||||
    if (wait) {
 | 
			
		||||
    if (type == UnscheduleEventType::Wait) {
 | 
			
		||||
        std::scoped_lock lk{advance_lock};
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -208,28 +205,31 @@ std::optional<s64> CoreTiming::Advance() {
 | 
			
		||||
        const Event& evt = event_queue.top();
 | 
			
		||||
 | 
			
		||||
        if (const auto event_type{evt.type.lock()}) {
 | 
			
		||||
            if (evt.reschedule_time == 0) {
 | 
			
		||||
                const auto evt_user_data = evt.user_data;
 | 
			
		||||
            const auto evt_time = evt.time;
 | 
			
		||||
            const auto evt_sequence_num = event_type->sequence_number;
 | 
			
		||||
 | 
			
		||||
            if (evt.reschedule_time == 0) {
 | 
			
		||||
                event_queue.pop();
 | 
			
		||||
 | 
			
		||||
                basic_lock.unlock();
 | 
			
		||||
 | 
			
		||||
                event_type->callback(
 | 
			
		||||
                    evt_user_data, evt_time,
 | 
			
		||||
                    std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt_time});
 | 
			
		||||
                    evt_time, std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt_time});
 | 
			
		||||
 | 
			
		||||
                basic_lock.lock();
 | 
			
		||||
            } else {
 | 
			
		||||
                basic_lock.unlock();
 | 
			
		||||
 | 
			
		||||
                const auto new_schedule_time{event_type->callback(
 | 
			
		||||
                    evt.user_data, evt.time,
 | 
			
		||||
                    std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt.time})};
 | 
			
		||||
                    evt_time, std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt_time})};
 | 
			
		||||
 | 
			
		||||
                basic_lock.lock();
 | 
			
		||||
 | 
			
		||||
                if (evt_sequence_num != event_type->sequence_number) {
 | 
			
		||||
                    // Heap handle is invalidated after external modification.
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                const auto next_schedule_time{new_schedule_time.has_value()
 | 
			
		||||
                                                  ? new_schedule_time.value().count()
 | 
			
		||||
                                                  : evt.reschedule_time};
 | 
			
		||||
@@ -241,8 +241,8 @@ std::optional<s64> CoreTiming::Advance() {
 | 
			
		||||
                    next_time = pause_end_time + next_schedule_time;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.user_data,
 | 
			
		||||
                                                     evt.type, next_schedule_time, evt.handle});
 | 
			
		||||
                event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type,
 | 
			
		||||
                                                     next_schedule_time, evt.handle});
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,17 +22,25 @@ namespace Core::Timing {
 | 
			
		||||
 | 
			
		||||
/// A callback that may be scheduled for a particular core timing event.
 | 
			
		||||
using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>(
 | 
			
		||||
    std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)>;
 | 
			
		||||
    s64 time, std::chrono::nanoseconds ns_late)>;
 | 
			
		||||
 | 
			
		||||
/// Contains the characteristics of a particular event.
 | 
			
		||||
struct EventType {
 | 
			
		||||
    explicit EventType(TimedCallback&& callback_, std::string&& name_)
 | 
			
		||||
        : callback{std::move(callback_)}, name{std::move(name_)} {}
 | 
			
		||||
        : callback{std::move(callback_)}, name{std::move(name_)}, sequence_number{0} {}
 | 
			
		||||
 | 
			
		||||
    /// The event's callback function.
 | 
			
		||||
    TimedCallback callback;
 | 
			
		||||
    /// A pointer to the name of the event.
 | 
			
		||||
    const std::string name;
 | 
			
		||||
    /// A monotonic sequence number, incremented when this event is
 | 
			
		||||
    /// changed externally.
 | 
			
		||||
    size_t sequence_number;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class UnscheduleEventType {
 | 
			
		||||
    Wait,
 | 
			
		||||
    NoWait,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -89,23 +97,17 @@ public:
 | 
			
		||||
 | 
			
		||||
    /// Schedules an event in core timing
 | 
			
		||||
    void ScheduleEvent(std::chrono::nanoseconds ns_into_future,
 | 
			
		||||
                       const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data = 0,
 | 
			
		||||
                       bool absolute_time = false);
 | 
			
		||||
                       const std::shared_ptr<EventType>& event_type, bool absolute_time = false);
 | 
			
		||||
 | 
			
		||||
    /// Schedules an event which will automatically re-schedule itself with the given time, until
 | 
			
		||||
    /// unscheduled
 | 
			
		||||
    void ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
 | 
			
		||||
                              std::chrono::nanoseconds resched_time,
 | 
			
		||||
                              const std::shared_ptr<EventType>& event_type,
 | 
			
		||||
                              std::uintptr_t user_data = 0, bool absolute_time = false);
 | 
			
		||||
                              bool absolute_time = false);
 | 
			
		||||
 | 
			
		||||
    void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, std::uintptr_t user_data,
 | 
			
		||||
                         bool wait = true);
 | 
			
		||||
 | 
			
		||||
    void UnscheduleEventWithoutWait(const std::shared_ptr<EventType>& event_type,
 | 
			
		||||
                                    std::uintptr_t user_data) {
 | 
			
		||||
        UnscheduleEvent(event_type, user_data, false);
 | 
			
		||||
    }
 | 
			
		||||
    void UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
 | 
			
		||||
                         UnscheduleEventType type = UnscheduleEventType::Wait);
 | 
			
		||||
 | 
			
		||||
    void AddTicks(u64 ticks_to_add);
 | 
			
		||||
 | 
			
		||||
@@ -158,7 +160,6 @@ private:
 | 
			
		||||
    heap_t event_queue;
 | 
			
		||||
    u64 event_fifo_id = 0;
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<EventType> ev_lost;
 | 
			
		||||
    Common::Event event{};
 | 
			
		||||
    Common::Event pause_event{};
 | 
			
		||||
    mutable std::mutex basic_lock;
 | 
			
		||||
 
 | 
			
		||||
@@ -10,15 +10,15 @@ namespace Kernel {
 | 
			
		||||
 | 
			
		||||
void KHardwareTimer::Initialize() {
 | 
			
		||||
    // Create the timing callback to register with CoreTiming.
 | 
			
		||||
    m_event_type = Core::Timing::CreateEvent(
 | 
			
		||||
        "KHardwareTimer::Callback", [](std::uintptr_t timer_handle, s64, std::chrono::nanoseconds) {
 | 
			
		||||
            reinterpret_cast<KHardwareTimer*>(timer_handle)->DoTask();
 | 
			
		||||
    m_event_type = Core::Timing::CreateEvent("KHardwareTimer::Callback",
 | 
			
		||||
                                             [this](s64, std::chrono::nanoseconds) {
 | 
			
		||||
                                                 this->DoTask();
 | 
			
		||||
                                                 return std::nullopt;
 | 
			
		||||
                                             });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KHardwareTimer::Finalize() {
 | 
			
		||||
    m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this));
 | 
			
		||||
    m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type);
 | 
			
		||||
    m_wakeup_time = std::numeric_limits<s64>::max();
 | 
			
		||||
    m_event_type.reset();
 | 
			
		||||
}
 | 
			
		||||
@@ -57,13 +57,12 @@ void KHardwareTimer::EnableInterrupt(s64 wakeup_time) {
 | 
			
		||||
 | 
			
		||||
    m_wakeup_time = wakeup_time;
 | 
			
		||||
    m_kernel.System().CoreTiming().ScheduleEvent(std::chrono::nanoseconds{m_wakeup_time},
 | 
			
		||||
                                                 m_event_type, reinterpret_cast<uintptr_t>(this),
 | 
			
		||||
                                                 true);
 | 
			
		||||
                                                 m_event_type, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KHardwareTimer::DisableInterrupt() {
 | 
			
		||||
    m_kernel.System().CoreTiming().UnscheduleEventWithoutWait(m_event_type,
 | 
			
		||||
                                                              reinterpret_cast<uintptr_t>(this));
 | 
			
		||||
    m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type,
 | 
			
		||||
                                                   Core::Timing::UnscheduleEventType::NoWait);
 | 
			
		||||
    m_wakeup_time = std::numeric_limits<s64>::max();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -238,7 +238,7 @@ struct KernelCore::Impl {
 | 
			
		||||
    void InitializePreemption(KernelCore& kernel) {
 | 
			
		||||
        preemption_event = Core::Timing::CreateEvent(
 | 
			
		||||
            "PreemptionCallback",
 | 
			
		||||
            [this, &kernel](std::uintptr_t, s64 time,
 | 
			
		||||
            [this, &kernel](s64 time,
 | 
			
		||||
                            std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
                {
 | 
			
		||||
                    KScopedSchedulerLock lock(kernel);
 | 
			
		||||
 
 | 
			
		||||
@@ -49,10 +49,10 @@ HidBus::HidBus(Core::System& system_)
 | 
			
		||||
    // Register update callbacks
 | 
			
		||||
    hidbus_update_event = Core::Timing::CreateEvent(
 | 
			
		||||
        "Hidbus::UpdateCallback",
 | 
			
		||||
        [this](std::uintptr_t user_data, s64 time,
 | 
			
		||||
        [this](s64 time,
 | 
			
		||||
               std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            const auto guard = LockService();
 | 
			
		||||
            UpdateHidbus(user_data, ns_late);
 | 
			
		||||
            UpdateHidbus(ns_late);
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -61,10 +61,10 @@ HidBus::HidBus(Core::System& system_)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
HidBus::~HidBus() {
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(hidbus_update_event, 0);
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(hidbus_update_event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void HidBus::UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
 | 
			
		||||
void HidBus::UpdateHidbus(std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    if (is_hidbus_enabled) {
 | 
			
		||||
        for (std::size_t i = 0; i < devices.size(); ++i) {
 | 
			
		||||
            if (!devices[i].is_device_initializated) {
 | 
			
		||||
 
 | 
			
		||||
@@ -108,7 +108,7 @@ private:
 | 
			
		||||
    void DisableJoyPollingReceiveMode(HLERequestContext& ctx);
 | 
			
		||||
    void SetStatusManagerType(HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
    void UpdateHidbus(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void UpdateHidbus(std::chrono::nanoseconds ns_late);
 | 
			
		||||
    std::optional<std::size_t> GetDeviceIndexFromHandle(BusHandle handle) const;
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
 
 | 
			
		||||
@@ -227,8 +227,7 @@ void ResourceManager::EnableTouchScreen(u64 aruid, bool is_enabled) {
 | 
			
		||||
    applet_resource->EnableTouchScreen(aruid, is_enabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResourceManager::UpdateControllers(std::uintptr_t user_data,
 | 
			
		||||
                                        std::chrono::nanoseconds ns_late) {
 | 
			
		||||
void ResourceManager::UpdateControllers(std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    auto& core_timing = system.CoreTiming();
 | 
			
		||||
    debug_pad->OnUpdate(core_timing);
 | 
			
		||||
    digitizer->OnUpdate(core_timing);
 | 
			
		||||
@@ -241,20 +240,19 @@ void ResourceManager::UpdateControllers(std::uintptr_t user_data,
 | 
			
		||||
    capture_button->OnUpdate(core_timing);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResourceManager::UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
 | 
			
		||||
void ResourceManager::UpdateNpad(std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    auto& core_timing = system.CoreTiming();
 | 
			
		||||
    npad->OnUpdate(core_timing);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResourceManager::UpdateMouseKeyboard(std::uintptr_t user_data,
 | 
			
		||||
                                          std::chrono::nanoseconds ns_late) {
 | 
			
		||||
void ResourceManager::UpdateMouseKeyboard(std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    auto& core_timing = system.CoreTiming();
 | 
			
		||||
    mouse->OnUpdate(core_timing);
 | 
			
		||||
    debug_mouse->OnUpdate(core_timing);
 | 
			
		||||
    keyboard->OnUpdate(core_timing);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResourceManager::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {
 | 
			
		||||
void ResourceManager::UpdateMotion(std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    auto& core_timing = system.CoreTiming();
 | 
			
		||||
    six_axis->OnUpdate(core_timing);
 | 
			
		||||
    seven_six_axis->OnUpdate(core_timing);
 | 
			
		||||
@@ -273,34 +271,34 @@ IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<Resource
 | 
			
		||||
    // Register update callbacks
 | 
			
		||||
    npad_update_event = Core::Timing::CreateEvent(
 | 
			
		||||
        "HID::UpdatePadCallback",
 | 
			
		||||
        [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
 | 
			
		||||
            -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
        [this, resource](
 | 
			
		||||
            s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            const auto guard = LockService();
 | 
			
		||||
            resource->UpdateNpad(user_data, ns_late);
 | 
			
		||||
            resource->UpdateNpad(ns_late);
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
        });
 | 
			
		||||
    default_update_event = Core::Timing::CreateEvent(
 | 
			
		||||
        "HID::UpdateDefaultCallback",
 | 
			
		||||
        [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
 | 
			
		||||
            -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
        [this, resource](
 | 
			
		||||
            s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            const auto guard = LockService();
 | 
			
		||||
            resource->UpdateControllers(user_data, ns_late);
 | 
			
		||||
            resource->UpdateControllers(ns_late);
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
        });
 | 
			
		||||
    mouse_keyboard_update_event = Core::Timing::CreateEvent(
 | 
			
		||||
        "HID::UpdateMouseKeyboardCallback",
 | 
			
		||||
        [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
 | 
			
		||||
            -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
        [this, resource](
 | 
			
		||||
            s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            const auto guard = LockService();
 | 
			
		||||
            resource->UpdateMouseKeyboard(user_data, ns_late);
 | 
			
		||||
            resource->UpdateMouseKeyboard(ns_late);
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
        });
 | 
			
		||||
    motion_update_event = Core::Timing::CreateEvent(
 | 
			
		||||
        "HID::UpdateMotionCallback",
 | 
			
		||||
        [this, resource](std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)
 | 
			
		||||
            -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
        [this, resource](
 | 
			
		||||
            s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            const auto guard = LockService();
 | 
			
		||||
            resource->UpdateMotion(user_data, ns_late);
 | 
			
		||||
            resource->UpdateMotion(ns_late);
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -314,10 +312,10 @@ IAppletResource::IAppletResource(Core::System& system_, std::shared_ptr<Resource
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IAppletResource::~IAppletResource() {
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(npad_update_event, 0);
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(default_update_event, 0);
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event, 0);
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(motion_update_event, 0);
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(npad_update_event);
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(default_update_event);
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(mouse_keyboard_update_event);
 | 
			
		||||
    system.CoreTiming().UnscheduleEvent(motion_update_event);
 | 
			
		||||
    resource_manager->FreeAppletResourceId(aruid);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -81,10 +81,10 @@ public:
 | 
			
		||||
    void EnablePadInput(u64 aruid, bool is_enabled);
 | 
			
		||||
    void EnableTouchScreen(u64 aruid, bool is_enabled);
 | 
			
		||||
 | 
			
		||||
    void UpdateControllers(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void UpdateNpad(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void UpdateMouseKeyboard(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void UpdateControllers(std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void UpdateNpad(std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void UpdateMouseKeyboard(std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void UpdateMotion(std::chrono::nanoseconds ns_late);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    Result CreateAppletResourceImpl(u64 aruid);
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
 | 
			
		||||
    // Schedule the screen composition events
 | 
			
		||||
    multi_composition_event = Core::Timing::CreateEvent(
 | 
			
		||||
        "ScreenComposition",
 | 
			
		||||
        [this](std::uintptr_t, s64 time,
 | 
			
		||||
        [this](s64 time,
 | 
			
		||||
               std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            vsync_signal.Set();
 | 
			
		||||
            return std::chrono::nanoseconds(GetNextTicks());
 | 
			
		||||
@@ -75,7 +75,7 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
 | 
			
		||||
 | 
			
		||||
    single_composition_event = Core::Timing::CreateEvent(
 | 
			
		||||
        "ScreenComposition",
 | 
			
		||||
        [this](std::uintptr_t, s64 time,
 | 
			
		||||
        [this](s64 time,
 | 
			
		||||
               std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            const auto lock_guard = Lock();
 | 
			
		||||
            Compose();
 | 
			
		||||
@@ -93,11 +93,11 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
 | 
			
		||||
 | 
			
		||||
Nvnflinger::~Nvnflinger() {
 | 
			
		||||
    if (system.IsMulticore()) {
 | 
			
		||||
        system.CoreTiming().UnscheduleEvent(multi_composition_event, {});
 | 
			
		||||
        system.CoreTiming().UnscheduleEvent(multi_composition_event);
 | 
			
		||||
        vsync_thread.request_stop();
 | 
			
		||||
        vsync_signal.Set();
 | 
			
		||||
    } else {
 | 
			
		||||
        system.CoreTiming().UnscheduleEvent(single_composition_event, {});
 | 
			
		||||
        system.CoreTiming().UnscheduleEvent(single_composition_event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ShutdownLayers();
 | 
			
		||||
 
 | 
			
		||||
@@ -190,15 +190,15 @@ CheatEngine::CheatEngine(System& system_, std::vector<CheatEntry> cheats_,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CheatEngine::~CheatEngine() {
 | 
			
		||||
    core_timing.UnscheduleEvent(event, 0);
 | 
			
		||||
    core_timing.UnscheduleEvent(event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CheatEngine::Initialize() {
 | 
			
		||||
    event = Core::Timing::CreateEvent(
 | 
			
		||||
        "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
 | 
			
		||||
        [this](std::uintptr_t user_data, s64 time,
 | 
			
		||||
        [this](s64 time,
 | 
			
		||||
               std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            FrameCallback(user_data, ns_late);
 | 
			
		||||
            FrameCallback(ns_late);
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
        });
 | 
			
		||||
    core_timing.ScheduleLoopingEvent(CHEAT_ENGINE_NS, CHEAT_ENGINE_NS, event);
 | 
			
		||||
@@ -239,7 +239,7 @@ void CheatEngine::Reload(std::vector<CheatEntry> reload_cheats) {
 | 
			
		||||
 | 
			
		||||
MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70));
 | 
			
		||||
 | 
			
		||||
void CheatEngine::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
 | 
			
		||||
void CheatEngine::FrameCallback(std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    if (is_pending_reload.exchange(false)) {
 | 
			
		||||
        vm.LoadProgram(cheats);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,7 @@ public:
 | 
			
		||||
    void Reload(std::vector<CheatEntry> reload_cheats);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void FrameCallback(std::chrono::nanoseconds ns_late);
 | 
			
		||||
 | 
			
		||||
    DmntCheatVm vm;
 | 
			
		||||
    CheatProcessMetadata metadata;
 | 
			
		||||
 
 | 
			
		||||
@@ -51,18 +51,17 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
 | 
			
		||||
 | 
			
		||||
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
 | 
			
		||||
    : core_timing{core_timing_}, memory{memory_} {
 | 
			
		||||
    event = Core::Timing::CreateEvent(
 | 
			
		||||
        "MemoryFreezer::FrameCallback",
 | 
			
		||||
        [this](std::uintptr_t user_data, s64 time,
 | 
			
		||||
               std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
            FrameCallback(user_data, ns_late);
 | 
			
		||||
    event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback",
 | 
			
		||||
                                      [this](s64 time, std::chrono::nanoseconds ns_late)
 | 
			
		||||
                                          -> std::optional<std::chrono::nanoseconds> {
 | 
			
		||||
                                          FrameCallback(ns_late);
 | 
			
		||||
                                          return std::nullopt;
 | 
			
		||||
                                      });
 | 
			
		||||
    core_timing.ScheduleEvent(memory_freezer_ns, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Freezer::~Freezer() {
 | 
			
		||||
    core_timing.UnscheduleEvent(event, 0);
 | 
			
		||||
    core_timing.UnscheduleEvent(event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Freezer::SetActive(bool is_active) {
 | 
			
		||||
@@ -159,7 +158,7 @@ Freezer::Entries::const_iterator Freezer::FindEntry(VAddr address) const {
 | 
			
		||||
                        [address](const Entry& entry) { return entry.address == address; });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Freezer::FrameCallback(std::uintptr_t, std::chrono::nanoseconds ns_late) {
 | 
			
		||||
void Freezer::FrameCallback(std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    if (!IsActive()) {
 | 
			
		||||
        LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events.");
 | 
			
		||||
        return;
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ private:
 | 
			
		||||
    Entries::iterator FindEntry(VAddr address);
 | 
			
		||||
    Entries::const_iterator FindEntry(VAddr address) const;
 | 
			
		||||
 | 
			
		||||
    void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void FrameCallback(std::chrono::nanoseconds ns_late);
 | 
			
		||||
    void FillEntryReads();
 | 
			
		||||
 | 
			
		||||
    std::atomic_bool active{false};
 | 
			
		||||
 
 | 
			
		||||
@@ -16,20 +16,16 @@
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
// Numbers are chosen randomly to make sure the correct one is given.
 | 
			
		||||
constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}};
 | 
			
		||||
constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}};
 | 
			
		||||
std::array<s64, 5> delays{};
 | 
			
		||||
 | 
			
		||||
std::bitset<CB_IDS.size()> callbacks_ran_flags;
 | 
			
		||||
std::bitset<5> callbacks_ran_flags;
 | 
			
		||||
u64 expected_callback = 0;
 | 
			
		||||
 | 
			
		||||
template <unsigned int IDX>
 | 
			
		||||
std::optional<std::chrono::nanoseconds> HostCallbackTemplate(std::uintptr_t user_data, s64 time,
 | 
			
		||||
std::optional<std::chrono::nanoseconds> HostCallbackTemplate(s64 time,
 | 
			
		||||
                                                             std::chrono::nanoseconds ns_late) {
 | 
			
		||||
    static_assert(IDX < CB_IDS.size(), "IDX out of range");
 | 
			
		||||
    static_assert(IDX < callbacks_ran_flags.size(), "IDX out of range");
 | 
			
		||||
    callbacks_ran_flags.set(IDX);
 | 
			
		||||
    REQUIRE(CB_IDS[IDX] == user_data);
 | 
			
		||||
    REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
 | 
			
		||||
    delays[IDX] = ns_late.count();
 | 
			
		||||
    ++expected_callback;
 | 
			
		||||
    return std::nullopt;
 | 
			
		||||
@@ -76,7 +72,7 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
 | 
			
		||||
        const u64 order = calls_order[i];
 | 
			
		||||
        const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)};
 | 
			
		||||
 | 
			
		||||
        core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]);
 | 
			
		||||
        core_timing.ScheduleEvent(future_ns, events[order]);
 | 
			
		||||
    }
 | 
			
		||||
    /// test pause
 | 
			
		||||
    REQUIRE(callbacks_ran_flags.none());
 | 
			
		||||
@@ -118,7 +114,7 @@ TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") {
 | 
			
		||||
    for (std::size_t i = 0; i < events.size(); i++) {
 | 
			
		||||
        const u64 order = calls_order[i];
 | 
			
		||||
        const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)};
 | 
			
		||||
        core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]);
 | 
			
		||||
        core_timing.ScheduleEvent(future_ns, events[order]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const u64 end = core_timing.GetGlobalTimeNs().count();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user