summaryrefslogtreecommitdiff
path: root/lib/tsan/go
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-01-07 19:55:37 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-01-07 19:55:37 +0000
commitca9211ecdede9bdedb812b2243a4abdb8dacd1b9 (patch)
tree9b19e801150082c33e9152275829a6ce90614b55 /lib/tsan/go
parent8ef50bf3d1c287b5013c3168de77a462dfce3495 (diff)
Diffstat (limited to 'lib/tsan/go')
-rw-r--r--lib/tsan/go/build.bat4
-rwxr-xr-xlib/tsan/go/buildgo.sh48
-rw-r--r--lib/tsan/go/test.c20
-rw-r--r--lib/tsan/go/tsan_go.cc138
4 files changed, 126 insertions, 84 deletions
diff --git a/lib/tsan/go/build.bat b/lib/tsan/go/build.bat
new file mode 100644
index 0000000000000..8f8087fc6352e
--- /dev/null
+++ b/lib/tsan/go/build.bat
@@ -0,0 +1,4 @@
+type tsan_go.cc ..\rtl\tsan_interface_atomic.cc ..\rtl\tsan_clock.cc ..\rtl\tsan_flags.cc ..\rtl\tsan_md5.cc ..\rtl\tsan_mutex.cc ..\rtl\tsan_report.cc ..\rtl\tsan_rtl.cc ..\rtl\tsan_rtl_mutex.cc ..\rtl\tsan_rtl_report.cc ..\rtl\tsan_rtl_thread.cc ..\rtl\tsan_stat.cc ..\rtl\tsan_suppressions.cc ..\rtl\tsan_sync.cc ..\rtl\tsan_stack_trace.cc ..\..\sanitizer_common\sanitizer_allocator.cc ..\..\sanitizer_common\sanitizer_common.cc ..\..\sanitizer_common\sanitizer_flags.cc ..\..\sanitizer_common\sanitizer_stacktrace.cc ..\..\sanitizer_common\sanitizer_libc.cc ..\..\sanitizer_common\sanitizer_printf.cc ..\..\sanitizer_common\sanitizer_suppressions.cc ..\..\sanitizer_common\sanitizer_thread_registry.cc ..\rtl\tsan_platform_windows.cc ..\..\sanitizer_common\sanitizer_win.cc ..\..\sanitizer_common\sanitizer_deadlock_detector1.cc ..\..\sanitizer_common\sanitizer_stackdepot.cc ..\..\sanitizer_common\sanitizer_persistent_allocator.cc > gotsan.cc
+
+gcc -c -o race_windows_amd64.syso gotsan.cc -I..\rtl -I..\.. -I..\..\sanitizer_common -I..\..\..\include -m64 -Wall -fno-exceptions -fno-rtti -DSANITIZER_GO -DTSAN_SHADOW_COUNT=4 -Wno-error=attributes -Wno-attributes -Wno-format -DTSAN_DEBUG=0 -O3 -fomit-frame-pointer
+
diff --git a/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh
index bd03fc0b65e05..4df2e96c5a8c9 100755
--- a/lib/tsan/go/buildgo.sh
+++ b/lib/tsan/go/buildgo.sh
@@ -1,10 +1,10 @@
-#!/bin/bash
set -e
SRCS="
tsan_go.cc
../rtl/tsan_clock.cc
../rtl/tsan_flags.cc
+ ../rtl/tsan_interface_atomic.cc
../rtl/tsan_md5.cc
../rtl/tsan_mutex.cc
../rtl/tsan_report.cc
@@ -12,43 +12,64 @@ SRCS="
../rtl/tsan_rtl_mutex.cc
../rtl/tsan_rtl_report.cc
../rtl/tsan_rtl_thread.cc
+ ../rtl/tsan_stack_trace.cc
../rtl/tsan_stat.cc
../rtl/tsan_suppressions.cc
../rtl/tsan_sync.cc
../../sanitizer_common/sanitizer_allocator.cc
../../sanitizer_common/sanitizer_common.cc
+ ../../sanitizer_common/sanitizer_deadlock_detector2.cc
../../sanitizer_common/sanitizer_flags.cc
../../sanitizer_common/sanitizer_libc.cc
+ ../../sanitizer_common/sanitizer_persistent_allocator.cc
../../sanitizer_common/sanitizer_printf.cc
../../sanitizer_common/sanitizer_suppressions.cc
../../sanitizer_common/sanitizer_thread_registry.cc
+ ../../sanitizer_common/sanitizer_stackdepot.cc
+ ../../sanitizer_common/sanitizer_stacktrace.cc
+ ../../sanitizer_common/sanitizer_symbolizer.cc
"
if [ "`uname -a | grep Linux`" != "" ]; then
SUFFIX="linux_amd64"
- OSCFLAGS="-fPIC -ffreestanding -Wno-maybe-uninitialized -Werror"
+ OSCFLAGS="-fPIC -ffreestanding -Wno-maybe-uninitialized -Wno-unused-const-variable -Werror -Wno-unknown-warning-option"
OSLDFLAGS="-lpthread -fPIC -fpie"
SRCS+="
../rtl/tsan_platform_linux.cc
../../sanitizer_common/sanitizer_posix.cc
../../sanitizer_common/sanitizer_posix_libcdep.cc
+ ../../sanitizer_common/sanitizer_procmaps_common.cc
+ ../../sanitizer_common/sanitizer_procmaps_linux.cc
../../sanitizer_common/sanitizer_linux.cc
- ../../sanitizer_common/sanitizer_linux_libcdep.cc
../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
"
+elif [ "`uname -a | grep FreeBSD`" != "" ]; then
+ SUFFIX="freebsd_amd64"
+ OSCFLAGS="-fno-strict-aliasing -fPIC -Werror"
+ OSLDFLAGS="-lpthread -fPIC -fpie"
+ SRCS+="
+ ../rtl/tsan_platform_linux.cc
+ ../../sanitizer_common/sanitizer_posix.cc
+ ../../sanitizer_common/sanitizer_posix_libcdep.cc
+ ../../sanitizer_common/sanitizer_procmaps_common.cc
+ ../../sanitizer_common/sanitizer_procmaps_freebsd.cc
+ ../../sanitizer_common/sanitizer_linux.cc
+ ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
+ "
elif [ "`uname -a | grep Darwin`" != "" ]; then
SUFFIX="darwin_amd64"
- OSCFLAGS="-fPIC"
+ OSCFLAGS="-fPIC -Wno-unused-const-variable -Wno-unknown-warning-option"
OSLDFLAGS="-lpthread -fPIC -fpie"
SRCS+="
../rtl/tsan_platform_mac.cc
- ../../sanitizer_common/sanitizer_posix.cc
../../sanitizer_common/sanitizer_mac.cc
+ ../../sanitizer_common/sanitizer_posix.cc
../../sanitizer_common/sanitizer_posix_libcdep.cc
+ ../../sanitizer_common/sanitizer_procmaps_mac.cc
"
elif [ "`uname -a | grep MINGW`" != "" ]; then
SUFFIX="windows_amd64"
- OSCFLAGS="-Wno-error=attributes -Wno-attributes"
+ OSCFLAGS="-Wno-error=attributes -Wno-attributes -Wno-unused-const-variable -Wno-unknown-warning-option"
OSLDFLAGS=""
SRCS+="
../rtl/tsan_platform_windows.cc
@@ -66,18 +87,17 @@ for F in $SRCS; do
cat $F >> gotsan.cc
done
-FLAGS=" -I../rtl -I../.. -I../../sanitizer_common -I../../../include -m64 -Wall -fno-exceptions -fno-rtti -DTSAN_GO -DSANITIZER_GO -DTSAN_SHADOW_COUNT=4 $OSCFLAGS"
+FLAGS=" -I../rtl -I../.. -I../../sanitizer_common -I../../../include -std=c++11 -m64 -Wall -fno-exceptions -fno-rtti -DSANITIZER_GO -DTSAN_SHADOW_COUNT=4 -DSANITIZER_DEADLOCK_DETECTOR_VERSION=2 $OSCFLAGS"
if [ "$DEBUG" == "" ]; then
- FLAGS+=" -DTSAN_DEBUG=0 -O3 -fomit-frame-pointer"
+ FLAGS+=" -DTSAN_DEBUG=0 -O3 -msse3 -fomit-frame-pointer"
else
FLAGS+=" -DTSAN_DEBUG=1 -g"
fi
-echo gcc gotsan.cc -S -o tmp.s $FLAGS $CFLAGS
-gcc gotsan.cc -S -o tmp.s $FLAGS $CFLAGS
-cat tmp.s $ASMS > gotsan.s
-echo as gotsan.s -o race_$SUFFIX.syso
-as gotsan.s -o race_$SUFFIX.syso
+CC=${CC:-gcc}
+
+echo $CC gotsan.cc -c -o race_$SUFFIX.syso $FLAGS $CFLAGS
+$CC gotsan.cc -c -o race_$SUFFIX.syso $FLAGS $CFLAGS
-gcc test.c race_$SUFFIX.syso -m64 -o test $OSLDFLAGS
+$CC test.c race_$SUFFIX.syso -m64 -o test $OSLDFLAGS
GORACE="exitcode=0 atexit_sleep_ms=0" ./test
diff --git a/lib/tsan/go/test.c b/lib/tsan/go/test.c
index 859b35d348e89..94433f1b8c221 100644
--- a/lib/tsan/go/test.c
+++ b/lib/tsan/go/test.c
@@ -13,7 +13,7 @@
#include <stdio.h>
-void __tsan_init(void **thr);
+void __tsan_init(void **thr, void (*cb)(void*));
void __tsan_fini();
void __tsan_map_shadow(void *addr, unsigned long size);
void __tsan_go_start(void *thr, void **chthr, void *pc);
@@ -22,27 +22,26 @@ void __tsan_read(void *thr, void *addr, void *pc);
void __tsan_write(void *thr, void *addr, void *pc);
void __tsan_func_enter(void *thr, void *pc);
void __tsan_func_exit(void *thr);
-void __tsan_malloc(void *thr, void *p, unsigned long sz, void *pc);
-void __tsan_free(void *p);
+void __tsan_malloc(void *p, unsigned long sz);
void __tsan_acquire(void *thr, void *addr);
void __tsan_release(void *thr, void *addr);
void __tsan_release_merge(void *thr, void *addr);
-int __tsan_symbolize(void *pc, char **img, char **rtn, char **file, int *l) {
- return 0;
-}
+void symbolize_cb(void *ctx) {}
-char buf[10];
+char buf0[100<<10];
void foobar() {}
void barfoo() {}
int main(void) {
void *thr0 = 0;
- __tsan_init(&thr0);
- __tsan_map_shadow(buf, sizeof(buf) + 4096);
+ char *buf = (char*)((unsigned long)buf0 + (64<<10) - 1 & ~((64<<10) - 1));
+ __tsan_malloc(buf, 10);
+ __tsan_init(&thr0, symbolize_cb);
+ __tsan_map_shadow(buf, 4096);
__tsan_func_enter(thr0, (char*)&main + 1);
- __tsan_malloc(thr0, buf, 10, 0);
+ __tsan_malloc(buf, 10);
__tsan_release(thr0, buf);
__tsan_release_merge(thr0, buf);
void *thr1 = 0;
@@ -60,7 +59,6 @@ int main(void) {
__tsan_read(thr2, buf, (char*)&barfoo + 1);
__tsan_func_exit(thr2);
__tsan_go_end(thr2);
- __tsan_free(buf);
__tsan_func_exit(thr0);
__tsan_fini();
return 0;
diff --git a/lib/tsan/go/tsan_go.cc b/lib/tsan/go/tsan_go.cc
index df54bb8e216cd..cccf72cedd27e 100644
--- a/lib/tsan/go/tsan_go.cc
+++ b/lib/tsan/go/tsan_go.cc
@@ -28,19 +28,15 @@ bool IsExpectedReport(uptr addr, uptr size) {
return false;
}
-void internal_start_thread(void(*func)(void*), void *arg) {
+void *internal_start_thread(void(*func)(void*), void *arg) {
+ return 0;
}
-ReportLocation *SymbolizeData(uptr addr) {
- return 0;
+void internal_join_thread(void *th) {
}
-ReportStack *NewReportStackEntry(uptr addr) {
- ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack,
- sizeof(ReportStack));
- internal_memset(ent, 0, sizeof(*ent));
- ent->pc = addr;
- return ent;
+ReportLocation *SymbolizeData(uptr addr) {
+ return 0;
}
void *internal_alloc(MBlockType typ, uptr sz) {
@@ -51,25 +47,31 @@ void internal_free(void *p) {
InternalFree(p);
}
+struct SymbolizeContext {
+ uptr pc;
+ char *func;
+ char *file;
+ uptr line;
+ uptr off;
+ uptr res;
+};
+
// Callback into Go.
-extern "C" int __tsan_symbolize(uptr pc, char **func, char **file,
- int *line, int *off);
-
-ReportStack *SymbolizeCode(uptr addr) {
- ReportStack *s = (ReportStack*)internal_alloc(MBlockReportStack,
- sizeof(ReportStack));
- internal_memset(s, 0, sizeof(*s));
- s->pc = addr;
- char *func = 0, *file = 0;
- int line = 0, off = 0;
- if (__tsan_symbolize(addr, &func, &file, &line, &off)) {
- s->offset = off;
- s->func = internal_strdup(func ? func : "??");
- s->file = internal_strdup(file ? file : "-");
- s->line = line;
- s->col = 0;
- free(func);
- free(file);
+static void (*symbolize_cb)(SymbolizeContext *ctx);
+
+SymbolizedStack *SymbolizeCode(uptr addr) {
+ SymbolizedStack *s = SymbolizedStack::New(addr);
+ SymbolizeContext ctx;
+ internal_memset(&ctx, 0, sizeof(ctx));
+ ctx.pc = addr;
+ symbolize_cb(&ctx);
+ if (ctx.res) {
+ AddressInfo &info = s->info;
+ info.module_offset = ctx.off;
+ info.function = internal_strdup(ctx.func ? ctx.func : "??");
+ info.file = internal_strdup(ctx.file ? ctx.file : "-");
+ info.line = ctx.line;
+ info.column = 0;
}
return s;
}
@@ -77,6 +79,7 @@ ReportStack *SymbolizeCode(uptr addr) {
extern "C" {
static ThreadState *main_thr;
+static bool inited;
static ThreadState *AllocGoroutine() {
ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex,
@@ -85,20 +88,18 @@ static ThreadState *AllocGoroutine() {
return thr;
}
-void __tsan_init(ThreadState **thrp) {
+void __tsan_init(ThreadState **thrp, void (*cb)(SymbolizeContext *cb)) {
+ symbolize_cb = cb;
ThreadState *thr = AllocGoroutine();
main_thr = *thrp = thr;
- thr->in_rtl++;
Initialize(thr);
- thr->in_rtl--;
+ inited = true;
}
void __tsan_fini() {
// FIXME: Not necessary thread 0.
ThreadState *thr = main_thr;
- thr->in_rtl++;
int res = Finalize(thr);
- thr->in_rtl--;
exit(res);
}
@@ -110,19 +111,31 @@ void __tsan_read(ThreadState *thr, void *addr, void *pc) {
MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1);
}
+void __tsan_read_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {
+ if (callpc != 0)
+ FuncEntry(thr, callpc);
+ MemoryRead(thr, (uptr)pc, (uptr)addr, kSizeLog1);
+ if (callpc != 0)
+ FuncExit(thr);
+}
+
void __tsan_write(ThreadState *thr, void *addr, void *pc) {
MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1);
}
-void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr step,
- void *pc) {
- (void)step;
+void __tsan_write_pc(ThreadState *thr, void *addr, uptr callpc, uptr pc) {
+ if (callpc != 0)
+ FuncEntry(thr, callpc);
+ MemoryWrite(thr, (uptr)pc, (uptr)addr, kSizeLog1);
+ if (callpc != 0)
+ FuncExit(thr);
+}
+
+void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr pc) {
MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, false);
}
-void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr step,
- void *pc) {
- (void)step;
+void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr pc) {
MemoryAccessRange(thr, (uptr)pc, (uptr)addr, size, true);
}
@@ -134,58 +147,65 @@ void __tsan_func_exit(ThreadState *thr) {
FuncExit(thr);
}
-void __tsan_malloc(ThreadState *thr, void *p, uptr sz, void *pc) {
- if (thr == 0) // probably before __tsan_init()
+void __tsan_malloc(void *p, uptr sz) {
+ if (!inited)
return;
- thr->in_rtl++;
- MemoryResetRange(thr, (uptr)pc, (uptr)p, sz);
- thr->in_rtl--;
-}
-
-void __tsan_free(void *p) {
- (void)p;
+ MemoryResetRange(0, 0, (uptr)p, sz);
}
void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {
ThreadState *thr = AllocGoroutine();
*pthr = thr;
- thr->in_rtl++;
- parent->in_rtl++;
int goid = ThreadCreate(parent, (uptr)pc, 0, true);
ThreadStart(thr, goid, 0);
- parent->in_rtl--;
- thr->in_rtl--;
}
void __tsan_go_end(ThreadState *thr) {
- thr->in_rtl++;
ThreadFinish(thr);
- thr->in_rtl--;
internal_free(thr);
}
void __tsan_acquire(ThreadState *thr, void *addr) {
- thr->in_rtl++;
Acquire(thr, 0, (uptr)addr);
- thr->in_rtl--;
}
void __tsan_release(ThreadState *thr, void *addr) {
- thr->in_rtl++;
ReleaseStore(thr, 0, (uptr)addr);
- thr->in_rtl--;
}
void __tsan_release_merge(ThreadState *thr, void *addr) {
- thr->in_rtl++;
Release(thr, 0, (uptr)addr);
- thr->in_rtl--;
}
void __tsan_finalizer_goroutine(ThreadState *thr) {
AcquireGlobal(thr, 0);
}
+void __tsan_mutex_before_lock(ThreadState *thr, uptr addr, uptr write) {
+}
+
+void __tsan_mutex_after_lock(ThreadState *thr, uptr addr, uptr write) {
+ if (write)
+ MutexLock(thr, 0, addr);
+ else
+ MutexReadLock(thr, 0, addr);
+}
+
+void __tsan_mutex_before_unlock(ThreadState *thr, uptr addr, uptr write) {
+ if (write)
+ MutexUnlock(thr, 0, addr);
+ else
+ MutexReadUnlock(thr, 0, addr);
+}
+
+void __tsan_go_ignore_sync_begin(ThreadState *thr) {
+ ThreadIgnoreSyncBegin(thr, 0);
+}
+
+void __tsan_go_ignore_sync_end(ThreadState *thr) {
+ ThreadIgnoreSyncEnd(thr, 0);
+}
+
} // extern "C"
} // namespace __tsan