How to understand atomics in a freestanding C or C++ implementation?

555 views Asked by At

C11 and C++11 define atomics in terms of threads of execution. Whereas in a hosted environment it is clear what a thread is, it is rather a vague term in a freestanding language implementation.

  1. How to formally understand atomics specified in C11 and C++11 in a freestanding implementation where all threads must be implemented inside the program? For example: is an ISR a separate thread of execution?
  2. Why did the standard committees define atomics in terms of threads and not simply in the domain of code ordering?
  3. Are there any embedded compilers already supporting C11/C++11 atomics besides gcc?
2

There are 2 answers

4
Pete Becker On BEST ANSWER

My somewhat mechanistic (and somewhat handwaving) approach to this kind of question is that atomics guarantee three things: reads and writes won't get torn by a context switch (so you only see values that were actually stored in the variable); caches get flushed (so you don't see stale values); and the compiler can't move instructions across an atomic operation (so operations that occur logically before an atomic access in fact occur before that access). Note that I've tried to avoid any notion of "thread" here, although it gets a bit labored.

If you're writing your own threading mechanism, these properties are obviously important. They are orthogonal to the details of the threading mechanism that you're using.

For signal handlers, they give you a place to stand when you need to examine values from the code executed in the signal handler and when the signal handler needs to modify values that the rest of the program cares about.

I'm not sure whether the standard formally addresses ISR's (pretty sure it doesn't), but from this mechanistic perspective, an ISR is no different from a signal that doesn't come from a call to raise. It's just an asynchronous function call, and it occupies stack space that it gets from the thread that gets interrupted. It's definitely not a thread; it's a parasite on an existing thread. So for an ISR I'd go with the guarantees for signals rather than the guarantees for threads.

0
Jens Gustedt On

Atomics are to deal with race conditions, so without threads they make almost no sense. The only other context where races may occur are with signal handlers, and there the C standard offers the concept of lock-freeness.

Seen like that there is no difference between freestanding and hosted environments. Threads and atomics are optional features, and if a freestanding environment supports both, it must comply to the specification of both. If it only supports atomics, it can provide lock-free atomic types for signal handlers, but the other atomic types then are useless.