diff --git a/compiler-rt/include/sanitizer/tsan_interface.h b/compiler-rt/include/sanitizer/tsan_interface.h --- a/compiler-rt/include/sanitizer/tsan_interface.h +++ b/compiler-rt/include/sanitizer/tsan_interface.h @@ -169,6 +169,9 @@ // if TSan should exit as if issues were detected. int __tsan_on_finalize(int failed); +// Release TSan internal memory in a best-effort manner. +void __tsan_flush_memory(); + #ifdef __cplusplus } // extern "C" #endif diff --git a/compiler-rt/test/tsan/flush_memory.cpp b/compiler-rt/test/tsan/flush_memory.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/tsan/flush_memory.cpp @@ -0,0 +1,35 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %env_tsan_opts="flush_memory_ms=1 flush_symbolizer_ms=1 memory_limit_mb=1" %deflake %t | FileCheck %s +#include "test.h" + +long X, Y; + +void *Thread(void *arg) { + __atomic_fetch_add(&X, 1, __ATOMIC_SEQ_CST); + barrier_wait(&barrier); + barrier_wait(&barrier); + Y = 1; + return &Y; +} + +int main() { + __tsan_flush_memory(); + barrier_init(&barrier, 2); + __atomic_fetch_add(&X, 1, __ATOMIC_SEQ_CST); + pthread_t t; + pthread_create(&t, NULL, Thread, NULL); + barrier_wait(&barrier); + __tsan_flush_memory(); + // Trigger a race to test flushing of the symbolizer cache. + Y = 2; + barrier_wait(&barrier); + pthread_join(t, NULL); + __atomic_fetch_add(&X, 1, __ATOMIC_SEQ_CST); + // Background runtime thread should do some flushes meanwhile. + sleep(2); + __tsan_flush_memory(); + fprintf(stderr, "DONE\n"); + return 0; +} + +// CHECK: WARNING: ThreadSanitizer: data race +// CHECK: DONE