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.
- 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?
- Why did the standard committees define atomics in terms of threads and not simply in the domain of code ordering?
- Are there any embedded compilers already supporting C11/C++11 atomics besides gcc?
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.