summaryrefslogtreecommitdiff
path: root/lib/tsan/go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-01-31 07:48:43 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-01-31 07:48:43 +0000
commit6faa20f2441cd845d98cb390ae2bacca908537ee (patch)
tree6cffadd0cf8c22460366a038b9ed5e80a8f705f9 /lib/tsan/go
parent6bd82d398b0c1e66f957a8553a912c5aa54b9639 (diff)
downloadcompiler-rt-6faa20f2441cd845d98cb390ae2bacca908537ee.tar.gz
compiler-rt-6faa20f2441cd845d98cb390ae2bacca908537ee.tar.bz2
compiler-rt-6faa20f2441cd845d98cb390ae2bacca908537ee.tar.xz
tsan: switch to explicit thread contexts in Go (instead of monotonic goroutine ids)
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@174047 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/tsan/go')
-rw-r--r--lib/tsan/go/test.c46
-rw-r--r--lib/tsan/go/tsan_go.cc74
2 files changed, 51 insertions, 69 deletions
diff --git a/lib/tsan/go/test.c b/lib/tsan/go/test.c
index 2414a1e9..902dfc91 100644
--- a/lib/tsan/go/test.c
+++ b/lib/tsan/go/test.c
@@ -13,20 +13,20 @@
#include <stdio.h>
-void __tsan_init();
+void __tsan_init(void **thr);
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);
-void __tsan_write(int goid, void *addr, void *pc);
-void __tsan_func_enter(int goid, void *pc);
-void __tsan_func_exit(int goid);
-void __tsan_malloc(int goid, void *p, unsigned long sz, void *pc);
+void __tsan_go_start(void *thr, void **chthr, void *pc);
+void __tsan_go_end(void *thr);
+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_acquire(int goid, void *addr);
-void __tsan_release(int goid, void *addr);
-void __tsan_release_merge(int goid, void *addr);
+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;
@@ -35,19 +35,21 @@ int __tsan_symbolize(void *pc, char **img, char **rtn, char **file, int *l) {
char buf[10];
int main(void) {
- __tsan_init();
+ void *thr0 = 0;
+ __tsan_init(&thr0);
__tsan_map_shadow(buf, sizeof(buf) + 4096);
- __tsan_func_enter(0, &main);
- __tsan_malloc(0, buf, 10, 0);
- __tsan_release(0, buf);
- __tsan_release_merge(0, buf);
- __tsan_go_start(0, 1, 0);
- __tsan_write(1, buf, 0);
- __tsan_acquire(1, buf);
- __tsan_go_end(1);
- __tsan_read(0, buf, 0);
+ __tsan_func_enter(thr0, &main);
+ __tsan_malloc(thr0, buf, 10, 0);
+ __tsan_release(thr0, buf);
+ __tsan_release_merge(thr0, buf);
+ void *thr1 = 0;
+ __tsan_go_start(thr0, &thr1, 0);
+ __tsan_write(thr1, buf, 0);
+ __tsan_acquire(thr1, buf);
+ __tsan_go_end(thr1);
+ __tsan_read(thr0, buf, 0);
__tsan_free(buf);
- __tsan_func_exit(0);
+ __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 360608a0..77f600b8 100644
--- a/lib/tsan/go/tsan_go.cc
+++ b/lib/tsan/go/tsan_go.cc
@@ -18,10 +18,6 @@
namespace __tsan {
-const int kMaxGoroutinesEver = 128*1024;
-
-static ThreadState *goroutines[kMaxGoroutinesEver];
-
void InitializeInterceptors() {
}
@@ -80,20 +76,18 @@ ReportStack *SymbolizeCode(uptr addr) {
extern "C" {
-static void AllocGoroutine(int tid) {
- if (tid >= kMaxGoroutinesEver) {
- Printf("FATAL: Reached goroutine limit\n");
- Die();
- }
+static ThreadState *main_thr;
+
+static ThreadState *AllocGoroutine() {
ThreadState *thr = (ThreadState*)internal_alloc(MBlockThreadContex,
sizeof(ThreadState));
internal_memset(thr, 0, sizeof(*thr));
- goroutines[tid] = thr;
+ return thr;
}
-void __tsan_init() {
- AllocGoroutine(0);
- ThreadState *thr = goroutines[0];
+void __tsan_init(ThreadState **thrp) {
+ ThreadState *thr = AllocGoroutine();
+ main_thr = *thrp = thr;
thr->in_rtl++;
Initialize(thr);
thr->in_rtl--;
@@ -101,7 +95,7 @@ void __tsan_init() {
void __tsan_fini() {
// FIXME: Not necessary thread 0.
- ThreadState *thr = goroutines[0];
+ ThreadState *thr = main_thr;
thr->in_rtl++;
int res = Finalize(thr);
thr->in_rtl--;
@@ -112,40 +106,35 @@ void __tsan_map_shadow(uptr addr, uptr size) {
MapShadow(addr, size);
}
-void __tsan_read(int goid, void *addr, void *pc) {
- ThreadState *thr = goroutines[goid];
+void __tsan_read(ThreadState *thr, void *addr, void *pc) {
MemoryAccess(thr, (uptr)pc, (uptr)addr, 0, false);
}
-void __tsan_write(int goid, void *addr, void *pc) {
- ThreadState *thr = goroutines[goid];
+void __tsan_write(ThreadState *thr, 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];
+void __tsan_read_range(ThreadState *thr, void *addr, uptr size, uptr step,
+ void *pc) {
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];
+void __tsan_write_range(ThreadState *thr, void *addr, uptr size, uptr step,
+ void *pc) {
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];
+void __tsan_func_enter(ThreadState *thr, void *pc) {
FuncEntry(thr, (uptr)pc);
}
-void __tsan_func_exit(int goid) {
- ThreadState *thr = goroutines[goid];
+void __tsan_func_exit(ThreadState *thr) {
FuncExit(thr);
}
-void __tsan_malloc(int goid, void *p, uptr sz, void *pc) {
- ThreadState *thr = goroutines[goid];
+void __tsan_malloc(ThreadState *thr, void *p, uptr sz, void *pc) {
if (thr == 0) // probably before __tsan_init()
return;
thr->in_rtl++;
@@ -157,52 +146,43 @@ 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];
+void __tsan_go_start(ThreadState *parent, ThreadState **pthr, void *pc) {
+ ThreadState *thr = AllocGoroutine();
+ *pthr = thr;
thr->in_rtl++;
parent->in_rtl++;
- int goid2 = ThreadCreate(parent, (uptr)pc, 0, true);
- ThreadStart(thr, goid2, 0);
+ int goid = ThreadCreate(parent, (uptr)pc, 0, true);
+ ThreadStart(thr, goid, 0);
parent->in_rtl--;
thr->in_rtl--;
}
-void __tsan_go_end(int goid) {
- ThreadState *thr = goroutines[goid];
+void __tsan_go_end(ThreadState *thr) {
thr->in_rtl++;
ThreadFinish(thr);
thr->in_rtl--;
internal_free(thr);
- goroutines[goid] = 0;
}
-void __tsan_acquire(int goid, void *addr) {
- ThreadState *thr = goroutines[goid];
+void __tsan_acquire(ThreadState *thr, void *addr) {
thr->in_rtl++;
Acquire(thr, 0, (uptr)addr);
thr->in_rtl--;
}
-void __tsan_release(int goid, void *addr) {
- ThreadState *thr = goroutines[goid];
+void __tsan_release(ThreadState *thr, void *addr) {
thr->in_rtl++;
ReleaseStore(thr, 0, (uptr)addr);
thr->in_rtl--;
}
-void __tsan_release_merge(int goid, void *addr) {
- ThreadState *thr = goroutines[goid];
+void __tsan_release_merge(ThreadState *thr, void *addr) {
thr->in_rtl++;
Release(thr, 0, (uptr)addr);
thr->in_rtl--;
}
-void __tsan_finalizer_goroutine(int goid) {
- ThreadState *thr = goroutines[goid];
+void __tsan_finalizer_goroutine(ThreadState *thr) {
AcquireGlobal(thr, 0);
}