_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.
_tx_initialize_kernel_enterwaits for the secondary cores to become ready with ado { ... } while (other_core_status != ((ULONG) 0));atcommon_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 atports_smp/linux/gnu/inc/tx_port.h:427, zeroes every one of those slots in aforloop running on core 0, and it is invoked attx_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 toTX_INITIALIZE_IN_PROGRESSduring 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:197inside theTX_REGRESSION_TESTblock, expands inside the loop toother_core_status = other_core_status + _tx_thread_system_state[0]; _tx_thread_system_state[0] = 0;. That folds core 0's ownTX_INITIALIZE_IN_PROGRESSinto the accumulator meant for the other cores, so the first pass cannot exit and the second can. Every SMP regression build definesTX_REGRESSION_TESTintest/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:
136 tests pass either way, and nothing misbehaves: line 171 writes
TX_INITIALIZE_IS_FINISHEDover 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, sincetx_application_defineruns before the clearing at:139and nothing application-controlled runs between the clearing and the loop.Two things might be worth considering, and I have no strong view on which:
TX_PORT_SPECIFIC_MEMORY_SYNCHRONIZATIONbody from theTX_REGRESSION_TESTblock, so the coverage report shows the edge as unreached rather than showing it reached by a mechanism unrelated to what the loop tests.devandmastercarry identical code here, so this is not specific to any one baseline. Line numbers above aredev's. Found while auditing what the regression-test macros contribute to the SMP coverage figure.