<div dir="ltr">So you're saying a compiler can optimize:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
- statement with memory access<br>
- read memory barrier<br>
- statement with memory access<br>
<br>
To drop the second statement? I would worry about your definition of memory barrier then..<span><font color="#888888"><br></font></span></blockquote><div>This is tricky, but I think you're mixing up the general case with the actual code you have. In general, you are pointing to this example:<br><br></div><div>- Read memory location 1 (asm level)<br></div><div>- RMB<br></div><div>- Read memory location 2 (asm level)<br><br></div><div>In this case, you are precisely correct, the compiler will not reorder the reads, and the CPU won't either.<br></div><div><br></div><div>What you actually have is this:<br></div><div><div>- Access memory location 1 (C code)<br></div><div>- RMB<br></div>- Acesss memory location 1 (C code)<br></div><div><br>I say "access" here because looking at the C code, not assembly. You have this:<br><br></div><div>read nvbo->head.next<br></div><div>RMB<br><div>read nvbo->head.next<br></div><br></div><div>This only works if you can guarantee that the compiler will actually generate a MOV instruction for the second read. If the variable isn't marked as "volatile", the compiler has no requirement to. Barriers control ordering and when a variable can be loaded, but you've already loaded it. You need to reload the variable, but you haven't shown the compiler a reason why it should. "Volatile" is a reason why.<br><br></div><div>I tested this code on gcc:<br><br></div><div>if(globalFlag) {<br></div><div>    math...<br></div><div>    if(globalFlag) {<br></div><div>        more math<br>    }<br>}<br></div><br></div><div class="gmail_quote">It only tests once. If you replace "math" with printf(), it retests the value of globalFlag. Printf(), which has absolutely no barrier semantics at all. In other words, GCC conservatively will assume any function call will require a reload because it could modify anything. The code will work as-is.<br><br>Obviously, pthread_mutex_lock() does not modify the value of `nvbo->head.next`. Once GCC knows that (and maybe other compilers already do), perhaps with LTO, it doesn't have to generate a second load. If you ever switch to an inlined lock or different compiler that understands that, your code will break. I suggest you simply do the right thing the first time and cast the pointer to volatile since you're treating the value as if it is volatile (i.e. changing outside of the scope of the compiler's knowledge).<br><br></div><div class="gmail_quote">Patrick<br></div><div class="gmail_quote"><div><br></div><div><br><br></div></div></div></div>