2 ms·
> Memory-mapped I/O If you are using volatile to interact with memory-mapped I/O, that means that there is a _thread of execution_ somewhere also interacting w
by fluffything 6y ago
> Memory-mapped I/O
If you are using volatile to interact with memory-mapped I/O, that means that there is a _thread of execution_ somewhere also interacting with that memory - otherwise why are you reading/writing to it? - such that if those reads and writes are not synchronized the program has a data-race and the behavior is undefined.
The claim that this is not a data-race because those threads of execution are "outside my process" is incorrect: the C standard doesn't know about processes. Whether one thread runs in a CPU and writes to a memory mapped DMA region, and the other thread is in your network card reading from that same memory region doesn't matter at all.
The right tool here is a `volatile atomic` load / store.
> - Values changed on other threads on x86 if you just don’t give a damn
If by "don't give a damn" you mean "don't care about UB" then this is correct, because doing that is UB, and UB can do anything.
> Values that are changed in interrupts
From the C standard point-of-view, an interrupt handler suspends a thread of execution, and the handler runs in a different thread of execution. Whether these threads are serialized by the OS or not doesn't matter, reading/writing across threads without synchronization is UB. In particular for interrupt handlers, using volatile to modify memory from an interrupt handler doesn't imply that the thread reading that memory will see the modification (e.g. the compiler might have cached that in a register). Using volatile to read the memory isn't sufficient either, because volatile is not a compiler fence, and it doesn't synchronize-with anything, not even volatile. The right tool here is a `volatile atomic` load / store.
> - longjmp/setjmp
The C standard requires the usage of volatile here, otherwise the behavior is undefined. There is only one thread of execution at play here, so no synchronization is necessary.
Similar control-flow constructs like throwing and catching exceptions do not require the use of volatile here, so the reason one must use volatile here is because longjmp/setjmp is a poorly designed language feature.