On Thu, Mar 10, 2022 at 09:05:54AM +0000, Visa Hankala wrote:

Hello Visa,

> In general, atomic_* functions have not provided implicit memory
> barriers on OpenBSD.

I've used atomics fairly extensively in other settings. Forgive me if I'm
explaining the obvious, but I had a devil of a job making sense of this
stuff a few years back, and so perhaps others might find it useful to expand
on this point.

Quick background: modern CPUs come in two main flavours, weakly ordered
(e.g. most Arm systems) and strongly ordered (e.g. x86), which determine the
rules of when multiple cores can see the reads/writes of other cores. Weakly
ordered systems can move/optimise loads/stores around more than strongly
ordered systems (so code that seems to work fine on x86 can then fail on
Arm).

There are in a sense two "safe" ways to use atomics: to assume that each
atomic is isolated and that reading/writing to it tells you nothing about any
other location in memory; or that every atomic is fully ordered with respect
to every other atomic (i.e. no reorderings of atomic operations are allowed).
The former is fast but (without additional operations) can't even express
a mutex safely. The latter doesn't have very good performance.

C11 thus allows you to do various atomic operations with different memory
orderings [1] so that you can choose on a case-by-case basis what you're
prepared to tolerate. "relaxed" is the most efficient but has the least
guarantees; "seq_cst" is the least efficient but has the most guarantees.

I would be very nervous about adding further atomic functions (as in the
original diff) to OpenBSD that don't allow the user to specify what ordering
they want: it's impossible to pick a memory ordering that suits all use
cases. For example, neither READ_ONCE nor the existing atomic_* instructions
define an ordering: I suppose I'd have to to assume they're relaxed. I worry
that people might assume these atomic operations provide greater guarantees
than they actually do.

Fortunately since, AFAICT, we already use C11 (or C17?!) for base, and LLVM
includes all of the relevant functions (e.g. the compare_exchange family
[2]) I don't think we need to add any functions of our own? It might not
even be a bad idea to deprecate the current atomic_* functions in base
and migrate to the C11 alternatives?


Laurie

[1] https://en.cppreference.com/w/c/atomic/memory_order
[2] https://en.cppreference.com/w/c/atomic/atomic_compare_exchange

Reply via email to