summaryrefslogtreecommitdiff
path: root/lib/tsan/go
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2013-01-18 20:06:45 +0000
committerAndrew Turner <andrew@FreeBSD.org>2013-01-18 20:06:45 +0000
commit58aabf08b77d221489f10e274812ec60917c21a8 (patch)
treeb946f82269be87d83f086167c762c362e734c5bb /lib/tsan/go
parent37dfff057418e02f8e5322da12684dd927e3d881 (diff)
Notes
Diffstat (limited to 'lib/tsan/go')
-rwxr-xr-xlib/tsan/go/buildgo.sh57
-rw-r--r--lib/tsan/go/test.c2
-rw-r--r--lib/tsan/go/tsan_go.cc81
3 files changed, 100 insertions, 40 deletions
diff --git a/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh
index a0d2f6761b41c..a153afd6ee8eb 100755
--- a/lib/tsan/go/buildgo.sh
+++ b/lib/tsan/go/buildgo.sh
@@ -1,24 +1,12 @@
#!/bin/bash
set -e
-if [ "`uname -a | grep Linux`" != "" ]; then
- LINUX=1
- SUFFIX="linux_amd64"
-elif [ "`uname -a | grep Darwin`" != "" ]; then
- MAC=1
- SUFFIX="darwin_amd64"
-else
- echo Unknown platform
- exit 1
-fi
-
SRCS="
tsan_go.cc
../rtl/tsan_clock.cc
../rtl/tsan_flags.cc
../rtl/tsan_md5.cc
../rtl/tsan_mutex.cc
- ../rtl/tsan_printf.cc
../rtl/tsan_report.cc
../rtl/tsan_rtl.cc
../rtl/tsan_rtl_mutex.cc
@@ -31,48 +19,59 @@ SRCS="
../../sanitizer_common/sanitizer_common.cc
../../sanitizer_common/sanitizer_flags.cc
../../sanitizer_common/sanitizer_libc.cc
- ../../sanitizer_common/sanitizer_posix.cc
../../sanitizer_common/sanitizer_printf.cc
- ../../sanitizer_common/sanitizer_symbolizer.cc
"
-if [ "$LINUX" != "" ]; then
+if [ "`uname -a | grep Linux`" != "" ]; then
+ SUFFIX="linux_amd64"
+ OSCFLAGS="-fPIC -ffreestanding"
+ OSLDFLAGS="-lpthread -fPIC -fpie"
SRCS+="
../rtl/tsan_platform_linux.cc
+ ../../sanitizer_common/sanitizer_posix.cc
../../sanitizer_common/sanitizer_linux.cc
"
-elif [ "$MAC" != "" ]; then
- SRCS+="
- ../rtl/tsan_platform_mac.cc
- ../../sanitizer_common/sanitizer_mac.cc
- "
+elif [ "`uname -a | grep Darwin`" != "" ]; then
+ SUFFIX="darwin_amd64"
+ OSCFLAGS="-fPIC"
+ OSLDFLAGS="-lpthread -fPIC -fpie"
+ SRCS+="
+ ../rtl/tsan_platform_mac.cc
+ ../../sanitizer_common/sanitizer_posix.cc
+ ../../sanitizer_common/sanitizer_mac.cc
+ "
+elif [ "`uname -a | grep MINGW`" != "" ]; then
+ SUFFIX="windows_amd64"
+ OSCFLAGS="-Wno-error=attributes -Wno-attributes"
+ OSLDFLAGS=""
+ SRCS+="
+ ../rtl/tsan_platform_windows.cc
+ ../../sanitizer_common/sanitizer_win.cc
+ "
+else
+ echo Unknown platform
+ exit 1
fi
SRCS+=$ADD_SRCS
-#ASMS="../rtl/tsan_rtl_amd64.S"
rm -f gotsan.cc
for F in $SRCS; do
cat $F >> gotsan.cc
done
-FLAGS=" -I../rtl -I../.. -I../../sanitizer_common -fPIC -g -Wall -Werror -fno-exceptions -DTSAN_GO -DSANITIZER_GO -DTSAN_SHADOW_COUNT=4"
+FLAGS=" -I../rtl -I../.. -I../../sanitizer_common -I../../../include -m64 -Wall -Werror -fno-exceptions -DTSAN_GO -DSANITIZER_GO -DTSAN_SHADOW_COUNT=4 $OSCFLAGS"
if [ "$DEBUG" == "" ]; then
FLAGS+=" -DTSAN_DEBUG=0 -O3 -fomit-frame-pointer"
else
FLAGS+=" -DTSAN_DEBUG=1 -g"
fi
-if [ "$LINUX" != "" ]; then
- FLAGS+=" -ffreestanding"
-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
-gcc test.c race_$SUFFIX.syso -lpthread -o test
-TSAN_OPTIONS="exitcode=0" ./test
-
+gcc 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 a9a5b3dbfcad1..2414a1e9925f7 100644
--- a/lib/tsan/go/test.c
+++ b/lib/tsan/go/test.c
@@ -15,6 +15,7 @@
void __tsan_init();
void __tsan_fini();
+void __tsan_map_shadow(void *addr, unsigned long size);
void __tsan_go_start(int pgoid, int chgoid, void *pc);
void __tsan_go_end(int goid);
void __tsan_read(int goid, void *addr, void *pc);
@@ -35,6 +36,7 @@ char buf[10];
int main(void) {
__tsan_init();
+ __tsan_map_shadow(buf, sizeof(buf) + 4096);
__tsan_func_enter(0, &main);
__tsan_malloc(0, buf, 10, 0);
__tsan_release(0, buf);
diff --git a/lib/tsan/go/tsan_go.cc b/lib/tsan/go/tsan_go.cc
index 4b3076c46ce78..360608a0cf1ba 100644
--- a/lib/tsan/go/tsan_go.cc
+++ b/lib/tsan/go/tsan_go.cc
@@ -18,7 +18,9 @@
namespace __tsan {
-static ThreadState *goroutines[kMaxTid];
+const int kMaxGoroutinesEver = 128*1024;
+
+static ThreadState *goroutines[kMaxGoroutinesEver];
void InitializeInterceptors() {
}
@@ -33,7 +35,7 @@ bool IsExpectedReport(uptr addr, uptr size) {
void internal_start_thread(void(*func)(void*), void *arg) {
}
-ReportStack *SymbolizeData(uptr addr) {
+ReportLocation *SymbolizeData(uptr addr) {
return 0;
}
@@ -79,9 +81,14 @@ ReportStack *SymbolizeCode(uptr addr) {
extern "C" {
static void AllocGoroutine(int tid) {
- goroutines[tid] = (ThreadState*)internal_alloc(MBlockThreadContex,
+ if (tid >= kMaxGoroutinesEver) {
+ Printf("FATAL: Reached goroutine limit\n");
+ Die();
+ }
+ ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex,
sizeof(ThreadState));
- internal_memset(goroutines[tid], 0, sizeof(ThreadState));
+ internal_memset(thr, 0, sizeof(*thr));
+ goroutines[tid] = thr;
}
void __tsan_init() {
@@ -98,7 +105,11 @@ void __tsan_fini() {
thr->in_rtl++;
int res = Finalize(thr);
thr->in_rtl--;
- exit(res);
+ exit(res);
+}
+
+void __tsan_map_shadow(uptr addr, uptr size) {
+ MapShadow(addr, size);
}
void __tsan_read(int goid, void *addr, void *pc) {
@@ -111,6 +122,18 @@ void __tsan_write(int goid, void *addr, void *pc) {
MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, true);
}
+void __tsan_read_range(int goid, void *addr, uptr size, uptr step, void *pc) {
+ ThreadState *thr = goroutines[goid];
+ for (uptr i = 0; i < size; i += step)
+ MemoryAccess(thr, (uptr)pc, (uptr)addr + i, 0, false);
+}
+
+void __tsan_write_range(int goid, void *addr, uptr size, uptr step, void *pc) {
+ ThreadState *thr = goroutines[goid];
+ for (uptr i = 0; i < size; i += step)
+ MemoryAccess(thr, (uptr)pc, (uptr)addr + i, 0, true);
+}
+
void __tsan_func_enter(int goid, void *pc) {
ThreadState *thr = goroutines[goid];
FuncEntry(thr, (uptr)pc);
@@ -123,9 +146,10 @@ void __tsan_func_exit(int goid) {
void __tsan_malloc(int goid, void *p, uptr sz, void *pc) {
ThreadState *thr = goroutines[goid];
+ if (thr == 0) // probably before __tsan_init()
+ return;
thr->in_rtl++;
- MemoryResetRange(thr, (uptr)pc, (uptr)p, sz);
- MemoryAccessRange(thr, (uptr)pc, (uptr)p, sz, true);
+ MemoryRangeImitateWrite(thr, (uptr)pc, (uptr)p, sz);
thr->in_rtl--;
}
@@ -142,7 +166,7 @@ void __tsan_go_start(int pgoid, int chgoid, void *pc) {
thr->in_rtl++;
parent->in_rtl++;
int goid2 = ThreadCreate(parent, (uptr)pc, 0, true);
- ThreadStart(thr, goid2);
+ ThreadStart(thr, goid2, 0);
parent->in_rtl--;
thr->in_rtl--;
}
@@ -152,6 +176,8 @@ void __tsan_go_end(int goid) {
thr->in_rtl++;
ThreadFinish(thr);
thr->in_rtl--;
+ internal_free(thr);
+ goroutines[goid] = 0;
}
void __tsan_acquire(int goid, void *addr) {
@@ -159,7 +185,6 @@ void __tsan_acquire(int goid, void *addr) {
thr->in_rtl++;
Acquire(thr, 0, (uptr)addr);
thr->in_rtl--;
- //internal_free(thr);
}
void __tsan_release(int goid, void *addr) {
@@ -178,8 +203,42 @@ void __tsan_release_merge(int goid, void *addr) {
void __tsan_finalizer_goroutine(int goid) {
ThreadState *thr = goroutines[goid];
- ThreadFinalizerGoroutine(thr);
-}
+ AcquireGlobal(thr, 0);
+}
+
+#ifdef _WIN32
+// MinGW gcc emits calls to the function.
+void ___chkstk_ms(void) {
+// The implementation must be along the lines of:
+// .code64
+// PUBLIC ___chkstk_ms
+// //cfi_startproc()
+// ___chkstk_ms:
+// push rcx
+// //cfi_push(%rcx)
+// push rax
+// //cfi_push(%rax)
+// cmp rax, PAGE_SIZE
+// lea rcx, [rsp + 24]
+// jb l_LessThanAPage
+// .l_MoreThanAPage:
+// sub rcx, PAGE_SIZE
+// or rcx, 0
+// sub rax, PAGE_SIZE
+// cmp rax, PAGE_SIZE
+// ja l_MoreThanAPage
+// .l_LessThanAPage:
+// sub rcx, rax
+// or [rcx], 0
+// pop rax
+// //cfi_pop(%rax)
+// pop rcx
+// //cfi_pop(%rcx)
+// ret
+// //cfi_endproc()
+// END
+}
+#endif
} // extern "C"
} // namespace __tsan