Repository navigation
hal: access 64-bit pin values with relaxed atomics - #4683
Open
grandixximo wants to merge 1 commit into
Open
grandixximo wants to merge 1 commit into
grandixximo wants to merge 1 commit into
Conversation
BsAtHome
reviewed
Oct 15, 2026
grandixximo
force-pushed
the
hal-atomic-accessors
branch
from
October 15, 2026 11:43
b71de81 to
c836fff
Compare
Contributor
|
And you have a conflict after the include change |
BsAtHome
reviewed
Oct 15, 2026
Since the move to 64-bit HAL types every integer pin is 64 bits wide. On 32-bit targets the plain volatile accessors compile to two 32-bit accesses (two movl on i386), so a reader in another thread can see half of a write: at a zero crossing the value is off by 2^32. A test with one thread toggling a sint pin between -1 and 0 and another reading it sees millions of torn values per second on i386, and still about 30 per second pinned to one CPU. A real path is a userspace jog wheel (e.g. shuttle) writing counts that the servo thread reads as joint.N.jog-counts. Use __atomic_load_n/__atomic_store_n (__atomic_load/__atomic_store for real) with __ATOMIC_RELAXED in the getters and setters. On amd64 and arm64 this compiles to the same single loads and stores as before; on i386 it is fildq/fistpq and on ARMv7 ldrexd/strexd. The same test sees no torn values. This also makes real pins atomic on ARMv7, where vldr/vstr were not guaranteed to be. Without lock-free 64-bit atomics the compiler falls back to libatomic, whose locks are process-local and do not protect HAL shared memory, so configure now fails on such targets (e.g. i486, ARM before ARMv6K), as requested by Bertho Stultiens in LinuxCNC#4614.
grandixximo
force-pushed
the
hal-atomic-accessors
branch
from
October 15, 2026 12:33
c836fff to
ade5539
Compare
Contributor
Author
|
Rebased onto the include move; the change is now in |
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.
Follow-up to the discussion in #4614.
Since #4565 every HAL integer pin is 64 bits wide. On 32-bit targets the plain volatile accessors compile to two 32-bit accesses (two
movlon i386), so a reader in another thread can see half of a write; at a zero crossing that is a value off by 2^32. With one thread toggling a sint pin between -1 and 0 and another reading it, i386 shows millions of torn reads per second, and about 30 per second even pinned to one CPU. A real path is a userspace jog wheel such asshuttlewriting counts that the servo thread reads asjoint.N.jog-counts.This PR:
__atomic_load_n/__atomic_store_n(__atomic_load/__atomic_storefor real) with__ATOMIC_RELAXEDin thehal.hgetters and setters. On amd64 and arm64 the generated code is the same single load or store as before. On i386 it isfildq/fistpq, on ARMv7ldrexd/strexd. The same test sees no torn values. Real pins become atomic on ARMv7 too.Tested in my fork together with the 32-bit CI job from #4682: rip-and-test 340/340, i386 and armhf 333/333.