Why doesn't this compiler barrier enforce orde

2019-05-10 16:20发布

问题:

I was looking at the documentation on the Atmel website and I came across this example where they explain some issues with reordering.

Here's the example code:

#define cli() __asm volatile( "cli" ::: "memory" )
#define sei() __asm volatile( "sei" ::: "memory" )

unsigned int ivar;

void test2( unsigned int val )
{
  val = 65535U / val;

  cli();

  ivar = val;

  sei();
}

In this example, they're implementing a critical region-like mechanism. The cli instruction disables interrupts and the sei instruction enables them. Normally, I would save the interrupt state and restore to that state, but I digress...

The problem which they note is that, with optimization enabled, the division on the first line actually gets moved to after the cli instruction. This can cause some issues when you're trying to be inside of the critical region for the shortest amount of time as possible.

How come this is possible if the cli() MACRO expands to inline asm which explicitly clobbers the memory? How is the compiler free to move things before or after this statement?

Also, I modified the code to include memory barriers before every statement in the form of __asm volatile("" ::: "memory"); and it doesn't seem to change anything.

I also removed the memory clobber from the cli() and sei() MACROs, and the generated code was identical.

Of course, if I declare the test2 function argument as volatile, there is no reordering, which I assume to be because volatile statements can't be reordered with respect to other volatile statements (which the inline asm technically is). Is my assumption correct?

Can volatile accesses be reordered with respect to volatile inline asm?

Can non-volatile accesses be reordered with respect to volatile inline asm?

What's weird is that Atmel claims they need the memory clobber just to enforce the ordering of volatile accesses with respect to the asm. That doesn't make any sense to me.

If the compiler barrier isn't the proper solution for this, then how could I go about preventing any outside code from "leaking" into the critical region?

If anyone could shed some light, I'd appreciate it.

Thanks

标签: c gcc arduino avr