[llvm-branch-commits] [compiler-rt] [sanitizers] Optimize locking StackDepotBase for fork (PR #76280)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Dec 22 23:26:49 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Vitaly Buka (vitalybuka)

<details>
<summary>Changes</summary>

Locking StackDepotBase fully is very expensive, as 2^20 buckets needs to
be locked. Not locking, and unclocking only buckets, needed to be
unlocked to avoid deadlocks, increases a chance of data race, when same
item can be inserted into table twice. However this is just a small
additional memory usage by forked process.


---
Full diff: https://github.com/llvm/llvm-project/pull/76280.diff


4 Files Affected:

- (modified) compiler-rt/lib/dfsan/dfsan_chained_origin_depot.cpp (+5-1) 
- (modified) compiler-rt/lib/msan/msan_chained_origin_depot.cpp (+7-2) 
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp (+12-2) 
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h (+2-1) 


``````````diff
diff --git a/compiler-rt/lib/dfsan/dfsan_chained_origin_depot.cpp b/compiler-rt/lib/dfsan/dfsan_chained_origin_depot.cpp
index 6644bd6a7c6c0c..d078265258ca14 100644
--- a/compiler-rt/lib/dfsan/dfsan_chained_origin_depot.cpp
+++ b/compiler-rt/lib/dfsan/dfsan_chained_origin_depot.cpp
@@ -19,9 +19,13 @@ static ChainedOriginDepot chainedOriginDepot;
 
 ChainedOriginDepot* GetChainedOriginDepot() { return &chainedOriginDepot; }
 
-void ChainedOriginDepotLockBeforeFork() { chainedOriginDepot.LockAll(); }
+void ChainedOriginDepotLockBeforeFork() {
+  // TODO: Consider same optimization as `StackDepotLockBeforeFork`.
+  chainedOriginDepot.LockAll();
+}
 
 void ChainedOriginDepotUnlockAfterFork(bool fork_child) {
+  // TODO: Consider same optimization as `StackDepotUnlockAfterFork`.
   chainedOriginDepot.UnlockAll();
 }
 
diff --git a/compiler-rt/lib/msan/msan_chained_origin_depot.cpp b/compiler-rt/lib/msan/msan_chained_origin_depot.cpp
index c3bd54141e6c38..66c80708669373 100644
--- a/compiler-rt/lib/msan/msan_chained_origin_depot.cpp
+++ b/compiler-rt/lib/msan/msan_chained_origin_depot.cpp
@@ -31,10 +31,15 @@ u32 ChainedOriginDepotGet(u32 id, u32 *other) {
   return chainedOriginDepot.Get(id, other);
 }
 
-void ChainedOriginDepotBeforeFork() { chainedOriginDepot.LockAll(); }
+void ChainedOriginDepotBeforeFork() {
+  // Don't `chainedOriginDepot.LockAll()`, see `StackDepotLockBeforeFork`.
+}
 
 void ChainedOriginDepotAfterFork(bool fork_child) {
-  chainedOriginDepot.UnlockAll();
+  // See `StackDepotUnlockAfterFork`.
+  if (fork_child) {
+    chainedOriginDepot.UnlockAll();
+  }
 }
 
 } // namespace __msan
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
index ce21f3c178bce0..8d134ca5a41aee 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
@@ -216,7 +216,13 @@ StackTrace StackDepotGet(u32 id) {
 }
 
 void StackDepotLockBeforeFork() {
-  theDepot.LockAll();
+  // Do not `theDepot.LockAll()`. It's very slow, but not rely needed. The
+  // parent process will neither lock nor unlock. Child process risks to be
+  // deadlocked on already locked buckets. To avoid deadlock we will unlock
+  // every locked buckets. This may affect consistency of the hash table, but
+  // the only possible issue is a few items inserted by parent process will be
+  // not found by child, and the child may insert them again, wasting some space
+  // in `stackStore`.
   compress_thread.LockAndStop();
   stackStore.LockAll();
 }
@@ -224,7 +230,11 @@ void StackDepotLockBeforeFork() {
 void StackDepotUnlockAfterFork(bool fork_child) {
   stackStore.UnlockAll();
   compress_thread.Unlock();
-  theDepot.UnlockAll();
+  if (fork_child) {
+    // Only child process needs to unlock to avoid deadlock. See
+    // `StackDepotLockAll`.
+    theDepot.UnlockAll();
+  }
 }
 
 void StackDepotPrintAll() {
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h
index 96d1ddc87fd032..3440a8f628e971 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h
@@ -171,7 +171,8 @@ void StackDepotBase<Node, kReservedBits, kTabSizeLog>::UnlockAll() {
   for (int i = 0; i < kTabSize; ++i) {
     atomic_uint32_t *p = &tab[i];
     uptr s = atomic_load(p, memory_order_relaxed);
-    unlock(p, s & kUnlockMask);
+    if (s & kLockMask)
+      unlock(p, s & kUnlockMask);
   }
 }
 

``````````

</details>


https://github.com/llvm/llvm-project/pull/76280


More information about the llvm-branch-commits mailing list