What is `std.atomic.Ordering.Monotonic`?

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

Thank you!

1 Like