title: Why does __sync_add_and_fetch work for a 64 bit variable on a 32 bit system?
body: <p>Consider the following condensed code:</p>
  
  <pre class="lang-c prettyprint-override"><code>/* Compile: gcc -pthread -m32 -ansi x.c */
  #include &lt;stdio.h&gt;
  #include &lt;inttypes.h&gt;
  #include &lt;pthread.h&gt;
  
  static volatile uint64_t v = 0;
  
  void *func (void *x) {
      __sync_add_and_fetch (&amp;v, 1);
      return x;
  }
  
  int main (void) {
      pthread_t t;
      pthread_create (&amp;t, NULL, func, NULL);
      pthread_join (t, NULL);
      printf ("v = %"PRIu64"\n", v);
      return 0;
  }
  </code></pre>
  
  <p>I have a <code>uint64_t</code> variable that I want to increment atomically, because the variable is a counter in a multi-threaded program.
  To achieve the atomicity I use GCC's <a href="http://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Atomic-Builtins.html">atomic builtins</a>.</p>
  
  <p>If I compile for an amd64 system (-m64) the produced assembler code is easy to understand. 
  By using a <code>lock addq</code>, the processor guarantees the increment to be atomic.</p>
  
  
  
  <pre class="lang-none prettyprint-override"><code> 400660:       f0 48 83 05 d7 09 20    lock addq $0x1,0x2009d7(%rip)
  </code></pre>
  
  <p>But the same C code produces a very complicated ASM code on an ia32 system (-m32):</p>
  
  <pre class="lang-none prettyprint-override"><code>804855a:       a1 28 a0 04 08          mov    0x804a028,%eax
  804855f:       8b 15 2c a0 04 08       mov    0x804a02c,%edx
  8048565:       89 c1                   mov    %eax,%ecx
  8048567:       89 d3                   mov    %edx,%ebx
  8048569:       83 c1 01                add    $0x1,%ecx
  804856c:       83 d3 00                adc    $0x0,%ebx
  804856f:       89 ce                   mov    %ecx,%esi
  8048571:       89 d9                   mov    %ebx,%ecx
  8048573:       89 f3                   mov    %esi,%ebx
  8048575:       f0 0f c7 0d 28 a0 04    lock cmpxchg8b 0x804a028
  804857c:       08 
  804857d:       75 e6                   jne    8048565 &lt;func+0x15&gt;
  </code></pre>
  
  <p>Here is what I don't understand:</p>
  
  <ul>
  <li><a href="http://faydoc.tripod.com/cpu/cmpxchg8b.htm"><code>lock cmpxchg8b</code></a> <strong>does</strong> guarantee that the changed variable is only written if the expected value still resides in the target address. The compare-and-swap is guaranteed to happen atomically.</li>
  <li><strong>But</strong> what guarantees that the reading of the variable in 0x804855a and 0x804855f to be atomic?</li>
  </ul>
  
  <p>Probably it does not matter if there was a "dirty read", but could someone please outline a short <strong>proof</strong> that there is no problem?</p>
  
  <p>Further: Why does the generated code jump back to 0x8048565 and not 0x804855a? I am positive that this is only correct if other writers, too, only increment the variable. Is this an implicated requirement for the <code>__sync_add_and_fetch</code> function?</p>