http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51752

--- Comment #6 from torvald at gcc dot gnu.org 2012-02-09 18:40:49 UTC ---
(In reply to comment #4)
> But isn't with
> 
>   __transaction_atomic
>     {
>       for (i = 0; i < 10; i++)
>         if (x[i])
>           x[i] += data;
>     }
> 
> and
> 

prepend with the following for thread B:

  data = 123;

>   __transaction_atomic { x[9] = 1; }
> 
> occuring concurrently the loop transaction terminated?  Thus,
> 
>   __transaction_atomic
>     {
>       tem = data;
>       for (i = 0; i < 10; i++)
>         if (x[i])
>           x[i] += tem;
>     }
> 
> equivalent?

No.  It might be for typical HTMs, but we can't expect this in the general
case.  The interleaving that can then happen is (with A and B being the two
concurrent threads):

  B: tem = data;  // reads initial value of zero
  A: data = 123;
  A: __transaction_atomic { x[9] = 1; }
  B: if (x[i])
  B:   x[i] += tem;  // adds zero, not 123.

The problem here is that B's store to data is nontransactional, and we cannot
add synchronization code for those (it might be library code, for example).

We could add a partial workaround to libitm that would reduce this case here to
"just" a racing load.  However, that would kill performance because basically,
B's transaction would have to wait for all earlier-started transactions before
it can start executing.  The racing load can still be a problem if we hoist
dereferencing a pointer.

We don't see this example with other concurrent code because there, the load of
x[] would have to be a synchronizing operation, and we don't hoist across
these.

Reply via email to