LLVM has lifted strong requirements for CAS failure memory orders in 431e3138a and 819e0d105e84.
Add support for honoring them in AtomicCAS.
Differential D99434
[TSAN] Honor failure memory orders in AtomicCAS bruno on Mar 26 2021, 12:12 PM. Authored by
Details LLVM has lifted strong requirements for CAS failure memory orders in 431e3138a and 819e0d105e84. Add support for honoring them in AtomicCAS.
Diff Detail
Event TimelineComment Actions I am happy with the mechanics and quality of the patch. Ideally @dvyukov could give a final sign-off.
Comment Actions Thanks both of you for the review @delcypher and @yln, will wait for @dvyukov to sign-off!
Comment Actions Also I wonder if we could first evaluate CAS and then use either mo or fmo accordingly, so that we don't over-synchronize on failure if mo is stronger than fmo. Comment Actions Not directly related to the change but we could also episodically fail weak CASes to test fmo case better. Comment Actions Address reviewer comments. To prevent false positive on release/consume, this now depends on https://reviews.llvm.org/D101501.
Comment Actions Apply review comments. Note that we cannot test mo == relaxed and fmo == anything yet because LLVM fallbacks to relaxed/relaxed. Remove the dep on https://reviews.llvm.org/D101501 for now, since there's even more stuff to improve in LLVM before we get this 100% right, at least we've got release/acquire working as of this patch. I'll come back to fix the other tests once LLVM is fixed.
Comment Actions Apply more reviewer suggested changes: first evaluate CAS, then decide what order to use. Now that LLVM side of this is fixed, also cover all fmo's allowed, add more tests.
Comment Actions Thank you @dvyukov for another round of reviews! A have more questions for you. Yes, fmo can be seq_cst. Take mo == mo_release and fmo == mo_seq_cst, we'd be acquiring the mutex with write_lock, which is fine under success. However, during failure, I don't see another solution besides s->mtx.Unlock() before honoring and calling GetOrCreateAndLock again to obtain the lock with write_lock = false. Since you said in a previous review that it would be too expensive to lock again, what do you suggest as an alternative? I wonder whether my concern is even legit (?) given that the mo == mo_release and fmo == mo_seq_cst in the testcase works regardless of this lock/unlock dance. It's also the case that the current added testcase takes ~20s on a fast linux machine, which seems way over the bar, I haven't tried to make it better yet, but (at least) diminishing the mo/fmo combinations should help, other ideas? In the meantime, I've updated the patch with that approach. Comment Actions We don't need to re-lock in read mode. We can lock in the strongest mode: write lock if either mo or fmo requires a release, and then do acquire under write if it turned out we need only acquire. It's fine to read a data structure under write lock. Comment Actions This is too long. But I think it's just to the "atexit sleep" in tsan. You can do this, and maybe even set atexit_sleep_ms to 0: test/tsan/fork_atexit.cpp:// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts=atexit_sleep_ms=50 %run %t 2>&1 | FileCheck %s Comment Actions Cool, thanks for the input!
Comment Actions I don't see any issues now. Thanks for bearing with me.
|
Can it be seq_cst?
If yes, then I think write_lock below is incorrect and checking only IsAcquireOrder(fmo) is incorrect as well.