Optimization of conditional access to globals: thread-unsafe?

Darryl Miles darryl-mailinglists@netbauds.net
Mon Oct 29 15:40:00 GMT 2007


Michael Matz wrote:
>> Don't you need the barrier before.  This is to ensure it completed the
>> condition test completely first before it then processed the assignment
>> expression.
>>
>> if(condition) {
>>  somebarrier();
>>  *p = value;
>> }
>>
>> The issue is not that the store is done too late, but that a 
>> write-access is done too early.
> 
> No.  The initial cause for this needless thread was that a store was moved 
> down, out of its control region.  Of course it doesn't help when people 
> keep shifting their point of focus in such discussions.  Now it already 
> moved to fear that GCC would somehow introduce new traps.  Without the 
> people discussing about that fear even bothering to check if that really 
> happens :-(

No the initial problem was that the store was done when the code 
execution path clearly indicates no store should be performed.  The 
store was a re-write of the same and existing value in *p.

The optimizer tried to interleave the compare/test with the load from 
memory.  By inserting the barrier between the test and assignment that 
would stop that interleave from taking place, since it can't optimize 
across the barrier, it must perform the test and branch first, before it 
stores to memory.

It may optionally interleave the 'load from memory into register for 
"value" variable'.  This is would be a speculative load and this would 
be safe, as the value or 'value' may go unused (thrown away) if the 
branch is taken to skip the store to *p.


Now the original case was show as a simple function with just the

if(condition) {
  *v = 1
}

I would agree with you that a barrier() afterwards would be needed if 
there was any statement beyond that close brace of the test within the 
same function.  This is to ensure the store is not deferred any later, 
that maybe accessed via another alias to the same memory for which the 
compiler could not see at compile time.

But there isn't, there is a function return, which does the trick nicely.

A purist perspective this makes it:

void foo(int value) {
  if(condition) {
   somebarrier();
   *v = value;
   somebarrier();
  }

  // more statements here that may access *v
  // if you don't have any statements here, then you can omit the 2nd 
somebarrier() call

  return;
}


Darryl



More information about the Gcc mailing list