Re: Avr-libc-user-manual: "Problems with reordering code"

David Brown <[email protected]> Thu, 9 Feb 2017 21:20:40 +0100
Newsgroups gmane.comp.hardware.avr.gcc
Message-ID <[email protected]>

On 09/02/17 19:49, Bob Paddock wrote:
> On Thu, Feb 9, 2017 at 1:13 PM, David Brown <[email protected]> wrote:
>
>> Note also that it is only control
>> of the memory access that is needed for code correctness - moving
>> instruction execution affects timing, but not the results.
>
> As I'm sure you are aware even if the code if mathematically correct,
> giving the correct answers, failing to meet timing goals can be
> catastrophic in Real Time Systems.

Yes.

>
> 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.