[compiler-rt] fa24c4a - [sanitizer] Run Stack compression in background thread
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 9 10:43:32 PST 2021
Author: Vitaly Buka
Date: 2021-12-09T10:29:50-08:00
New Revision: fa24c4a1c07ad17c9709e086d86ca6f792fe79f2
URL: https://github.com/llvm/llvm-project/commit/fa24c4a1c07ad17c9709e086d86ca6f792fe79f2
DIFF: https://github.com/llvm/llvm-project/commit/fa24c4a1c07ad17c9709e086d86ca6f792fe79f2.diff
LOG: [sanitizer] Run Stack compression in background thread
Depends on D114495.
Reviewed By: dvyukov
Differential Revision: https://reviews.llvm.org/D114498
Added:
Modified:
compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h
compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
index 13624a83865d7..50564e62645de 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp
@@ -15,13 +15,14 @@
#include "sanitizer_common.h"
#include "sanitizer_flags.h"
#include "sanitizer_procmaps.h"
-
+#include "sanitizer_stackdepot.h"
namespace __sanitizer {
#if (SANITIZER_LINUX || SANITIZER_NETBSD) && !SANITIZER_GO
// Weak default implementation for when sanitizer_stackdepot is not linked in.
SANITIZER_WEAK_ATTRIBUTE StackDepotStats StackDepotGetStats() { return {}; }
+SANITIZER_WEAK_ATTRIBUTE void StackDepotStopBackgroundThread() {}
void *BackgroundThread(void *arg) {
VPrintf(1, "%s: Started BackgroundThread\n", SanitizerToolName);
@@ -201,6 +202,9 @@ void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start,
SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify,
__sanitizer_sandbox_arguments *args) {
+#if (SANITIZER_LINUX || SANITIZER_NETBSD) && !SANITIZER_GO
+ __sanitizer::StackDepotStopBackgroundThread();
+#endif
__sanitizer::PlatformPrepareForSandboxing(args);
if (__sanitizer::sandboxing_callback)
__sanitizer::sandboxing_callback();
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
index 6fdf2c424ba59..66a0fd64a05a8 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cpp
@@ -484,6 +484,9 @@ u32 GetNumberOfCPUs() { return zx_system_get_num_cpus(); }
uptr GetRSS() { UNIMPLEMENTED(); }
+void *internal_start_thread(void *(*func)(void *arg), void *arg) { return 0; }
+void internal_join_thread(void *th) {}
+
void InitializePlatformCommonFlags(CommonFlags *cf) {}
} // namespace __sanitizer
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
index 1d3ac5cc778a7..c755b1829d2a3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
@@ -12,8 +12,10 @@
#include "sanitizer_stackdepot.h"
+#include "sanitizer_atomic.h"
#include "sanitizer_common.h"
#include "sanitizer_hash.h"
+#include "sanitizer_mutex.h"
#include "sanitizer_stack_store.h"
#include "sanitizer_stackdepotbase.h"
@@ -75,7 +77,7 @@ uptr StackDepotNode::allocated() {
static void CompressStackStore() {
u64 start = MonotonicNanoTime();
uptr
diff = stackStore.Pack(static_cast<StackStore::Compression>(
- common_flags()->compress_stack_depot));
+ Abs(common_flags()->compress_stack_depot)));
if (!
diff )
return;
u64 finish = MonotonicNanoTime();
@@ -85,12 +87,112 @@ static void CompressStackStore() {
(finish - start) / 1000000);
}
+namespace {
+
+class CompressThread {
+ public:
+ constexpr CompressThread() = default;
+ void NewWorkNotify();
+ void Stop();
+ void LockAndStop() NO_THREAD_SAFETY_ANALYSIS;
+ void Unlock() NO_THREAD_SAFETY_ANALYSIS;
+
+ private:
+ enum class State {
+ NotStarted = 0,
+ Started,
+ Failed,
+ Stopped,
+ };
+
+ void Run();
+
+ bool WaitForWork() {
+ semaphore_.Wait();
+ return atomic_load(&run_, memory_order_acquire);
+ }
+
+ Semaphore semaphore_ = {};
+ StaticSpinMutex mutex_ = {};
+ State state_ GUARDED_BY(mutex_) = State::NotStarted;
+ void *thread_ GUARDED_BY(mutex_) = nullptr;
+ atomic_uint8_t run_ = {};
+};
+
+static CompressThread compress_thread;
+
+void CompressThread::NewWorkNotify() {
+ int compress = common_flags()->compress_stack_depot;
+ if (!compress)
+ return;
+ if (compress > 0 /* for testing or debugging */) {
+ SpinMutexLock l(&mutex_);
+ if (state_ == State::NotStarted) {
+ atomic_store(&run_, 1, memory_order_release);
+ CHECK_EQ(nullptr, thread_);
+ thread_ = internal_start_thread(
+ [](void *arg) -> void * {
+ reinterpret_cast<CompressThread *>(arg)->Run();
+ return nullptr;
+ },
+ this);
+ state_ = thread_ ? State::Started : State::Failed;
+ }
+ if (state_ == State::Started) {
+ semaphore_.Post();
+ return;
+ }
+ }
+ CompressStackStore();
+}
+
+void CompressThread::Run() {
+ VPrintf(1, "%s: StackDepot compression thread started\n", SanitizerToolName);
+ while (WaitForWork()) CompressStackStore();
+ VPrintf(1, "%s: StackDepot compression thread stopped\n", SanitizerToolName);
+}
+
+void CompressThread::Stop() {
+ void *t = nullptr;
+ {
+ SpinMutexLock l(&mutex_);
+ if (state_ != State::Started)
+ return;
+ state_ = State::Stopped;
+ CHECK_NE(nullptr, thread_);
+ t = thread_;
+ thread_ = nullptr;
+ }
+ atomic_store(&run_, 0, memory_order_release);
+ semaphore_.Post();
+ internal_join_thread(t);
+}
+
+void CompressThread::LockAndStop() {
+ mutex_.Lock();
+ if (state_ != State::Started)
+ return;
+ CHECK_NE(nullptr, thread_);
+
+ atomic_store(&run_, 0, memory_order_release);
+ semaphore_.Post();
+ internal_join_thread(thread_);
+ // Allow to restart after Unlock() if needed.
+ state_ = State::NotStarted;
+ thread_ = nullptr;
+}
+
+void CompressThread::Unlock() { mutex_.Unlock(); }
+
+} // namespace
+
void StackDepotNode::store(u32 id, const args_type &args, hash_type hash) {
stack_hash = hash;
uptr pack = 0;
store_id = stackStore.Store(args, &pack);
- if (pack && common_flags()->compress_stack_depot)
- CompressStackStore();
+ if (LIKELY(!pack))
+ return;
+ compress_thread.NewWorkNotify();
}
StackDepotNode::args_type StackDepotNode::load(u32 id) const {
@@ -113,11 +215,13 @@ StackTrace StackDepotGet(u32 id) {
void StackDepotLockAll() {
theDepot.LockAll();
+ compress_thread.LockAndStop();
stackStore.LockAll();
}
void StackDepotUnlockAll() {
stackStore.UnlockAll();
+ compress_thread.Unlock();
theDepot.UnlockAll();
}
@@ -127,6 +231,8 @@ void StackDepotPrintAll() {
#endif
}
+void StackDepotStopBackgroundThread() { compress_thread.Stop(); }
+
StackDepotHandle StackDepotNode::get_handle(u32 id) {
return StackDepotHandle(&theDepot.nodes[id], id);
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h
index 56d655d9404ca..cca6fd5346883 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h
@@ -42,6 +42,7 @@ StackTrace StackDepotGet(u32 id);
void StackDepotLockAll();
void StackDepotUnlockAll();
void StackDepotPrintAll();
+void StackDepotStopBackgroundThread();
void StackDepotTestOnlyUnmap();
diff --git a/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp b/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp
index c64c9392a107b..6bf067618f950 100644
--- a/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp
+++ b/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp
@@ -1,7 +1,9 @@
// RUN: %clangxx %s -fsanitize-memory-track-origins=1 -o %t
// RUN: %env_tool_opts="compress_stack_depot=0:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --implicit-check-not="StackDepot released"
-// RUN: %env_tool_opts="compress_stack_depot=1:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS
-// RUN: %env_tool_opts="compress_stack_depot=2:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS
+// RUN: %env_tool_opts="compress_stack_depot=-1:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS
+// RUN: %env_tool_opts="compress_stack_depot=-2:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS
+// RUN: %env_tool_opts="compress_stack_depot=1:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS,THREAD
+// RUN: %env_tool_opts="compress_stack_depot=2:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS,THREAD
// Ubsan does not store stacks.
// UNSUPPORTED: ubsan
@@ -9,6 +11,8 @@
// FIXME: Fails for unknown reason.
// UNSUPPORTED: s390x
+#include <sanitizer/common_interface_defs.h>
+
#include <memory>
__attribute__((noinline)) void a(unsigned v);
@@ -35,7 +39,13 @@ __attribute__((noinline)) void b(unsigned v) { return a(v); }
int main(int argc, char *argv[]) {
for (unsigned i = 0; i < 100000; ++i)
a(i + (i << 16));
+
+ __sanitizer_sandbox_arguments args = {0};
+ __sanitizer_sandbox_on_notify(&args);
+
return 0;
}
+// THREAD: StackDepot compression thread started
// COMPRESS: StackDepot released {{[0-9]+}}
+// THREAD: StackDepot compression thread stopped
More information about the llvm-commits
mailing list