diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.inc b/compiler-rt/lib/tsan/rtl/tsan_flags.inc --- a/compiler-rt/lib/tsan/rtl/tsan_flags.inc +++ b/compiler-rt/lib/tsan/rtl/tsan_flags.inc @@ -43,6 +43,10 @@ bool, force_seq_cst_atomics, false, "If set, all atomics are effectively sequentially consistent (seq_cst), " "regardless of what user actually specified.") +TSAN_FLAG( + bool, force_background_thread, false, + "If set, eagerly launch a background thread for memory reclamation " + "instead of waiting for a user call to pthread_create."); TSAN_FLAG(bool, halt_on_error, false, "Exit after first reported error.") TSAN_FLAG(int, atexit_sleep_ms, 1000, "Sleep in main thread before exiting for that many ms " diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -698,6 +698,15 @@ OnInitialize(); } +#if !SANITIZER_GO +static bool UNUSED __local_tsan_dyninit = [] { + if (flags()->force_background_thread) { + MaybeSpawnBackgroundThread(); + } + return false; +}(); +#endif + void MaybeSpawnBackgroundThread() { // On MIPS, TSan initialization is run before // __pthread_initialize_minimal_internal() is finished, so we can not spawn diff --git a/compiler-rt/test/tsan/force_background_thread.cpp b/compiler-rt/test/tsan/force_background_thread.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/tsan/force_background_thread.cpp @@ -0,0 +1,25 @@ +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %env_tsan_opts=force_background_thread=0 %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_tsan -O1 %s -o %t && %deflake %env_tsan_opts=force_background_thread=1 %run %t 2>&1 | FileCheck %s +#include "test.h" +#include +#include +#include + +void *Thread(void *a) { + ((int *)a)[0]++; + barrier_wait(&barrier); + return NULL; +} + +int main() { + barrier_init(&barrier, 2); + int *p = new int(42); + pthread_t t; + pthread_create(&t, NULL, Thread, p); + barrier_wait(&barrier); + p[0]++; + pthread_join(t, NULL); + delete p; +} + +// CHECK: WARNING: ThreadSanitizer: data race