aboutsummaryrefslogtreecommitdiff
path: root/lib/tsan/go/tsan_go.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tsan/go/tsan_go.cc')
-rw-r--r--lib/tsan/go/tsan_go.cc81
1 files changed, 70 insertions, 11 deletions
diff --git a/lib/tsan/go/tsan_go.cc b/lib/tsan/go/tsan_go.cc
index 4b3076c46ce7..360608a0cf1b 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