diff --git a/.gitmodules b/.gitmodules index 1d9f8c3f..fa3785a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,9 +58,6 @@ [submodule "third_party/Catch2"] path = third_party/Catch2 url = https://github.com/catchorg/Catch2.git -[submodule "third_party/capstone"] - path = third_party/capstone - url = https://github.com/capstone-engine/capstone [submodule "third_party/hips"] path = third_party/hips url = https://github.com/wheremyfoodat/Hips @@ -80,3 +77,6 @@ path = third_party/SDL2 url = https://github.com/libsdl-org/SDL branch = SDL2 +[submodule "third_party/capstone"] + path = third_party/capstone + url = https://github.com/Panda3DS-emu/capstone diff --git a/include/scheduler.hpp b/include/scheduler.hpp index 7c663992..7c7b1e68 100644 --- a/include/scheduler.hpp +++ b/include/scheduler.hpp @@ -29,6 +29,8 @@ struct Scheduler { // Set nextTimestamp to the timestamp of the next event void updateNextTimestamp() { nextTimestamp = events.cbegin()->first; } + // Add an event to the scheduler. Assumes this event doesn't already exist in the scheduler. + // (If it might, then use rescheduleEvent instead, which will remove and reschedule the event) void addEvent(EventType type, u64 timestamp) { events.emplace(timestamp, type); updateNextTimestamp(); @@ -46,6 +48,47 @@ struct Scheduler { } }; + // Reschedule an event of "type" to "newTimestamp". + // If the event is already in the scheduler, replace its timestamp with the new timestamp + // If possible, it will perform an in-place replacement. Otherwise, it will fallback to a remove+insert operation. + // If the event is not in the scheduler, we'll add it + void rescheduleEvent(EventType type, u64 newTimestamp) { + // Find the event if it exists + for (auto it = events.begin(); it != events.end(); ++it) { + if (it->second == type) { + bool inplace = true; + + // Peek at the previous and next events to see if we can safely update in-place + if (it != events.begin()) { + auto previousIterator = std::prev(it); + if (newTimestamp < previousIterator->first) { + inplace = false; + } + } + + auto nextIterator = std::next(it); + if (nextIterator != events.end() && newTimestamp > nextIterator->first) { + inplace = false; + } + + if (inplace) { + it->first = newTimestamp; + updateNextTimestamp(); + } else { + EventType ev = it->second; + events.erase(it); + events.emplace(newTimestamp, ev); + updateNextTimestamp(); + } + + return; + } + } + + // The event did not exist: Add it to the scheduler + addEvent(type, newTimestamp); + } + void reset() { currentTimestamp = 0; diff --git a/src/core/kernel/threads.cpp b/src/core/kernel/threads.cpp index ce278713..5ada30e3 100644 --- a/src/core/kernel/threads.cpp +++ b/src/core/kernel/threads.cpp @@ -738,8 +738,7 @@ void Kernel::addWakeupEvent(u64 tick) { nextScheduledWakeupTick = tick; auto& scheduler = cpu.getScheduler(); - scheduler.removeEvent(Scheduler::EventType::ThreadWakeup); - scheduler.addEvent(Scheduler::EventType::ThreadWakeup, tick); + scheduler.rescheduleEvent(Scheduler::EventType::ThreadWakeup, tick); } } diff --git a/src/core/kernel/timers.cpp b/src/core/kernel/timers.cpp index 0904b33a..e2a47c2e 100644 --- a/src/core/kernel/timers.cpp +++ b/src/core/kernel/timers.cpp @@ -52,9 +52,7 @@ void Kernel::pollTimers() { } } -void Kernel::cancelTimer(Timer* timer) { - timer->running = false; -} +void Kernel::cancelTimer(Timer* timer) { timer->running = false; } void Kernel::signalTimer(Handle timerHandle, Timer* timer) { timer->fired = true; @@ -115,8 +113,7 @@ void Kernel::svcSetTimer() { Scheduler& scheduler = cpu.getScheduler(); // Signal an event to poll timers as soon as possible - scheduler.removeEvent(Scheduler::EventType::UpdateTimers); - scheduler.addEvent(Scheduler::EventType::UpdateTimers, cpu.getTicks() + 1); + scheduler.rescheduleEvent(Scheduler::EventType::UpdateTimers, cpu.getTicks() + 1); // If the initial delay is 0 then instantly signal the timer if (initial == 0) { diff --git a/src/core/services/ir/circlepad_pro.cpp b/src/core/services/ir/circlepad_pro.cpp index 0ed4d830..d70aa626 100644 --- a/src/core/services/ir/circlepad_pro.cpp +++ b/src/core/services/ir/circlepad_pro.cpp @@ -19,8 +19,7 @@ void CirclePadPro::receivePayload(Payload payload) { // Convert to cycles period = Scheduler::nsToCycles(periodNs); - scheduler.removeEvent(Scheduler::EventType::UpdateIR); - scheduler.addEvent(Scheduler::EventType::UpdateIR, scheduler.currentTimestamp + period); + scheduler.rescheduleEvent(Scheduler::EventType::UpdateIR, scheduler.currentTimestamp + period); break; } diff --git a/src/core/services/y2r.cpp b/src/core/services/y2r.cpp index c864728b..93f192be 100644 --- a/src/core/services/y2r.cpp +++ b/src/core/services/y2r.cpp @@ -447,8 +447,7 @@ void Y2RService::startConversion(u32 messagePointer) { // Remove any potential pending Y2R event and schedule a new one Scheduler& scheduler = kernel.getScheduler(); - scheduler.removeEvent(Scheduler::EventType::SignalY2R); - scheduler.addEvent(Scheduler::EventType::SignalY2R, scheduler.currentTimestamp + delayTicks); + scheduler.rescheduleEvent(Scheduler::EventType::SignalY2R, scheduler.currentTimestamp + delayTicks); } void Y2RService::isFinishedSendingYUV(u32 messagePointer) { diff --git a/third_party/capstone b/third_party/capstone index eb4fc2d7..8b0f54b1 160000 --- a/third_party/capstone +++ b/third_party/capstone @@ -1 +1 @@ -Subproject commit eb4fc2d7612db10379adf7aeb287a7923dcc0fc7 +Subproject commit 8b0f54b1ff88f636a9c40bb2cce74408b13bc0c7 diff --git a/third_party/host_memory/host_memory.cpp b/third_party/host_memory/host_memory.cpp index e7f08192..29c24d39 100644 --- a/third_party/host_memory/host_memory.cpp +++ b/third_party/host_memory/host_memory.cpp @@ -481,7 +481,7 @@ namespace Common { long page_size = sysconf(_SC_PAGESIZE); if (page_size != 0x1000) { - Helpers::warn("page size {:#x} is incompatible with 4K paging", page_size); + Helpers::warn("Page size %X is incompatible with 4K paging", page_size); throw std::bad_alloc{}; }