Member-only story
Guaranteeing Atomic 64-Bit Loads on 32-Bit ARM Cores in C Without Inline Assembly
Introduction
Atomic operations are critical in concurrent programming, ensuring that certain operations on shared data are performed without interference from other threads or processes. On 32-bit ARM architectures, handling 64-bit data atomically poses a unique challenge because the architecture natively operates on 32-bit words. A 64-bit load or store operation cannot be guaranteed to be atomic on a 32-bit system without special considerations, as it typically requires two separate 32-bit operations that could be interrupted.
Historically, developers resorted to inline assembly to enforce atomicity on ARM cores by using specific instructions like LDREXD
and STREXD
(exclusive load and store for doublewords) available on ARM architectures that support them. However, inline assembly is error-prone, less portable, and harder to maintain. Modern C standards and toolchains provide alternatives to achieve atomic operations without resorting to inline assembly. This article explores how to guarantee atomic 64-bit loads on 32-bit ARM cores using standard C constructs, focusing on the C11 atomic operations library, compiler-specific intrinsics, and other techniques, while discussing their implementation details, limitations, and best practices.