Zig’s std documentation defines six memory orders, but currently, there is no detailed explanation available.
Unordered
Monotonic
Acquire
Release
AcqRel
SeqCst
I guess that the last four might be similar to the following in C++.
memory_order_acquire
memory_order_release
memory_order_acq_rel
memory_order_seq_cst
But what does the Monotonic
mean? It doesn’t seem like memory_order_consume
.
Reference
It follows LLVM’s atomic instructions: Monotonic
In C++ would be memory_order_relaxed
In Rust it would be Relaxed
Monotonic is the weakest level of atomicity that can be used in synchronization primitives, although it does not provide any general synchronization. It essentially guarantees that if you take all the operations affecting a specific address, a consistent ordering exists.
Relevant standard
This corresponds to the C++11/C11 memory_order_relaxed
; see those standards for the exact definition.
Notes for frontends
If you are writing a frontend which uses this directly, use with caution. The guarantees in terms of synchronization are very weak, so make sure these are only used in a pattern which you know is correct. Generally, these would either be used for atomic operations which do not protect other memory (like an atomic counter), or along with a fence
.
Notes for optimizers
In terms of the optimizer, this can be treated as a read+write on the relevant memory location (and alias analysis will take advantage of that). In addition, it is legal to reorder non-atomic and Unordered loads around Monotonic loads. CSE/DSE and a few other optimizations are allowed, but Monotonic operations are unlikely to be used in ways which would make those optimizations useful.
Notes for code generation
Code generation is essentially the same as that for unordered for loads and stores. No fences are required. cmpxchg
and atomicrmw
are required to appear as a single operation.
5 Likes