diff options
Diffstat (limited to 'lib/tsan/go/tsan_go.cc')
-rw-r--r-- | lib/tsan/go/tsan_go.cc | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/lib/tsan/go/tsan_go.cc b/lib/tsan/go/tsan_go.cc new file mode 100644 index 0000000..4b3076c --- /dev/null +++ b/lib/tsan/go/tsan_go.cc @@ -0,0 +1,185 @@ +//===-- tsan_go.cc --------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// ThreadSanitizer runtime for Go language. +// +//===----------------------------------------------------------------------===// + +#include "tsan_rtl.h" +#include "tsan_symbolize.h" +#include "sanitizer_common/sanitizer_common.h" +#include <stdlib.h> + +namespace __tsan { + +static ThreadState *goroutines[kMaxTid]; + +void InitializeInterceptors() { +} + +void InitializeDynamicAnnotations() { +} + +bool IsExpectedReport(uptr addr, uptr size) { + return false; +} + +void internal_start_thread(void(*func)(void*), void *arg) { +} + +ReportStack *SymbolizeData(uptr addr) { + return 0; +} + +ReportStack *NewReportStackEntry(uptr addr) { + ReportStack *ent = (ReportStack*)internal_alloc(MBlockReportStack, + sizeof(ReportStack)); + internal_memset(ent, 0, sizeof(*ent)); + ent->pc = addr; + return ent; +} + +void *internal_alloc(MBlockType typ, uptr sz) { + return InternalAlloc(sz); +} + +void internal_free(void *p) { + InternalFree(p); +} + +// 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); + } + return s; +} + +extern "C" { + +static void AllocGoroutine(int tid) { + goroutines[tid] = (ThreadState*)internal_alloc(MBlockThreadContex, + sizeof(ThreadState)); + internal_memset(goroutines[tid], 0, sizeof(ThreadState)); +} + +void __tsan_init() { + AllocGoroutine(0); + ThreadState *thr = goroutines[0]; + thr->in_rtl++; + Initialize(thr); + thr->in_rtl--; +} + +void __tsan_fini() { + // FIXME: Not necessary thread 0. + ThreadState *thr = goroutines[0]; + thr->in_rtl++; + int res = Finalize(thr); + thr->in_rtl--; + exit(res); +} + +void __tsan_read(int goid, void *addr, void *pc) { + ThreadState *thr = goroutines[goid]; + MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, false); +} + +void __tsan_write(int goid, void *addr, void *pc) { + ThreadState *thr = goroutines[goid]; + MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, true); +} + +void __tsan_func_enter(int goid, void *pc) { + ThreadState *thr = goroutines[goid]; + FuncEntry(thr, (uptr)pc); +} + +void __tsan_func_exit(int goid) { + ThreadState *thr = goroutines[goid]; + FuncExit(thr); +} + +void __tsan_malloc(int goid, void *p, uptr sz, void *pc) { + ThreadState *thr = goroutines[goid]; + thr->in_rtl++; + MemoryResetRange(thr, (uptr)pc, (uptr)p, sz); + MemoryAccessRange(thr, (uptr)pc, (uptr)p, sz, true); + thr->in_rtl--; +} + +void __tsan_free(void *p) { + (void)p; +} + +void __tsan_go_start(int pgoid, int chgoid, void *pc) { + if (chgoid == 0) + return; + AllocGoroutine(chgoid); + ThreadState *thr = goroutines[chgoid]; + ThreadState *parent = goroutines[pgoid]; + thr->in_rtl++; + parent->in_rtl++; + int goid2 = ThreadCreate(parent, (uptr)pc, 0, true); + ThreadStart(thr, goid2); + parent->in_rtl--; + thr->in_rtl--; +} + +void __tsan_go_end(int goid) { + ThreadState *thr = goroutines[goid]; + thr->in_rtl++; + ThreadFinish(thr); + thr->in_rtl--; +} + +void __tsan_acquire(int goid, void *addr) { + ThreadState *thr = goroutines[goid]; + thr->in_rtl++; + Acquire(thr, 0, (uptr)addr); + thr->in_rtl--; + //internal_free(thr); +} + +void __tsan_release(int goid, void *addr) { + ThreadState *thr = goroutines[goid]; + thr->in_rtl++; + ReleaseStore(thr, 0, (uptr)addr); + thr->in_rtl--; +} + +void __tsan_release_merge(int goid, void *addr) { + ThreadState *thr = goroutines[goid]; + thr->in_rtl++; + Release(thr, 0, (uptr)addr); + thr->in_rtl--; +} + +void __tsan_finalizer_goroutine(int goid) { + ThreadState *thr = goroutines[goid]; + ThreadFinalizerGoroutine(thr); +} + +} // extern "C" +} // namespace __tsan |