Data race in `readTVarIO#`?
Currently readTVarIO#
is defined thusly (annotations are my own):
stg_readTVarIOzh ( P_ tvar /* :: TVar a */ )
{
W_ result, resultinfo;
again:
result = StgTVar_current_value(tvar);
// (1)
resultinfo = %INFO_PTR(result);
prim_read_barrier; // (2)
if (resultinfo == stg_TREC_HEADER_info) {
goto again;
}
return (result);
}
I'm skeptical that the barriers here are correct. In particular, it seems to me that there should be a read barrier between the load from tvar->current_value
and the %INFO_PTR
load (point (1)). Secondly, I don't believe that the barrier at (2) is necessary.
IMHO, this is all much easier to reason about with C11-style release acquire semantics. Under this worldview, the load from current_value
should be an acquire-load, which will synchronize with the release-store in unlock_tvar
. This will guarantee a happens-before relationship, which then allows us to conclude that the barrier at (2) is redundant since the construction of the closure necessarily happens-before the store in unlock_tvar
.