Skip to content

The SMP Linux port cannot exercise the kernel-enter core-ready wait loop, and a regression hook masks that in coverage #768

Description

@fdesbiens

_tx_initialize_kernel_enter waits for the secondary cores to become ready with a do { ... } while (other_core_status != ((ULONG) 0)); at common_smp/src/tx_initialize_kernel_enter.c:142-167, summing _tx_thread_system_state[1 .. TX_THREAD_SMP_MAX_CORES-1]. On the Linux SMP port that loop cannot take its loop-back edge. TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION, defined at ports_smp/linux/gnu/inc/tx_port.h:427, zeroes every one of those slots in a for loop running on core 0, and it is invoked at tx_initialize_kernel_enter.c:139 -- three lines before the loop reads them. The accumulator is zero on the first pass, deterministically, with no timing involved.

The clearing is doing real work rather than being incidental. _tx_thread_system_state[1 .. N-1] has only two writers in the tree: _tx_thread_smp_current_state_set, which sets every core to TX_INITIALIZE_IN_PROGRESS during initialization, and this macro. The port's simulated cores never clear their own slots, so without the macro the loop would never exit and the port would not start.

The consequence is in the coverage report rather than in behaviour. TX_PORT_SPECIFIC_MEMORY_SYNCHRONIZATION, defined in the same header at :197 inside the TX_REGRESSION_TEST block, expands inside the loop to other_core_status = other_core_status + _tx_thread_system_state[0]; _tx_thread_system_state[0] = 0;. That folds core 0's own TX_INITIALIZE_IN_PROGRESS into the accumulator meant for the other cores, so the first pass cannot exit and the second can. Every SMP regression build defines TX_REGRESSION_TEST in test/smp/cmake/CMakeLists.txt, so the suite reports both outcomes of that loop as covered.

Measured over the full SMP suite on the Linux port, 136 tests, one kernel enter per test process:

line 167 executions loop-back taken exit taken
macro as the header defines it 270 135 135
macro expanded to nothing 135 0 135

136 tests pass either way, and nothing misbehaves: line 171 writes TX_INITIALIZE_IS_FINISHED over the value the macro already left, so the scheduler is entered in the same state. But a reader of the SMP coverage report would reasonably conclude that the core-ready wait loop is exercised, and on this port it is not and cannot be -- neither by the suite nor by any test that could be added, since tx_application_define runs before the clearing at :139 and nothing application-controlled runs between the clearing and the loop.

Two things might be worth considering, and I have no strong view on which:

  • letting the simulated cores clear their own slots, so the loop performs its intended wait and is exercised for the reason it exists;
  • leaving the port as it is and dropping the TX_PORT_SPECIFIC_MEMORY_SYNCHRONIZATION body from the TX_REGRESSION_TEST block, so the coverage report shows the edge as unreached rather than showing it reached by a mechanism unrelated to what the loop tests.

dev and master carry identical code here, so this is not specific to any one baseline. Line numbers above are dev's. Found while auditing what the regression-test macros contribute to the SMP coverage figure.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions