[compiler-rt] r280920 - [tsan] Support C++11 call_once in TSan on Darwin
Kuba Brecka via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 8 03:15:21 PDT 2016
Author: kuba.brecka
Date: Thu Sep 8 05:15:20 2016
New Revision: 280920
URL: http://llvm.org/viewvc/llvm-project?rev=280920&view=rev
Log:
[tsan] Support C++11 call_once in TSan on Darwin
This patch adds a wrapper for call_once, which uses an already-compiled helper __call_once with an atomic release which is invisible to TSan. To avoid false positives, the interceptor performs an explicit atomic release in the callback wrapper.
Differential Revision: https://reviews.llvm.org/D24188
Added:
compiler-rt/trunk/test/tsan/Darwin/libcxx-call-once.mm
Modified:
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc?rev=280920&r1=280919&r2=280920&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors_mac.cc Thu Sep 8 05:15:20 2016
@@ -327,6 +327,33 @@ STDCXX_INTERCEPTOR(void, _ZNSt3__119__sh
}
}
+namespace {
+struct call_once_callback_args {
+ void (*orig_func)(void *arg);
+ void *orig_arg;
+ void *flag;
+};
+
+void call_once_callback_wrapper(void *arg) {
+ call_once_callback_args *new_args = (call_once_callback_args *)arg;
+ new_args->orig_func(new_args->orig_arg);
+ __tsan_release(new_args->flag);
+}
+} // namespace
+
+// This adds a libc++ interceptor for:
+// void __call_once(volatile unsigned long&, void*, void(*)(void*));
+// C++11 call_once is implemented via an internal function __call_once which is
+// inside libc++.dylib, and the atomic release store inside it is thus
+// TSan-invisible. To avoid false positives, this interceptor wraps the callback
+// function and performs an explicit Release after the user code has run.
+STDCXX_INTERCEPTOR(void, _ZNSt3__111__call_onceERVmPvPFvS2_E, void *flag,
+ void *arg, void (*func)(void *arg)) {
+ call_once_callback_args new_args = {func, arg, flag};
+ REAL(_ZNSt3__111__call_onceERVmPvPFvS2_E)(flag, &new_args,
+ call_once_callback_wrapper);
+}
+
} // namespace __tsan
#endif // SANITIZER_MAC
Added: compiler-rt/trunk/test/tsan/Darwin/libcxx-call-once.mm
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/Darwin/libcxx-call-once.mm?rev=280920&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/Darwin/libcxx-call-once.mm (added)
+++ compiler-rt/trunk/test/tsan/Darwin/libcxx-call-once.mm Thu Sep 8 05:15:20 2016
@@ -0,0 +1,34 @@
+// RUN: %clangxx_tsan %s -o %t -framework Foundation -std=c++11
+// RUN: %env_tsan_opts=ignore_interceptors_accesses=1 %run %t 2>&1 | FileCheck %s
+
+#import <Foundation/Foundation.h>
+
+#import <iostream>
+#import <thread>
+
+long my_global;
+std::once_flag once_token;
+
+void thread_func() {
+ std::call_once(once_token, [] {
+ my_global = 17;
+ });
+
+ long val = my_global;
+ fprintf(stderr, "my_global = %ld\n", val);
+}
+
+int main(int argc, const char *argv[]) {
+ fprintf(stderr, "Hello world.\n");
+
+ std::thread t1(thread_func);
+ std::thread t2(thread_func);
+ t1.join();
+ t2.join();
+
+ fprintf(stderr, "Done.\n");
+}
+
+// CHECK: Hello world.
+// CHECK-NOT: WARNING: ThreadSanitizer
+// CHECK: Done.
More information about the llvm-commits
mailing list