aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Support/FileCheckTest.cpp
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-05-23 17:14:08 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-05-27 16:27:47 +0200
commit4408eeed0ff191304121c11168aa1db861cccb97 (patch)
tree7a517ecda86889073f19de62f5a646d8cc421364 /llvm/unittests/Support/FileCheckTest.cpp
parent42eba9b40b25cceeb3e6d432047c5ef99d4a7b50 (diff)
downloadllvm-4408eeed0ff191304121c11168aa1db861cccb97.zip
llvm-4408eeed0ff191304121c11168aa1db861cccb97.tar.gz
llvm-4408eeed0ff191304121c11168aa1db861cccb97.tar.bz2
tsan: fix false positives in AcquireGlobal
Add ThreadClock:: global_acquire_ which is the last time another thread has done a global acquire of this thread's clock. It helps to avoid problem described in: https://github.com/golang/go/issues/39186 See test/tsan/java_finalizer2.cpp for a regression test. Note the failuire is _extremely_ hard to hit, so if you are trying to reproduce it, you may want to run something like: $ go get golang.org/x/tools/cmd/stress $ stress -p=64 ./a.out The crux of the problem is roughly as follows. A number of O(1) optimizations in the clocks algorithm assume proper transitive cumulative propagation of clock values. The AcquireGlobal operation may produce an inconsistent non-linearazable view of thread clocks. Namely, it may acquire a later value from a thread with a higher ID, but fail to acquire an earlier value from a thread with a lower ID. If a thread that executed AcquireGlobal then releases to a sync clock, it will spoil the sync clock with the inconsistent values. If another thread later releases to the sync clock, the optimized algorithm may break. The exact sequence of events that leads to the failure. - thread 1 executes AcquireGlobal - thread 1 acquires value 1 for thread 2 - thread 2 increments clock to 2 - thread 2 releases to sync object 1 - thread 3 at time 1 - thread 3 acquires from sync object 1 - thread 1 acquires value 1 for thread 3 - thread 1 releases to sync object 2 - sync object 2 clock has 1 for thread 2 and 1 for thread 3 - thread 3 releases to sync object 2 - thread 3 sees value 1 in the clock for itself and decides that it has already released to the clock and did not acquire anything from other threads after that (the last_acquire_ check in release operation) - thread 3 does not update the value for thread 2 in the clock from 1 to 2 - thread 4 acquires from sync object 2 - thread 4 detects a false race with thread 2 as it should have been synchronized with thread 2 up to time 2, but because of the broken clock it is now synchronized only up to time 1 The global_acquire_ value helps to prevent this scenario. Namely, thread 3 will not trust any own clock values up to global_acquire_ for the purposes of the last_acquire_ optimization. Reviewed-in: https://reviews.llvm.org/D80474 Reported-by: nvanbenschoten (Nathan VanBenschoten)
Diffstat (limited to 'llvm/unittests/Support/FileCheckTest.cpp')
0 files changed, 0 insertions, 0 deletions