<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - atomic compare-and-swap under thread sanitizer after multithreaded fork is incorrect"
   href="https://llvm.org/bugs/show_bug.cgi?id=23176">23176</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>atomic compare-and-swap under thread sanitizer after multithreaded fork is incorrect
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>compiler-rt
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>3.5
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>compiler-rt
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>bsilver16384+llvm@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Many of the atomic compare-and-swap primitives work incorrectly under thread
sanitizer after a multithreaded fork. Some of the ones which do not work:
__sync_bool_compare_and_swap, __sync_val_compare_and_swap,
__tsan_atomic32_compare_exchange_val. They all return a value indicating that
the variable did not contain the correct value at the start, even when it does.
However, they do change the value of the variable correctly. The variants which
return the previous value always return 1.

__tsan_atomic32_compare_exchange_strong does work correctly under the same
circumstances.

Here's a simple test program which shows the problem:
#include <stdio.h>
#include <unistd.h>
#include <sanitizer/tsan_interface_atomic.h>

#include <thread>

void succeed() {
  int test = 4;
  int result = 4;
  __tsan_atomic32_compare_exchange_strong(&test, &result, 5,
                                          __tsan_memory_order_seq_cst,
                                          __tsan_memory_order_seq_cst);
  printf("got %d value is %d\n", result, test);
}

void fail2() {
  int test = 4;
  int result = __tsan_atomic32_compare_exchange_val(
      &test, 4, 5, __tsan_memory_order_seq_cst, __tsan_memory_order_seq_cst);
  printf("got %d value is %d\n", result, test);
}

void fail1() {
  int test = 4;
  int result = __sync_val_compare_and_swap(&test, 4, 5);
  printf("got %d value is %d\n", result, test);
}

void nop() {}

int main() {
  ::std::thread thread1(nop);
  if (fork() == 0) {
    fail1();
    fail2();
    succeed();
    exit(0);
  } else {
    thread1.join();
  }
}

Here's what it prints for me:
got 1 value is 5
got 1 value is 5
got 4 value is 5

Those 1s should be 4s.</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>