diff options
| author | Ian Lance Taylor <iant@golang.org> | 2016-05-26 17:47:03 -0700 |
|---|---|---|
| committer | Ian Lance Taylor <iant@golang.org> | 2016-05-31 20:53:16 +0000 |
| commit | 66736880ca2e50fc7c5428a171fbbe6d344a853b (patch) | |
| tree | 419a3c55e891e5e0a9bee219be22dcc444857944 /src/runtime/cgo | |
| parent | 0e13dbc1a91cbe00e3c83a55f56db69380fe8f68 (diff) | |
| download | go-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.c | 2 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_util.c | 2 | ||||
| -rw-r--r-- | src/runtime/cgo/libcgo.h | 39 |
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) |
