This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Optimization of conditional access to globals: thread-unsafe?


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



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]