diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2016-04-27 12:30:48 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2016-04-27 12:30:48 +0000 |
commit | 3efe395788e17f9be556b2570fb0cd9a1ae93796 (patch) | |
tree | e1e706b5b00c4b4018cd55b67b41a8739f702db8 /compiler-rt/lib/tsan/go | |
parent | 15cec298e64872b693430214980a822ee2044a5d (diff) | |
download | bcm5719-llvm-3efe395788e17f9be556b2570fb0cd9a1ae93796.tar.gz bcm5719-llvm-3efe395788e17f9be556b2570fb0cd9a1ae93796.zip |
tsan: change tsan/Go interface for obtaining the current Processor
Current interface assumes that Go calls ProcWire/ProcUnwire
to establish the association between thread and proc.
With the wisdom of hindsight, this interface does not work
very well. I had to sprinkle Go scheduler with wire/unwire
calls, and any mistake leads to hard to debug crashes.
This is not something one wants to maintian.
Fortunately, there is a simpler solution. We can ask Go
runtime as to what is the current Processor, and that
question is very easy to answer on Go side.
Switch to such interface.
llvm-svn: 267703
Diffstat (limited to 'compiler-rt/lib/tsan/go')
-rw-r--r-- | compiler-rt/lib/tsan/go/test.c | 25 | ||||
-rw-r--r-- | compiler-rt/lib/tsan/go/tsan_go.cc | 47 |
2 files changed, 40 insertions, 32 deletions
diff --git a/compiler-rt/lib/tsan/go/test.c b/compiler-rt/lib/tsan/go/test.c index e59cca3ef96..51ccf29ead2 100644 --- a/compiler-rt/lib/tsan/go/test.c +++ b/compiler-rt/lib/tsan/go/test.c @@ -27,12 +27,21 @@ 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 *pc, void *p, unsigned long sz); -void __tsan_free(void *proc, void *p, unsigned long sz); +void __tsan_free(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); -void symbolize_cb(long cmd, void *ctx) {} +void *current_proc; + +void symbolize_cb(long cmd, void *ctx) { + switch (cmd) { + case 0: + if (current_proc == 0) + abort(); + *(void**)ctx = current_proc; + } +} char buf0[100<<10]; @@ -43,11 +52,11 @@ int main(void) { void *thr0 = 0; void *proc0 = 0; __tsan_init(&thr0, &proc0, symbolize_cb); + current_proc = proc0; char *buf = (char*)((unsigned long)buf0 + (64<<10) - 1 & ~((64<<10) - 1)); __tsan_map_shadow(buf, 4096); __tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10); - __tsan_free(proc0, buf, 10); - __tsan_free(thr0, buf, 10); + __tsan_free(buf, 10); __tsan_func_enter(thr0, (char*)&main + 1); __tsan_malloc(thr0, (char*)&barfoo + 1, buf, 10); __tsan_release(thr0, buf); @@ -57,8 +66,6 @@ int main(void) { void *thr2 = 0; __tsan_go_start(thr0, &thr2, (char*)&barfoo + 1); __tsan_func_exit(thr0); - __tsan_proc_unwire(proc0, thr0); - __tsan_proc_wire(proc0, thr1); __tsan_func_enter(thr1, (char*)&foobar + 1); __tsan_func_enter(thr1, (char*)&foobar + 1); __tsan_write(thr1, buf, (char*)&barfoo + 1); @@ -68,14 +75,14 @@ int main(void) { __tsan_go_end(thr1); void *proc1 = 0; __tsan_proc_create(&proc1); - __tsan_proc_wire(proc1, thr2); + current_proc = proc1; __tsan_func_enter(thr2, (char*)&foobar + 1); __tsan_read(thr2, buf, (char*)&barfoo + 1); - __tsan_free(proc1, buf, 10); + __tsan_free(buf, 10); __tsan_func_exit(thr2); __tsan_go_end(thr2); - __tsan_proc_destroy(proc0); __tsan_proc_destroy(proc1); + current_proc = proc0; __tsan_fini(); return 0; } diff --git a/compiler-rt/lib/tsan/go/tsan_go.cc b/compiler-rt/lib/tsan/go/tsan_go.cc index 390c1b48a71..bc0d5530433 100644 --- a/compiler-rt/lib/tsan/go/tsan_go.cc +++ b/compiler-rt/lib/tsan/go/tsan_go.cc @@ -40,8 +40,9 @@ void internal_free(void *p) { static void (*go_runtime_cb)(uptr cmd, void *ctx); enum { - CallbackSymbolizeCode = 0, - CallbackSymbolizeData = 1, + CallbackGetProc = 0, + CallbackSymbolizeCode = 1, + CallbackSymbolizeData = 2, }; struct SymbolizeCodeContext { @@ -109,11 +110,27 @@ ReportLocation *SymbolizeData(uptr addr) { } } -extern "C" { - static ThreadState *main_thr; static bool inited; +static Processor* get_cur_proc() { + if (UNLIKELY(!inited)) { + // Running Initialize(). + // We have not yet returned the Processor to Go, so we cannot ask it back. + // Currently, Initialize() does not use the Processor, so return nullptr. + return nullptr; + } + Processor *proc; + go_runtime_cb(CallbackGetProc, &proc); + return proc; +} + +Processor *ThreadState::proc() { + return get_cur_proc(); +} + +extern "C" { + static ThreadState *AllocGoroutine() { ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex, sizeof(ThreadState)); @@ -127,7 +144,7 @@ void __tsan_init(ThreadState **thrp, Processor **procp, ThreadState *thr = AllocGoroutine(); main_thr = *thrp = thr; Initialize(thr); - *procp = thr->proc; + *procp = thr->proc1; inited = true; } @@ -189,27 +206,19 @@ void __tsan_malloc(ThreadState *thr, uptr pc, uptr p, uptr sz) { MemoryResetRange(0, 0, (uptr)p, sz); } -void __tsan_free(Processor *proc, uptr p, uptr sz) { - ctx->metamap.FreeRange(proc, p, sz); +void __tsan_free(uptr p, uptr sz) { + ctx->metamap.FreeRange(get_cur_proc(), p, sz); } void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) { ThreadState *thr = AllocGoroutine(); *pthr = thr; int goid = ThreadCreate(parent, (uptr)pc, 0, true); - Processor *proc = parent->proc; - // Temporary borrow proc to handle goroutine start. - ProcUnwire(proc, parent); - ProcWire(proc, thr); ThreadStart(thr, goid, 0); - ProcUnwire(proc, thr); - ProcWire(proc, parent); } void __tsan_go_end(ThreadState *thr) { - Processor *proc = thr->proc; ThreadFinish(thr); - ProcUnwire(proc, thr); internal_free(thr); } @@ -221,14 +230,6 @@ void __tsan_proc_destroy(Processor *proc) { ProcDestroy(proc); } -void __tsan_proc_wire(Processor *proc, ThreadState *thr) { - ProcWire(proc, thr); -} - -void __tsan_proc_unwire(Processor *proc, ThreadState *thr) { - ProcUnwire(proc, thr); -} - void __tsan_acquire(ThreadState *thr, void *addr) { Acquire(thr, 0, (uptr)addr); } |