On 09/02/17 19:49, Bob Paddock wrote:
On Thu, Feb 9, 2017 at 1:13 PM, David Brown <address@hidden> wrote:
So the only solution is to use different parts, such as ARM, with its
Instruction Synchronization Barrier (ISB) [that can waste thousands of
cycles]?
No. That won't help. The compiler can re-arrange "harmless" execution and
calculations around an inline assembly instruction with the "ISB" opcode (or
any similar opcode), even if the inline assembly is marked "volatile". Given
"isb(); x = a/b; isb(); return x;" the compiler is free to order the division
before or after either of these isb() calls, if the compiler knows that the
isb() function/macro/inline assembly does not affect the results of the
calculation.
In C, the only things that can be ordered are /visible/ effects. Those are
volatile memory accesses, file I/O, program start/stop, and calling external
code with unknown effect (since that external code could have visible
effects). C11 adds some atomic access and synchronisation functions, and C
implementations can add more - gcc adds volatile inline assembly. Other
things - non-volatile memory accesses, and calculations, can be shuffled
around at will, including back and forth across volatile accesses.
The only way I know of to force control of the order of execution is to make
"visible" dependencies on the results or the perquisites to the calculations.
(And if the calculation does not have any results, it is not actually needed
at all as far as C is concerned.) You have to use the techniques I gave in my
earlier posts here - they are as convenient, safe, and efficient as it gets.
But it does mean that there is /no/ "general" execution barrier, in the same
way that "asm ("":::"memory")" is a general memory barrier.
If someone knows differently, I'd be happy to be corrected here.