title: G++ 4.6 -std=gnu++0x: Static Local Variable Constructor Call Timing and Thread Safety
body: <pre><code>void a() { ... }
  void b() { ... }
  
  struct X
  {
      X() { b(); }
  };
  
  void f()
  {
      a();
      static X x;
      ...
  }
  </code></pre>
  
  <p>Assume f is called multiple times from various threads (potentially contended) after the entry of main. (and of course that the only calls to a and b are those seen above)</p>
  
  <p>When the above code is compiled with <strong>gcc g++ 4.6</strong> in <strong>-std=gnu++0x</strong> mode:</p>
  
  <p>Q1. Is it guaranteed that a() will be called at least once and return before b() is called?  That is to ask, on the first call to f(), is the constructor of x called at the same time an automatic duration local variable (non-static) would be (and not at global static initialization time for example)?</p>
  
  <p>Q2. Is it guaranteed that b() will be called exactly once?  Even if two threads execute f for the first time at the same time on different cores?  If yes, by which <strong>specific mechanism</strong> does the GCC generated code provide synchronization?  <strong>Edit</strong>: Additionally could one of the threads calling f() obtain access to x before the constructor of X returns?</p>
  
  <p><strong>Update:</strong> I am trying to compile an example and decompile to investigate mechanism...</p>
  
  <p>test.cpp:</p>
  
  <pre><code>struct X;
  
  void ext1(int x);
  void ext2(X&amp; x);
  
  void a() { ext1(1); }
  void b() { ext1(2); }
  
  struct X
  {
      X() { b(); }
  };
  
  void f()
  {
      a();
      static X x;
      ext2(x);
  }
  </code></pre>
  
  <p>Then:</p>
  
  <pre><code>$ g++ -std=gnu++0x -c -o test.o ./test.cpp
  $ objdump -d test.o -M intel &gt; test.dump
  </code></pre>
  
  <p>test.dump:</p>
  
  <pre><code>test.o:     file format elf64-x86-64
  
  
  Disassembly of section .text:
  
  0000000000000000 &lt;_Z1av&gt;:
     0:   55                      push   rbp
     1:   48 89 e5                mov    rbp,rsp
     4:   bf 01 00 00 00          mov    edi,0x1
     9:   e8 00 00 00 00          call   e &lt;_Z1av+0xe&gt;
     e:   5d                      pop    rbp
     f:   c3                      ret    
  
  0000000000000010 &lt;_Z1bv&gt;:
    10:   55                      push   rbp
    11:   48 89 e5                mov    rbp,rsp
    14:   bf 02 00 00 00          mov    edi,0x2
    19:   e8 00 00 00 00          call   1e &lt;_Z1bv+0xe&gt;
    1e:   5d                      pop    rbp
    1f:   c3                      ret    
  
  0000000000000020 &lt;_Z1fv&gt;:
    20:   55                      push   rbp
    21:   48 89 e5                mov    rbp,rsp
    24:   41 54                   push   r12
    26:   53                      push   rbx
    27:   e8 00 00 00 00          call   2c &lt;_Z1fv+0xc&gt;
    2c:   b8 00 00 00 00          mov    eax,0x0
    31:   0f b6 00                movzx  eax,BYTE PTR [rax]
    34:   84 c0                   test   al,al
    36:   75 2d                   jne    65 &lt;_Z1fv+0x45&gt;
    38:   bf 00 00 00 00          mov    edi,0x0
    3d:   e8 00 00 00 00          call   42 &lt;_Z1fv+0x22&gt;
    42:   85 c0                   test   eax,eax
    44:   0f 95 c0                setne  al
    47:   84 c0                   test   al,al
    49:   74 1a                   je     65 &lt;_Z1fv+0x45&gt;
    4b:   41 bc 00 00 00 00       mov    r12d,0x0
    51:   bf 00 00 00 00          mov    edi,0x0
    56:   e8 00 00 00 00          call   5b &lt;_Z1fv+0x3b&gt;
    5b:   bf 00 00 00 00          mov    edi,0x0
    60:   e8 00 00 00 00          call   65 &lt;_Z1fv+0x45&gt;
    65:   bf 00 00 00 00          mov    edi,0x0
    6a:   e8 00 00 00 00          call   6f &lt;_Z1fv+0x4f&gt;
    6f:   5b                      pop    rbx
    70:   41 5c                   pop    r12
    72:   5d                      pop    rbp
    73:   c3                      ret    
    74:   48 89 c3                mov    rbx,rax
    77:   45 84 e4                test   r12b,r12b
    7a:   75 0a                   jne    86 &lt;_Z1fv+0x66&gt;
    7c:   bf 00 00 00 00          mov    edi,0x0
    81:   e8 00 00 00 00          call   86 &lt;_Z1fv+0x66&gt;
    86:   48 89 d8                mov    rax,rbx
    89:   48 89 c7                mov    rdi,rax
    8c:   e8 00 00 00 00          call   91 &lt;_Z1fv+0x71&gt;
  
  Disassembly of section .text._ZN1XC2Ev:
  
  0000000000000000 &lt;_ZN1XC1Ev&gt;:
     0:   55                      push   rbp
     1:   48 89 e5                mov    rbp,rsp
     4:   48 83 ec 10             sub    rsp,0x10
     8:   48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi
     c:   e8 00 00 00 00          call   11 &lt;_ZN1XC1Ev+0x11&gt;
    11:   c9                      leave  
    12:   c3                      ret    
  </code></pre>
  
  <p>I don't see the synchronization mechanism?  Or is it added at linktime?</p>
  
  <p><strong>Update2:</strong> Ok when I link it I can see it...</p>
  
  <pre><code>400973: 84 c0                   test   %al,%al
  400975: 75 2d                   jne    4009a4 &lt;_Z1fv+0x45&gt;
  400977: bf 98 20 40 00          mov    $0x402098,%edi
  40097c: e8 1f fe ff ff          callq  4007a0 &lt;__cxa_guard_acquire@plt&gt;
  400981: 85 c0                   test   %eax,%eax
  400983: 0f 95 c0                setne  %al
  400986: 84 c0                   test   %al,%al
  400988: 74 1a                   je     4009a4 &lt;_Z1fv+0x45&gt;
  40098a: 41 bc 00 00 00 00       mov    $0x0,%r12d
  400990: bf a0 20 40 00          mov    $0x4020a0,%edi
  400995: e8 a6 00 00 00          callq  400a40 &lt;_ZN1XC1Ev&gt;
  40099a: bf 98 20 40 00          mov    $0x402098,%edi
  40099f: e8 0c fe ff ff          callq  4007b0 &lt;__cxa_guard_release@plt&gt;
  4009a4: bf a0 20 40 00          mov    $0x4020a0,%edi
  4009a9: e8 72 ff ff ff          callq  400920 &lt;_Z4ext2R1X&gt;
  4009ae: 5b                      pop    %rbx
  4009af: 41 5c                   pop    %r12
  4009b1: 5d                      pop    %rbp
  </code></pre>
  
  <p>It surrounds it with <strong>__cxa_guard_acquire</strong> and <strong>__cxa_guard_release</strong>, whatever they do.</p>