diff --git a/firmware/controllers/system/timer/event_queue.cpp b/firmware/controllers/system/timer/event_queue.cpp index e277e8a647..6bec890af4 100644 --- a/firmware/controllers/system/timer/event_queue.cpp +++ b/firmware/controllers/system/timer/event_queue.cpp @@ -24,11 +24,6 @@ extern bool verboseMode; uint32_t maxSchedulingPrecisionLoss = 0; -EventQueue::EventQueue() { - head = nullptr; - setLateDelay(100); -} - bool EventQueue::checkIfPending(scheduling_s *scheduling) { assertNotInListMethodBody(scheduling_s, head, scheduling, nextScheduling_s); } @@ -100,10 +95,8 @@ efitime_t EventQueue::getNextEventTime(efitime_t nowX) const { * * looks like we end up here after 'writeconfig' (which freezes the firmware) - we are late * for the next scheduled event - * */ - efitime_t aBitInTheFuture = nowX + lateDelay; - return aBitInTheFuture; + return nowX + lateDelay; } else { return head->momentX; } @@ -139,13 +132,20 @@ int EventQueue::executeAll(efitime_t now) { break; } - // Only execute events that occured in the past. - // The list is sorted, so as soon as we see an event - // in the future, we're done. - if (current->momentX > now) { + // If the next event is far in the future, we'll reschedule + // and execute it next time. + // We do this when the next event is close enough that the overhead of + // resetting the timer and scheduling an new interrupt is greater than just + // waiting for the time to arrive. On current CPUs, this is reasonable to set + // around 10 microseconds. + if (current->momentX > now + lateDelay) { break; } + // near future - spin wait for the event to happen and avoid the + // overhead of rescheduling the timer. + while (current->momentX > getTimeNowNt()) ; + executionCounter++; // step the head forward, unlink this element, clear scheduled flag @@ -187,10 +187,6 @@ void EventQueue::assertListIsSorted() const { } } -void EventQueue::setLateDelay(int value) { - lateDelay = value; -} - scheduling_s * EventQueue::getHead() { return head; } diff --git a/firmware/controllers/system/timer/event_queue.h b/firmware/controllers/system/timer/event_queue.h index 421e7dac01..ffda221811 100644 --- a/firmware/controllers/system/timer/event_queue.h +++ b/firmware/controllers/system/timer/event_queue.h @@ -45,7 +45,10 @@ */ class EventQueue { public: - EventQueue(); + // See comment in EventQueue::executeAll for info about lateDelay - it sets the + // time gap between events for which we will wait instead of rescheduling the next + // event in a group of events near one another. + EventQueue(efitime_t lateDelay = 0) : lateDelay(lateDelay) {} /** * O(size) - linear search in sorted linked list @@ -58,7 +61,6 @@ public: void clear(void); int size(void) const; scheduling_s *getElementAtIndexForUnitText(int index); - void setLateDelay(int value); scheduling_s * getHead(); void assertListIsSorted() const; private: @@ -66,7 +68,7 @@ private: /** * this list is sorted */ - scheduling_s *head; - efitime_t lateDelay; + scheduling_s *head = nullptr; + const efitime_t lateDelay; }; diff --git a/firmware/controllers/system/timer/single_timer_executor.cpp b/firmware/controllers/system/timer/single_timer_executor.cpp index 2b088c99c3..89a99dfbc3 100644 --- a/firmware/controllers/system/timer/single_timer_executor.cpp +++ b/firmware/controllers/system/timer/single_timer_executor.cpp @@ -49,12 +49,10 @@ void globalTimerCallback() { ___engine.executor.onTimerCallback(); } -SingleTimerExecutor::SingleTimerExecutor() { - /** - * See comments in "getNextEventTime" - * 10us is roughly double the cost of the interrupt + overhead of a single timer event - */ - queue.setLateDelay(US2NT(10)); +SingleTimerExecutor::SingleTimerExecutor() + // 10us is roughly double the cost of the interrupt + overhead of a single timer event + : queue(US2NT(10)) +{ } void SingleTimerExecutor::scheduleForLater(scheduling_s *scheduling, int delayUs, action_s action) {