diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp @@ -12,6 +12,7 @@ #include "sanitizer_stackdepot.h" +#include "sanitizer_atomic.h" #include "sanitizer_common.h" #include "sanitizer_hash.h" #include "sanitizer_stack_store.h" @@ -81,10 +82,15 @@ return pack; } +static Semaphore compress_semaphore; + +// 0 - didn't try, 1 - started or pending, 2 - failed. +static atomic_uint8_t thread_started; + static void CompressTraces() { u64 start = MonotonicNanoTime(); uptr diff = stackStore.Pack(static_cast( - common_flags()->compress_stack_depot)); + Abs(common_flags()->compress_stack_depot))); if (!diff) return; u64 finish = MonotonicNanoTime(); @@ -93,8 +99,37 @@ (finish - start) / 1000000); } +static void *CompressTracesThread(void *args) { + for (;;) { + compress_semaphore.Wait(); + CompressTraces(); + } + return nullptr; +} + +static bool MaybeRunBackgroundThread() { + if (common_flags()->compress_stack_depot < 0 /* hack for testing */) + return false; + + u8 cmp = 0; + if (!atomic_compare_exchange_weak(&thread_started, &cmp, 1, + memory_order_acquire)) { + return cmp == 1; + } + if (!internal_start_thread(&CompressTracesThread, nullptr)) { + atomic_store(&thread_started, 2, memory_order_release); + return false; + } + VPrintf(1, "%s: StackDepot Thread Started\n", SanitizerToolName); + return true; +} + void StackDepotNode::post_process() { - if (common_flags()->compress_stack_depot) + if (!common_flags()->compress_stack_depot) + return; + if (MaybeRunBackgroundThread()) + compress_semaphore.Post(1); + else CompressTraces(); } diff --git a/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp b/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp --- a/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp @@ -1,6 +1,6 @@ // 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=-1:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS // Ubsan does not store stacks. // UNSUPPORTED: ubsan