title: pthread_create(3) and memory synchronization guarantee in SMP architectures
body: <p>I am looking at the section 4.11 of <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11" rel="nofollow">The Open Group Base Specifications Issue 7 (IEEE Std 1003.1, 2013 Edition), section 4.11</a> document, which spells out the memory synchronization rules. This is the most specific by the POSIX standard I have managed to come by for detailing the POSIX/C memory model.</p>
  
  <p>Here's a quote</p>
  
  <blockquote>
    <p>4.11 Memory Synchronization</p>
    
    <p>Applications shall ensure that access to any memory location by more
    than one thread of control (threads or processes) is restricted such
    that no thread of control can read or modify a memory location while
    another thread of control may be modifying it. Such access is
    restricted using functions that synchronize thread execution and also
    synchronize memory with respect to other threads. The following
    functions synchronize memory with respect to other threads:</p>
    
    <p>fork() pthread_barrier_wait() pthread_cond_broadcast()
    pthread_cond_signal() pthread_cond_timedwait() pthread_cond_wait()
    pthread_create() pthread_join() pthread_mutex_lock()
    pthread_mutex_timedlock()</p>
    
    <p>pthread_mutex_trylock() pthread_mutex_unlock() pthread_spin_lock()
    pthread_spin_trylock() pthread_spin_unlock() pthread_rwlock_rdlock()
    pthread_rwlock_timedrdlock() pthread_rwlock_timedwrlock()
    pthread_rwlock_tryrdlock() pthread_rwlock_trywrlock()</p>
    
    <p>pthread_rwlock_unlock() pthread_rwlock_wrlock() sem_post()
    sem_timedwait() sem_trywait() sem_wait() semctl() semop() wait()
    waitpid()</p>
  </blockquote>
  
  <p>(exceptions to the requirement omitted).</p>
  
  <p>Basically, paraphrasing the above document,  the rule is that when applications read or modify a memory location while another thread or process may modify it, they should make sure to <em>synchronize the thread execution <strong>and memory</strong> with respect to other threads</em> by calling one of the listed functions. Among them,  <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html" rel="nofollow"><code>pthread_create(3)</code></a> is mentioned to provide that memory synchronization.</p>
  
  <p>I understand that this basically means there needs to be some sort of <a href="http://en.wikipedia.org/wiki/Memory_barrier" rel="nofollow">memory barrier</a> implied by each of the functions (although the standard seems not to use that concept). So for example returning from <code>pthread_create()</code>, we are guaranteed that the memory modifications made by that thread before the call appear to other threads (running possibly different CPU/core) after they also synchronize memory. But what about the newly created thread - is there implied memory barrier before the thread starts running the thread function so that it unfailingly sees the memory modifications synchronized by <code>pthread_create()</code>? Is this specified by the standard? Or should we provide memory synchronization explicitly to be able to trust correctness of any data we read according to POSIX standard?</p>
  
  <p>Special case (which would as a special case answer the above question): does a context switch provide memory synchronization, that is, when the execution of a process or thread is started or resumed, is the memory synchronized with respect to any memory synchronization by other threads of execution?</p>
  
  <p><strong>Example:</strong></p>
  
  <p>Thread <code>#1</code> creates a constant object allocated from heap. Thread <code>#1</code> creates a new thread <code>#2</code> that reads the data from the object. If we can assume the new thread <code>#2</code> starts with memory synchronized then everything is fine. However, if the CPU core running the new thread has copy of previously allocated but since discarded data in its cache memory instead of the new value, then it might have wrong view of the state and the application may function incorrectly.</p>
  
  <p>More concretely...</p>
  
  <ol>
  <li><p>Previously in the program (this is the value in CPU #1 cache memory)</p>
  
  <pre><code> int i = 0;        
  </code></pre></li>
  <li><p>Thread <code>T0</code> running in <strong>CPU #0</strong>:</p>
  
  <pre><code> pthread_mutex_lock(...);
   int tmp = i;
   pthread_mutex_unlock(...);
  </code></pre></li>
  <li><p>Thread <code>T1</code> running in <strong>CPU #1</strong>:</p>
  
  <pre><code> i = 42;
   pthread_create(...);
  </code></pre></li>
  <li><p>Newly created thread <code>T2</code> running in <strong>CPU #0</strong>:</p>
  
  <pre><code> printf("i=%d\n", i);    /* First step in the thread function */
  </code></pre></li>
  </ol>
  
  <p>Without memory barrier, without synchronizing thread <code>T2</code> memory it could happen that the output would be </p>
  
  <pre><code>     i=0
  </code></pre>
  
  <p>(previously cached, unsynchronized value).</p>
  
  <p><strong>Update:</strong>
  Lot of applications using POSIX thread library would not be thread safe if this implementation craziness was allowed.</p>