Conversation
chSysWaitSystemState() polls ch_system.state, which another core writes, but the field is not volatile. The compiler loads it once before the loop and then compares the cached value forever, so a core that arrives before chSysInit() has finished on the other core never leaves. Found on RP2350, where core1 calls it from c1_main(): with its process stack cut from 16 KB to 1 KB, core1 no longer spent long enough in the CRT0 stack fill to arrive after core0, and hung with the kernel state already running.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
chSysWaitSystemState()pollsch_system.state, which another core writes, but the field is not volatile, so the compiler reads it once and then spins on the cached value. A core that calls it before the other core'schSysInit()has finished never leaves. This reads the state through a volatile pointer.Seen in an RP2350 build (gcc 10-2020-q4), where core1 calls it from
c1_main():Found on an RPI_UAVFC after cutting core1's process stack from 16 KB to 1 KB: the board stopped booting. Read over SWD without halting, core1's PC stayed in that loop while
ch_system.statein memory was alreadych_sys_running. The larger stack had been hiding the race, because core1's CRT0 spent long enough filling it that core0 finished first. With this change the same build boots and core1 runs normally.demos/RP/RT-RP2040-PICO/c1_main.ccalls it the same way, so any SMP port whose second core reaches it early enough can hit this. The same fix is also carried in #113.