Copy internal deadlock detector from tsan to sanitizer_common (with some cosmetic changes). Tsan version will be deleted in subsequent changes. This allows us to switch tsan to the sanitizer_common mutex and remove tsan's mutex.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
58 | should this be 'static constexpr' ? |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
76 | if mutex_count == kMutexTypeMax Why it can't just? |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
76 | I guess that needed to be CHECK_LT. SANITIZER_WEAK_ATTRIBUTE MutexMeta mutex_meta[] = {{}}; (array with 1 element) Now with mutex_meta[kMutexTypeMax] we can do this. |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
59 | Given this is just the dummy, could this be mutex_meta[1] ? I think in the case that this is not overridden, the DebugMutexInit loop will just immediately see !mutex_meta[0].name, right? | |
76 | We might still overflow with the improved loop if the overridden version has <kMutexTypeMax elements and no terminator (unless I misunderstand how weak linking works for arrays). I think the previous version was correct, because it is impossible to know what the size of the override array is. Do we now still have a CHECK-fail if the last element was not the terminating element? Because otherwise somebody might keep adding entries and they will just be ignored. Non-dummy arrays of mutex_meta should therefore actually be able to have up to kMutexTypeMax+1 elements to be checked, where the last one should always be the terminator. |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
59 | Never mind, I just saw your comment about miscompilation. |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
76 | What about adding CHECK_LT(mutex_count, kMutexTypeMax) after the loop? It will catch "too many" types. |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
76 | An override array can have up to kMutexTypeMax+1 elements with +1 being the terminator. Otherwise kMutexTypeMax is not the max, and the other arrays are wasting space. I think to fix:
The dummy mutex_meta might need a size-change to kMutexTypeMax+1 in case the compiler decides to be clever again. |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
76 | ... and there needs to be a CHECK after if (!mutex_meta[t].name) mutex_count = t; if (!mutex_meta[t].name) break; CHECK(t < kMutexTypeMax); // Indicates array is not properly terminated. |
Oh, it's actual copying, but it looks very different from TSAN version.
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
51 | Why this detector operates on types and not individual mutexes? | |
152 | mutex_count -> mutex_type_count ? | |
210 | static THREADLOCAL | |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.h | ||
79 | enum class (maybe) |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
76 |
This is a very slow debug mode. Execution speed effect is worse then spending few bytes of memory. And we are wasting half of the array right now, what tsan uses is half of kMutexTypeMax. And other sanitizer waste all of it. Not just one and not just if we are not careful with checks here. They are always wasting all of it. |
PTAL
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
51 | We don't lock more than 1 of the same type. | |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.h | ||
79 | The same reason we can't use enum call in tsan applies here. It's not possible to "extend" enum classes, and we need to be able to extend it in each sanitizer. |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
51 | That's fine, but maybe add comment explaining that. It's not obvious without digging into details. |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
51 | Done |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
76 | Hi Dmitry, the statement "int cnt[kMutexTypeMax] = {};" seems to be causing some unit test to fail to in some configurations ? Can we maybe remove the empty initializer list? $ cmake -G Ninja "../llvm" -DLLVM_ENABLE_PROJECTS="clang;compiler-rt;" -DLLVM_TARGETS_TO_BUILD="X86" -DCMAKE_BUILD_TYPE=Release -DCOMPILER_RT_DEBUG=ON -DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 $ ninja -j12 check-sanitizer [6/22] Generating Sanitizer-x86_64-Test-Nolibc FAILED: projects/compiler-rt/lib/sanitizer_common/tests/Sanitizer-x86_64-Test-Nolibc cd /home/pierre/llvm-project/build/projects/compiler-rt/lib/sanitizer_common/tests && /home/pierre/llvm-project/build/./bin/clang sanitizer_nolibc_test_main.x86_64.o -Wl,-whole-archive libRTSanitizerCommon.test.nolibc.x86_64.a -Wl,-no-whole-archive -o /home/pierre/llvm-project/build/projects/compiler-rt/lib/sanitizer_common/tests/./Sanitizer-x86_64-Test-Nolibc -static -nostdlib -m64 -m64 libRTSanitizerCommon.test.nolibc.x86_64.a(sanitizer_mutex.cpp.o): In function `__sanitizer::DebugMutexInit()': /home/pierre/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp:76: undefined reference to `memset' clang-14: error: linker command failed with exit code 1 (use -v to see invocation) [13/22] Running lint check for sanitizer sources... ninja: build stopped: subcommand failed. |
compiler-rt/lib/sanitizer_common/sanitizer_mutex.cpp | ||
---|---|---|
76 | I've sent https://reviews.llvm.org/D106978 |
enum class (maybe)