diff options
| author | Andrew Turner <andrew@FreeBSD.org> | 2013-01-18 20:06:45 +0000 |
|---|---|---|
| committer | Andrew Turner <andrew@FreeBSD.org> | 2013-01-18 20:06:45 +0000 |
| commit | 58aabf08b77d221489f10e274812ec60917c21a8 (patch) | |
| tree | b946f82269be87d83f086167c762c362e734c5bb /lib/tsan/go | |
| parent | 37dfff057418e02f8e5322da12684dd927e3d881 (diff) | |
Notes
Diffstat (limited to 'lib/tsan/go')
| -rwxr-xr-x | lib/tsan/go/buildgo.sh | 57 | ||||
| -rw-r--r-- | lib/tsan/go/test.c | 2 | ||||
| -rw-r--r-- | lib/tsan/go/tsan_go.cc | 81 |
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 |
