aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/cgo
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2016-05-26 17:47:03 -0700
committerIan Lance Taylor <iant@golang.org>2016-05-31 20:53:16 +0000
commit66736880ca2e50fc7c5428a171fbbe6d344a853b (patch)
tree419a3c55e891e5e0a9bee219be22dcc444857944 /src/runtime/cgo
parent0e13dbc1a91cbe00e3c83a55f56db69380fe8f68 (diff)
downloadgo-66736880ca2e50fc7c5428a171fbbe6d344a853b.tar.xz
runtime/cgo: add TSAN acquire/release calls
Add TSAN acquire/release calls to runtime/cgo to match the ones generated by cgo. This avoids a false positive race around the malloc memory used in runtime/cgo when other goroutines are simultaneously calling malloc and free from cgo. These new calls will only be used when building with CGO_CFLAGS and CGO_LDFLAGS set to -fsanitize=thread, which becomes a requirement to avoid all false positives when using TSAN. These are needed not just for runtime/cgo, but also for any runtime package that uses cgo (such as net and os/user). Add an unused attribute to the _cgo_tsan_acquire and _cgo_tsan_release functions, in case there are no actual cgo function calls. Add a test that checks that setting CGO_CFLAGS/CGO_LDFLAGS avoids a false positive report when using os/user. Change-Id: I0905c644ff7f003b6718aac782393fa219514c48 Reviewed-on: https://go-review.googlesource.com/23492 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Diffstat (limited to 'src/runtime/cgo')
-rw-r--r--src/runtime/cgo/gcc_linux_amd64.c2
-rw-r--r--src/runtime/cgo/gcc_util.c2
-rw-r--r--src/runtime/cgo/libcgo.h39
3 files changed, 43 insertions, 0 deletions
diff --git a/src/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c
index 50a7e6e078..0c34c66592 100644
--- a/src/runtime/cgo/gcc_linux_amd64.c
+++ b/src/runtime/cgo/gcc_linux_amd64.c
@@ -89,7 +89,9 @@ threadentry(void *v)
ThreadStart ts;
ts = *(ThreadStart*)v;
+ _cgo_tsan_acquire();
free(v);
+ _cgo_tsan_release();
/*
* Set specific keys.
diff --git a/src/runtime/cgo/gcc_util.c b/src/runtime/cgo/gcc_util.c
index 4111fe1195..99af021331 100644
--- a/src/runtime/cgo/gcc_util.c
+++ b/src/runtime/cgo/gcc_util.c
@@ -11,7 +11,9 @@ x_cgo_thread_start(ThreadStart *arg)
ThreadStart *ts;
/* Make our own copy that can persist after we return. */
+ _cgo_tsan_acquire();
ts = malloc(sizeof *ts);
+ _cgo_tsan_release();
if(ts == nil) {
fprintf(stderr, "runtime/cgo: out of memory in thread_start\n");
abort();
diff --git a/src/runtime/cgo/libcgo.h b/src/runtime/cgo/libcgo.h
index 6a484ad4a0..249d052edc 100644
--- a/src/runtime/cgo/libcgo.h
+++ b/src/runtime/cgo/libcgo.h
@@ -94,3 +94,42 @@ struct context_arg {
uintptr_t Context;
};
extern void (*x_cgo_context_function)(struct context_arg*);
+
+/*
+ * TSAN support. This is only useful when building with
+ * CGO_CFLAGS="-fsanitize=thread" CGO_LDFLAGS="-fsanitize=thread" go install
+ */
+#undef CGO_TSAN
+#if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+# define CGO_TSAN
+# endif
+#elif defined(__SANITIZE_THREAD__)
+# define CGO_TSAN
+#endif
+
+#ifdef CGO_TSAN
+
+// These must match the definitions in yesTsanProlog in cmd/cgo/out.go.
+
+long long _cgo_sync __attribute__ ((common));
+
+extern void __tsan_acquire(void*);
+extern void __tsan_release(void*);
+
+__attribute__ ((unused))
+static void _cgo_tsan_acquire() {
+ __tsan_acquire(&_cgo_sync);
+}
+
+__attribute__ ((unused))
+static void _cgo_tsan_release() {
+ __tsan_release(&_cgo_sync);
+}
+
+#else // !defined(CGO_TSAN)
+
+#define _cgo_tsan_acquire()
+#define _cgo_tsan_release()
+
+#endif // !defined(CGO_TSAN)