Scheduler: Optimize by adding a proper reschedule function

This commit is contained in:
wheremyfoodat
2025-10-12 02:26:12 +03:00
parent fd90f9a4d0
commit 0b8d8af9c7
5 changed files with 48 additions and 11 deletions

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) {