diff --git a/src/main/scheduler/scheduler.c b/src/main/scheduler/scheduler.c index a2e24de9c0..fc18976160 100644 --- a/src/main/scheduler/scheduler.c +++ b/src/main/scheduler/scheduler.c @@ -92,6 +92,8 @@ static FAST_DATA_ZERO_INIT bool gyroEnabled; static int32_t desiredPeriodCycles; static uint32_t lastTargetCycles; +static uint8_t skippedRxAttempts = 0; + #if defined(USE_LATE_TASK_STATISTICS) static int16_t lateTaskCount = 0; static uint32_t lateTaskTotal = 0; @@ -569,8 +571,8 @@ FAST_CODE void scheduler(void) if (task->attr->checkFunc) { // Increase priority for event driven tasks if (task->dynamicPriority > 0) { - task->taskAgeCycles = 1 + (cmpTimeUs(currentTimeUs, task->lastSignaledAtUs) / task->attr->desiredPeriodUs); - task->dynamicPriority = 1 + task->attr->staticPriority * task->taskAgeCycles; + task->taskAgePeriods = 1 + (cmpTimeUs(currentTimeUs, task->lastSignaledAtUs) / task->attr->desiredPeriodUs); + task->dynamicPriority = 1 + task->attr->staticPriority * task->taskAgePeriods; } else if (task->attr->checkFunc(currentTimeUs, cmpTimeUs(currentTimeUs, task->lastExecutedAtUs))) { const uint32_t checkFuncExecutionTimeUs = cmpTimeUs(micros(), currentTimeUs); #if !defined(UNIT_TEST) @@ -581,17 +583,17 @@ FAST_CODE void scheduler(void) checkFuncTotalExecutionTimeUs += checkFuncExecutionTimeUs; // time consumed by scheduler + task checkFuncMaxExecutionTimeUs = MAX(checkFuncMaxExecutionTimeUs, checkFuncExecutionTimeUs); task->lastSignaledAtUs = currentTimeUs; - task->taskAgeCycles = 1; + task->taskAgePeriods = 1; task->dynamicPriority = 1 + task->attr->staticPriority; } else { - task->taskAgeCycles = 0; + task->taskAgePeriods = 0; } } else { // Task is time-driven, dynamicPriority is last execution age (measured in desiredPeriods) // Task age is calculated from last execution - task->taskAgeCycles = (cmpTimeUs(currentTimeUs, task->lastExecutedAtUs) / task->attr->desiredPeriodUs); - if (task->taskAgeCycles > 0) { - task->dynamicPriority = 1 + task->attr->staticPriority * task->taskAgeCycles; + task->taskAgePeriods = (cmpTimeUs(currentTimeUs, task->lastExecutedAtUs) / task->attr->desiredPeriodUs); + if (task->taskAgePeriods > 0) { + task->dynamicPriority = 1 + task->attr->staticPriority * task->taskAgePeriods; } } @@ -633,6 +635,10 @@ FAST_CODE void scheduler(void) } #endif // USE_LATE_TASK_STATISTICS + if ((currentTask - tasks) == TASK_RX) { + skippedRxAttempts = 0; + } + if ((cyclesOverdue > 0) || (-cyclesOverdue < taskGuardMinCycles)) { if (taskGuardCycles < taskGuardMaxCycles) { taskGuardCycles += taskGuardDeltaUpCycles; @@ -643,7 +649,8 @@ FAST_CODE void scheduler(void) #if defined(USE_LATE_TASK_STATISTICS) taskCount++; #endif // USE_LATE_TASK_STATISTICS - } else if (selectedTask->taskAgeCycles > TASK_AGE_EXPEDITE_COUNT) { + } else if ((selectedTask->taskAgePeriods > TASK_AGE_EXPEDITE_COUNT) || + (((selectedTask - tasks) == TASK_RX) && (++skippedRxAttempts > TASK_AGE_EXPEDITE_RX))) { // If a task has been unable to run, then reduce it's recorded estimated run time to ensure // it's ultimate scheduling selectedTask->anticipatedExecutionTime *= TASK_AGE_EXPEDITE_SCALE; diff --git a/src/main/scheduler/scheduler.h b/src/main/scheduler/scheduler.h index 66330822ee..b3678649b3 100644 --- a/src/main/scheduler/scheduler.h +++ b/src/main/scheduler/scheduler.h @@ -47,6 +47,7 @@ // Decay the estimated max task duration by 1/(1 << TASK_EXEC_TIME_SHIFT) on every invocation #define TASK_EXEC_TIME_SHIFT 7 +#define TASK_AGE_EXPEDITE_RX 25 // Make RX tasks more schedulable if it's failed to be scheduled this many times #define TASK_AGE_EXPEDITE_COUNT 1 // Make aged tasks more schedulable #define TASK_AGE_EXPEDITE_SCALE 0.9 // By scaling their expected execution time @@ -197,7 +198,7 @@ typedef struct { // Scheduling uint16_t dynamicPriority; // measurement of how old task was last executed, used to avoid task starvation - uint16_t taskAgeCycles; + uint16_t taskAgePeriods; timeDelta_t taskLatestDeltaTimeUs; timeUs_t lastExecutedAtUs; // last time of invocation timeUs_t lastSignaledAtUs; // time of invocation event for event-driven tasks diff --git a/src/test/unit/scheduler_unittest.cc b/src/test/unit/scheduler_unittest.cc index 172a0f73cb..bc20c0ce48 100644 --- a/src/test/unit/scheduler_unittest.cc +++ b/src/test/unit/scheduler_unittest.cc @@ -396,7 +396,7 @@ TEST(SchedulerUnittest, TestTwoTasks) simulatedTime = startTime; tasks[TASK_ACCEL].lastExecutedAtUs = simulatedTime; tasks[TASK_ATTITUDE].lastExecutedAtUs = tasks[TASK_ACCEL].lastExecutedAtUs - TEST_UPDATE_ATTITUDE_TIME; - EXPECT_EQ(0, tasks[TASK_ATTITUDE].taskAgeCycles); + EXPECT_EQ(0, tasks[TASK_ATTITUDE].taskAgePeriods); // run the scheduler scheduler(); // no tasks should have run, since neither task's desired time has elapsed