Merge pull request #812 from wheremyfoodat/scheduler

Scheduler: Optimize by adding a proper reschedule function
This commit is contained in:
wheremyfoodat
2025-10-12 03:02:50 +03:00
committed by GitHub
8 changed files with 53 additions and 16 deletions

6
.gitmodules vendored
View File

@@ -58,9 +58,6 @@
[submodule "third_party/Catch2"] [submodule "third_party/Catch2"]
path = third_party/Catch2 path = third_party/Catch2
url = https://github.com/catchorg/Catch2.git 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"] [submodule "third_party/hips"]
path = third_party/hips path = third_party/hips
url = https://github.com/wheremyfoodat/Hips url = https://github.com/wheremyfoodat/Hips
@@ -80,3 +77,6 @@
path = third_party/SDL2 path = third_party/SDL2
url = https://github.com/libsdl-org/SDL url = https://github.com/libsdl-org/SDL
branch = SDL2 branch = SDL2
[submodule "third_party/capstone"]
path = third_party/capstone
url = https://github.com/Panda3DS-emu/capstone

View File

@@ -29,6 +29,8 @@ struct Scheduler {
// Set nextTimestamp to the timestamp of the next event // Set nextTimestamp to the timestamp of the next event
void updateNextTimestamp() { nextTimestamp = events.cbegin()->first; } 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) { void addEvent(EventType type, u64 timestamp) {
events.emplace(timestamp, type); events.emplace(timestamp, type);
updateNextTimestamp(); 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() { void reset() {
currentTimestamp = 0; currentTimestamp = 0;

View File

@@ -738,8 +738,7 @@ void Kernel::addWakeupEvent(u64 tick) {
nextScheduledWakeupTick = tick; nextScheduledWakeupTick = tick;
auto& scheduler = cpu.getScheduler(); auto& scheduler = cpu.getScheduler();
scheduler.removeEvent(Scheduler::EventType::ThreadWakeup); scheduler.rescheduleEvent(Scheduler::EventType::ThreadWakeup, tick);
scheduler.addEvent(Scheduler::EventType::ThreadWakeup, tick);
} }
} }

View File

@@ -52,9 +52,7 @@ void Kernel::pollTimers() {
} }
} }
void Kernel::cancelTimer(Timer* timer) { void Kernel::cancelTimer(Timer* timer) { timer->running = false; }
timer->running = false;
}
void Kernel::signalTimer(Handle timerHandle, Timer* timer) { void Kernel::signalTimer(Handle timerHandle, Timer* timer) {
timer->fired = true; timer->fired = true;
@@ -115,8 +113,7 @@ void Kernel::svcSetTimer() {
Scheduler& scheduler = cpu.getScheduler(); Scheduler& scheduler = cpu.getScheduler();
// Signal an event to poll timers as soon as possible // Signal an event to poll timers as soon as possible
scheduler.removeEvent(Scheduler::EventType::UpdateTimers); scheduler.rescheduleEvent(Scheduler::EventType::UpdateTimers, cpu.getTicks() + 1);
scheduler.addEvent(Scheduler::EventType::UpdateTimers, cpu.getTicks() + 1);
// If the initial delay is 0 then instantly signal the timer // If the initial delay is 0 then instantly signal the timer
if (initial == 0) { if (initial == 0) {

View File

@@ -19,8 +19,7 @@ void CirclePadPro::receivePayload(Payload payload) {
// Convert to cycles // Convert to cycles
period = Scheduler::nsToCycles(periodNs); period = Scheduler::nsToCycles(periodNs);
scheduler.removeEvent(Scheduler::EventType::UpdateIR); scheduler.rescheduleEvent(Scheduler::EventType::UpdateIR, scheduler.currentTimestamp + period);
scheduler.addEvent(Scheduler::EventType::UpdateIR, scheduler.currentTimestamp + period);
break; break;
} }

View File

@@ -447,8 +447,7 @@ void Y2RService::startConversion(u32 messagePointer) {
// Remove any potential pending Y2R event and schedule a new one // Remove any potential pending Y2R event and schedule a new one
Scheduler& scheduler = kernel.getScheduler(); Scheduler& scheduler = kernel.getScheduler();
scheduler.removeEvent(Scheduler::EventType::SignalY2R); scheduler.rescheduleEvent(Scheduler::EventType::SignalY2R, scheduler.currentTimestamp + delayTicks);
scheduler.addEvent(Scheduler::EventType::SignalY2R, scheduler.currentTimestamp + delayTicks);
} }
void Y2RService::isFinishedSendingYUV(u32 messagePointer) { void Y2RService::isFinishedSendingYUV(u32 messagePointer) {

View File

@@ -481,7 +481,7 @@ namespace Common {
long page_size = sysconf(_SC_PAGESIZE); long page_size = sysconf(_SC_PAGESIZE);
if (page_size != 0x1000) { 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{}; throw std::bad_alloc{};
} }