<div dir="ltr">Hi,<div><br></div><div>The __sync_* builtins are currently implemented using an atomicrmw instruction with the seq_cst ordering. A bug has been raised on GCC about this, and I think it applies to LLVM too. However my memory-ordering-fu is incredibly weak, so please bear with me if I make mistakes explaining.</div><div><br></div><div>Consider the following code:</div><div><br></div><div><pre class="code-java" style="margin-top:0px;margin-bottom:0px;padding:0px;font-size:13px;line-height:1.3em;max-height:30em;overflow:auto;word-wrap:normal;color:rgb(0,0,0)">void thread1(void)
{
        __sync_fetch_and_add(&foo, 1);
        printf(<span class="code-quote" style="color:rgb(0,145,0);background-color:inherit">"bar = %d\n"</span>, bar);
}

void thread2(void)
{
        __sync_fetch_and_add(&bar, 1);
        printf(<span class="code-quote" style="color:rgb(0,145,0);background-color:inherit">"foo = %d\n"</span>, foo);
}</pre><pre class="code-java" style="margin-top:0px;margin-bottom:0px;padding:0px;font-size:13px;line-height:1.3em;max-height:30em;overflow:auto;word-wrap:normal;color:rgb(0,0,0)"><span style="font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.3em"><br></span></pre>The user expected that the output "bar = 0\nfoo = 0" was impossible. Note that this is in C90/C99 mode - in C11 there is a race condition here so it is the user's problem.<br><br>The problem is that a sequentially-consistent fetch and add can allow an unordered load to jump in the middle. A seq_cst fetch and add could be lowered as:</div><div><br></div><div>ld.acq.ex x0, [foo]<br>add x0, #1</div><div>st.rel.ex x0, [foo]</div><div><br></div><div>Now consider a following load from [bar]. That is unordered and may be speculated before the store, because they are to different memory locations.</div><div><br></div><div>ld.acq.ex x0, [foo]</div><div>add x0, #1</div><div>ld.unordered x1, [bar] # Not the intention in using __sync_!</div><div>st.rel.ex x0, [foo]<br><pre class="code-java" style="margin-top:0px;margin-bottom:0px;padding:0px;font-size:13px;line-height:1.3em;max-height:30em;overflow:auto;word-wrap:normal;color:rgb(0,0,0)"><br></pre>So, I think the __sync_* builtins, at least in non-C11 mode, need a stronger guarantee than seq_cst - perhaps an extra "fence" IR instruction?</div><div><br></div><div>What are experts' thoughts?</div><div><br></div><div>Cheers,</div><div><br></div><div>James</div></div>