Skip to content

SITL: scheduler sleep (#11436) pins averageSystemLoadPercent at 100%+, blocking arming in 9.1 #11710

Description

@sevrugin

Summary

On 9.1, a freshly-defaulted SITL cannot arm. The Configurator's Status tab shows CPU in red, and arming is blocked by ARMING_DISABLED_SYSTEM_OVERLOADED. The machine is not loaded at all — averageSystemLoadPercent is structurally ≥100 in SITL builds since #11436.

Steps to reproduce

  1. Build/run the 9.1 SITL, defaults, UART1+UART2 = MSP, everything else off.
  2. Connect the Configurator → Status tab: CPU is red.
  3. Arming is refused with the system-overload flag.

Cause

averageSystemLoadPercent is a duty-cycle estimator that depends on busy-polling:

averageSystemLoadPercent = 100 * totalWaitingTasks / totalWaitingTasksSamples;

It samples once per scheduler() call and counts how many tasks were already overdue. On hardware, scheduler() spins thousands of times between task deadlines, so the vast majority of samples see zero waiting tasks and the
average stays well under 100.

#11436 (commit 8a47561) made scheduler() sleep until the next task is due:

#if defined(SITL_BUILD)
    if (sitlEarliestNextTaskAt > nowUs + 50) {
        usleep(sleepUs);
    }
#endif

Every zero-waiting sample is now gone. The scheduler runs one task, sleeps until the next is due, and wakes with ≥1 task already overdue — so the average sits at 100%+ permanently, and 200%+ whenever two tasks come due in the
same wake-up (routine: the 1 kHz gyro task alongside the 100 Hz ones). isSystemOverloaded() is averageSystemLoadPercent >= 100, so fc_core.c raises ARMING_DISABLED_SYSTEM_OVERLOADED forever.

The CPU saving in #11436 is real and worth keeping — it's the load metric that no longer means anything once the idle samples are gone.

Suggested fix

Measure actual duty cycle in SITL rather than counting overdue tasks: accumulate task execution time and compare against wall-clock elapsed in the taskSystem() window (load = 100 * busyUs / elapsedUs). That reports something
truthful under both scheduling models. Excluding the CPU-load arming check under SITL_BUILD would unblock arming but leaves the Status tab lying.

Version

9.1.0 (regression from 9.0 — the SITL sleep does not exist there). Reproduced on Linux.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions