explicit list field to simplify code navigation
This commit is contained in:
parent
ee674dc979
commit
aa4967383a
|
@ -91,7 +91,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Ignition scheduler maintains a linked list of all pending ignition events.
|
* Ignition scheduler maintains a linked list of all pending ignition events.
|
||||||
*/
|
*/
|
||||||
IgnitionEvent *next = nullptr;
|
IgnitionEvent *nextIgnitionEvent = nullptr;
|
||||||
/**
|
/**
|
||||||
* Sequential number of currently processed spark event
|
* Sequential number of currently processed spark event
|
||||||
* @see globalSparkIdCounter
|
* @see globalSparkIdCounter
|
||||||
|
|
|
@ -30,7 +30,7 @@ EventQueue::EventQueue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EventQueue::checkIfPending(scheduling_s *scheduling) {
|
bool EventQueue::checkIfPending(scheduling_s *scheduling) {
|
||||||
return assertNotInList<scheduling_s>(head, scheduling);
|
assertNotInListMethodBody(scheduling_s, head, scheduling, nextScheduling_s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,7 +63,7 @@ bool EventQueue::insertTask(scheduling_s *scheduling, efitime_t timeX, schfunc_t
|
||||||
|
|
||||||
if (head == NULL || timeX < head->momentX) {
|
if (head == NULL || timeX < head->momentX) {
|
||||||
// here we insert into head of the linked list
|
// here we insert into head of the linked list
|
||||||
LL_PREPEND(head, scheduling);
|
LL_PREPEND2(head, scheduling, nextScheduling_s);
|
||||||
#if EFI_UNIT_TEST
|
#if EFI_UNIT_TEST
|
||||||
assertListIsSorted();
|
assertListIsSorted();
|
||||||
#endif /* EFI_UNIT_TEST */
|
#endif /* EFI_UNIT_TEST */
|
||||||
|
@ -71,12 +71,12 @@ bool EventQueue::insertTask(scheduling_s *scheduling, efitime_t timeX, schfunc_t
|
||||||
} else {
|
} else {
|
||||||
// here we know we are not in the head of the list, let's find the position - linear search
|
// here we know we are not in the head of the list, let's find the position - linear search
|
||||||
scheduling_s *insertPosition = head;
|
scheduling_s *insertPosition = head;
|
||||||
while (insertPosition->next != NULL && insertPosition->next->momentX < timeX) {
|
while (insertPosition->nextScheduling_s != NULL && insertPosition->nextScheduling_s->momentX < timeX) {
|
||||||
insertPosition = insertPosition->next;
|
insertPosition = insertPosition->nextScheduling_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduling->next = insertPosition->next;
|
scheduling->nextScheduling_s = insertPosition->nextScheduling_s;
|
||||||
insertPosition->next = scheduling;
|
insertPosition->nextScheduling_s = scheduling;
|
||||||
#if EFI_UNIT_TEST
|
#if EFI_UNIT_TEST
|
||||||
assertListIsSorted();
|
assertListIsSorted();
|
||||||
#endif /* EFI_UNIT_TEST */
|
#endif /* EFI_UNIT_TEST */
|
||||||
|
@ -132,7 +132,7 @@ int EventQueue::executeAll(efitime_t now) {
|
||||||
int listIterationCounter = 0;
|
int listIterationCounter = 0;
|
||||||
int executionCounter = 0;
|
int executionCounter = 0;
|
||||||
// we need safe iteration because we are removing elements inside the loop
|
// we need safe iteration because we are removing elements inside the loop
|
||||||
LL_FOREACH_SAFE(head, current, tmp)
|
LL_FOREACH_SAFE2(head, current, tmp, nextScheduling_s)
|
||||||
{
|
{
|
||||||
efiAssert(CUSTOM_ERR_ASSERT, current->callback != NULL, "callback==null1", 0);
|
efiAssert(CUSTOM_ERR_ASSERT, current->callback != NULL, "callback==null1", 0);
|
||||||
if (++listIterationCounter > QUEUE_LENGTH_LIMIT) {
|
if (++listIterationCounter > QUEUE_LENGTH_LIMIT) {
|
||||||
|
@ -143,14 +143,14 @@ int EventQueue::executeAll(efitime_t now) {
|
||||||
executionCounter++;
|
executionCounter++;
|
||||||
efiAssert(CUSTOM_ERR_ASSERT, head == current, "removing from head", -1);
|
efiAssert(CUSTOM_ERR_ASSERT, head == current, "removing from head", -1);
|
||||||
//LL_DELETE(head, current);
|
//LL_DELETE(head, current);
|
||||||
head = head->next;
|
head = head->nextScheduling_s;
|
||||||
if (executionList == NULL) {
|
if (executionList == NULL) {
|
||||||
lastInExecutionList = executionList = current;
|
lastInExecutionList = executionList = current;
|
||||||
} else {
|
} else {
|
||||||
lastInExecutionList->next = current;
|
lastInExecutionList->nextScheduling_s = current;
|
||||||
lastInExecutionList = current;
|
lastInExecutionList = current;
|
||||||
}
|
}
|
||||||
current->next = nullptr;
|
current->nextScheduling_s = nullptr;
|
||||||
} else {
|
} else {
|
||||||
/**
|
/**
|
||||||
* The list is sorted. Once we find one action in the future, all the remaining ones
|
* The list is sorted. Once we find one action in the future, all the remaining ones
|
||||||
|
@ -167,7 +167,7 @@ int EventQueue::executeAll(efitime_t now) {
|
||||||
* we need safe iteration here because 'callback' might change change 'current->next'
|
* we need safe iteration here because 'callback' might change change 'current->next'
|
||||||
* while re-inserting it into the queue from within the callback
|
* while re-inserting it into the queue from within the callback
|
||||||
*/
|
*/
|
||||||
LL_FOREACH_SAFE(executionList, current, tmp)
|
LL_FOREACH_SAFE2(executionList, current, tmp, nextScheduling_s)
|
||||||
{
|
{
|
||||||
efiAssert(CUSTOM_ERR_ASSERT, current->callback != NULL, "callback==null2", 0);
|
efiAssert(CUSTOM_ERR_ASSERT, current->callback != NULL, "callback==null2", 0);
|
||||||
uint32_t before = getTimeNowLowerNt();
|
uint32_t before = getTimeNowLowerNt();
|
||||||
|
@ -198,16 +198,16 @@ int EventQueue::executeAll(efitime_t now) {
|
||||||
int EventQueue::size(void) const {
|
int EventQueue::size(void) const {
|
||||||
scheduling_s *tmp;
|
scheduling_s *tmp;
|
||||||
int result;
|
int result;
|
||||||
LL_COUNT(head, tmp, result);
|
LL_COUNT2(head, tmp, result, nextScheduling_s);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if EFI_UNIT_TEST
|
#if EFI_UNIT_TEST
|
||||||
void EventQueue::assertListIsSorted() const {
|
void EventQueue::assertListIsSorted() const {
|
||||||
scheduling_s *current = head;
|
scheduling_s *current = head;
|
||||||
while (current != NULL && current->next != NULL) {
|
while (current != NULL && current->nextScheduling_s != NULL) {
|
||||||
efiAssertVoid(CUSTOM_ERR_6623, current->momentX <= current->next->momentX, "list order");
|
efiAssertVoid(CUSTOM_ERR_6623, current->momentX <= current->nextScheduling_s->momentX, "list order");
|
||||||
current = current->next;
|
current = current->nextScheduling_s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -223,7 +223,7 @@ scheduling_s * EventQueue::getHead() {
|
||||||
scheduling_s *EventQueue::getForUnitText(int index) {
|
scheduling_s *EventQueue::getForUnitText(int index) {
|
||||||
scheduling_s * current;
|
scheduling_s * current;
|
||||||
|
|
||||||
LL_FOREACH(head, current)
|
LL_FOREACH2(head, current, nextScheduling_s)
|
||||||
{
|
{
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
return current;
|
return current;
|
||||||
|
|
|
@ -18,29 +18,28 @@
|
||||||
|
|
||||||
#define QUEUE_LENGTH_LIMIT 1000
|
#define QUEUE_LENGTH_LIMIT 1000
|
||||||
|
|
||||||
template<typename T>
|
// templates do not accept field names so we use a macro here
|
||||||
bool assertNotInList(T *head, T*element) {
|
#define assertNotInListMethodBody(T, head, element, field) \
|
||||||
// this code is just to validate state, no functional load
|
/* this code is just to validate state, no functional load*/ \
|
||||||
T * current;
|
T * current; \
|
||||||
int counter = 0;
|
int counter = 0; \
|
||||||
LL_FOREACH(head, current)
|
LL_FOREACH2(head, current, field) { \
|
||||||
{
|
if (++counter > QUEUE_LENGTH_LIMIT) { \
|
||||||
if (++counter > QUEUE_LENGTH_LIMIT) {
|
firmwareError(CUSTOM_ERR_LOOPED_QUEUE, "Looped queue?"); \
|
||||||
firmwareError(CUSTOM_ERR_LOOPED_QUEUE, "Looped queue?");
|
return false; \
|
||||||
|
} \
|
||||||
|
if (current == element) { \
|
||||||
|
/** \
|
||||||
|
* for example, this might happen in case of sudden RPM change if event \
|
||||||
|
* was not scheduled by angle but was scheduled by time. In case of scheduling \
|
||||||
|
* by time with slow RPM the whole next fast revolution might be within the wait period \
|
||||||
|
*/ \
|
||||||
|
warning(CUSTOM_RE_ADDING_INTO_EXECUTION_QUEUE, "re-adding element into event_queue"); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
if (current == element) {
|
|
||||||
/**
|
|
||||||
* for example, this might happen in case of sudden RPM change if event
|
|
||||||
* was not scheduled by angle but was scheduled by time. In case of scheduling
|
|
||||||
* by time with slow RPM the whole next fast revolution might be within the wait period
|
|
||||||
*/
|
|
||||||
warning(CUSTOM_RE_ADDING_INTO_EXECUTION_QUEUE, "re-adding element into event_queue");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execution sorted linked list
|
* Execution sorted linked list
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Scheduler implementation uses a sorted linked list of these scheduling records.
|
* Scheduler implementation uses a sorted linked list of these scheduling records.
|
||||||
*/
|
*/
|
||||||
scheduling_s *next = nullptr;
|
scheduling_s *nextScheduling_s = nullptr;
|
||||||
|
|
||||||
schfunc_t callback = nullptr;
|
schfunc_t callback = nullptr;
|
||||||
void *param = nullptr;
|
void *param = nullptr;
|
||||||
|
|
|
@ -215,6 +215,10 @@ void turnSparkPinHigh(IgnitionEvent *event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool assertNotInIgnitionList(IgnitionEvent *head, IgnitionEvent *element) {
|
||||||
|
assertNotInListMethodBody(IgnitionEvent, head, element, nextIgnitionEvent)
|
||||||
|
}
|
||||||
|
|
||||||
static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventIndex, IgnitionEvent *iEvent,
|
static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventIndex, IgnitionEvent *iEvent,
|
||||||
int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
int rpm DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
|
|
||||||
|
@ -315,7 +319,7 @@ static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventI
|
||||||
/**
|
/**
|
||||||
* Spark should be scheduled in relation to some future trigger event, this way we get better firing precision
|
* Spark should be scheduled in relation to some future trigger event, this way we get better firing precision
|
||||||
*/
|
*/
|
||||||
bool isPending = assertNotInList<IgnitionEvent>(ENGINE(ignitionEventsHead), iEvent);
|
bool isPending = assertNotInIgnitionList(ENGINE(ignitionEventsHead), iEvent);
|
||||||
if (isPending) {
|
if (isPending) {
|
||||||
#if SPARK_EXTREME_LOGGING
|
#if SPARK_EXTREME_LOGGING
|
||||||
scheduleMsg(logger, "not adding to queue sparkDown ind=%d %d %s %d", trgEventIndex, getRevolutionCounter(), iEvent->getOutputForLoggins()->name, (int)getTimeNowUs());
|
scheduleMsg(logger, "not adding to queue sparkDown ind=%d %d %s %d", trgEventIndex, getRevolutionCounter(), iEvent->getOutputForLoggins()->name, (int)getTimeNowUs());
|
||||||
|
@ -323,7 +327,7 @@ static ALWAYS_INLINE void handleSparkEvent(bool limitedSpark, uint32_t trgEventI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LL_APPEND(ENGINE(ignitionEventsHead), iEvent);
|
LL_APPEND2(ENGINE(ignitionEventsHead), iEvent, nextIgnitionEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,11 +387,11 @@ static ALWAYS_INLINE void prepareIgnitionSchedule(DECLARE_ENGINE_PARAMETER_SIGNA
|
||||||
static void scheduleAllSparkEventsUntilNextTriggerTooth(uint32_t trgEventIndex DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
static void scheduleAllSparkEventsUntilNextTriggerTooth(uint32_t trgEventIndex DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
IgnitionEvent *current, *tmp;
|
IgnitionEvent *current, *tmp;
|
||||||
|
|
||||||
LL_FOREACH_SAFE(ENGINE(ignitionEventsHead), current, tmp)
|
LL_FOREACH_SAFE2(ENGINE(ignitionEventsHead), current, tmp, nextIgnitionEvent)
|
||||||
{
|
{
|
||||||
if (current->sparkPosition.triggerEventIndex == trgEventIndex) {
|
if (current->sparkPosition.triggerEventIndex == trgEventIndex) {
|
||||||
// time to fire a spark which was scheduled previously
|
// time to fire a spark which was scheduled previously
|
||||||
LL_DELETE(ENGINE(ignitionEventsHead), current);
|
LL_DELETE2(ENGINE(ignitionEventsHead), current, nextIgnitionEvent);
|
||||||
|
|
||||||
scheduling_s * sDown = ¤t->signalTimerDown;
|
scheduling_s * sDown = ¤t->signalTimerDown;
|
||||||
|
|
||||||
|
|
|
@ -108,9 +108,9 @@ TEST(misc, testSignalExecutor) {
|
||||||
|
|
||||||
ASSERT_EQ(4, eq.size());
|
ASSERT_EQ(4, eq.size());
|
||||||
ASSERT_EQ(10, eq.getHead()->momentX);
|
ASSERT_EQ(10, eq.getHead()->momentX);
|
||||||
ASSERT_EQ(10, eq.getHead()->next->momentX);
|
ASSERT_EQ(10, eq.getHead()->nextScheduling_s->momentX);
|
||||||
ASSERT_EQ(11, eq.getHead()->next->next->momentX);
|
ASSERT_EQ(11, eq.getHead()->nextScheduling_s->nextScheduling_s->momentX);
|
||||||
ASSERT_EQ(12, eq.getHead()->next->next->next->momentX);
|
ASSERT_EQ(12, eq.getHead()->nextScheduling_s->nextScheduling_s->nextScheduling_s->momentX);
|
||||||
|
|
||||||
callbackCounter = 0;
|
callbackCounter = 0;
|
||||||
eq.executeAll(10);
|
eq.executeAll(10);
|
||||||
|
|
Loading…
Reference in New Issue